From cc210364486dd3fb4bb58b98b1e1ba9cf594472e Mon Sep 17 00:00:00 2001 From: Clippy Bot Date: Tue, 23 Jun 2026 18:47:23 +0000 Subject: [PATCH] fix(clippy): apply auto-fixable linting suggestions --- .../memory/feedback_widget_decomposition.md | 22 +- .gitignore | 12 +- .woodpecker/server-audit.yaml | 50 +- .woodpecker/server-clippy-fix.yaml | 90 +- .woodpecker/server-lint.yaml | 48 +- .woodpecker/server-test.yaml | 52 +- .woodpecker/server-vet.yaml | 50 +- .woodpecker/useragent-analyze.yaml | 34 +- AGENTS.md | 298 +- CLAUDE.md | 2 +- LICENSE | 380 +- README.md | 24 +- app/.dart_tool/extension_discovery/README.md | 62 +- app/.dart_tool/package_config.json | 356 +- app/.dart_tool/package_graph.json | 458 +- .../ephemeral/Flutter-Generated.xcconfig | 22 +- .../ephemeral/flutter_export_environment.sh | 24 +- docs/ARCHITECTURE.md | 668 +- docs/IMPLEMENTATION.md | 452 +- .../2026-03-28-grant-creation-refactor.md | 2616 +- .../plans/2026-03-28-grant-grid-view.md | 1642 +- .../2026-03-28-grant-grid-view-design.md | 340 +- mise.toml | 48 +- protobufs/arbiter.proto | 32 +- protobufs/client.proto | 50 +- protobufs/client/auth.proto | 86 +- protobufs/client/evm.proto | 38 +- protobufs/client/vault.proto | 36 +- protobufs/evm.proto | 306 +- protobufs/operator.proto | 56 +- protobufs/operator/auth.proto | 82 +- protobufs/operator/evm.proto | 66 +- protobufs/operator/sdk_client.proto | 200 +- protobufs/operator/vault/bootstrap.proto | 48 +- protobufs/operator/vault/unseal.proto | 74 +- protobufs/operator/vault/vault.proto | 48 +- protobufs/shared/client.proto | 18 +- protobufs/shared/evm.proto | 148 +- protobufs/shared/vault.proto | 22 +- scripts/gen_erc20_registry.py | 300 +- server/.cargo/audit.toml | 26 +- server/.cargo/config.toml | 4 +- server/.cargo/mutants.toml | 2 +- server/.gitignore | 2 +- server/Cargo.lock | 12694 ++++---- server/Cargo.toml | 342 +- server/clippy.toml | 56 +- server/crates/arbiter-client/Cargo.toml | 58 +- server/crates/arbiter-client/src/auth.rs | 320 +- .../arbiter-client/src/bin/test_connect.rs | 88 +- server/crates/arbiter-client/src/client.rs | 202 +- server/crates/arbiter-client/src/lib.rs | 24 +- server/crates/arbiter-client/src/storage.rs | 268 +- server/crates/arbiter-client/src/transport.rs | 82 +- .../crates/arbiter-client/src/wallets/evm.rs | 394 +- .../crates/arbiter-client/src/wallets/mod.rs | 4 +- server/crates/arbiter-crypto/.gitignore | 2 +- server/crates/arbiter-crypto/Cargo.toml | 50 +- server/crates/arbiter-crypto/src/authn/mod.rs | 4 +- server/crates/arbiter-crypto/src/authn/v1.rs | 504 +- server/crates/arbiter-crypto/src/hashing.rs | 224 +- server/crates/arbiter-crypto/src/lib.rs | 14 +- server/crates/arbiter-crypto/src/safecell.rs | 236 +- server/crates/arbiter-macros/Cargo.toml | 38 +- server/crates/arbiter-macros/src/hashable.rs | 262 +- server/crates/arbiter-macros/src/lib.rs | 20 +- server/crates/arbiter-macros/src/utils.rs | 48 +- server/crates/arbiter-proto/Cargo.toml | 70 +- server/crates/arbiter-proto/build.rs | 42 +- server/crates/arbiter-proto/src/lib.rs | 168 +- server/crates/arbiter-proto/src/transport.rs | 436 +- .../arbiter-proto/src/transport/grpc.rs | 212 +- server/crates/arbiter-proto/src/url.rs | 256 +- server/crates/arbiter-server/Cargo.toml | 122 +- server/crates/arbiter-server/diesel.toml | 18 +- .../2026-02-14-171124-0000_init/down.sql | 2 +- .../2026-02-14-171124-0000_init/up.sql | 412 +- .../arbiter-server/src/actors/bootstrap.rs | 196 +- .../arbiter-server/src/actors/evm/mod.rs | 520 +- .../client_connect_approval.rs | 254 +- .../src/actors/flow_coordinator/mod.rs | 228 +- .../crates/arbiter-server/src/actors/mod.rs | 118 +- .../src/actors/operator_registry.rs | 122 +- .../arbiter-server/src/actors/vault/mod.rs | 924 +- .../crates/arbiter-server/src/context/mod.rs | 114 +- .../crates/arbiter-server/src/context/tls.rs | 514 +- .../src/crypto/encryption/mod.rs | 6 +- .../src/crypto/encryption/v1.rs | 204 +- .../src/crypto/integrity/mod.rs | 6 +- .../arbiter-server/src/crypto/integrity/v1.rs | 668 +- .../crates/arbiter-server/src/crypto/mod.rs | 310 +- server/crates/arbiter-server/src/db/mod.rs | 312 +- server/crates/arbiter-server/src/db/models.rs | 812 +- server/crates/arbiter-server/src/db/schema.rs | 474 +- server/crates/arbiter-server/src/evm/abi.rs | 168 +- server/crates/arbiter-server/src/evm/mod.rs | 1752 +- .../crates/arbiter-server/src/evm/policies.rs | 444 +- .../src/evm/policies/ether_transfer/mod.rs | 718 +- .../src/evm/policies/ether_transfer/tests.rs | 860 +- .../src/evm/policies/token_transfers/mod.rs | 816 +- .../src/evm/policies/token_transfers/tests.rs | 1028 +- .../arbiter-server/src/evm/safe_signer.rs | 388 +- server/crates/arbiter-server/src/evm/utils.rs | 52 +- .../crates/arbiter-server/src/grpc/client.rs | 230 +- .../arbiter-server/src/grpc/client/auth.rs | 438 +- .../arbiter-server/src/grpc/client/evm.rs | 174 +- .../arbiter-server/src/grpc/client/inbound.rs | 2 +- .../src/grpc/client/outbound.rs | 2 +- .../arbiter-server/src/grpc/client/vault.rs | 94 +- .../crates/arbiter-server/src/grpc/common.rs | 4 +- .../arbiter-server/src/grpc/common/inbound.rs | 70 +- .../src/grpc/common/outbound.rs | 242 +- server/crates/arbiter-server/src/grpc/mod.rs | 150 +- .../arbiter-server/src/grpc/operator.rs | 290 +- .../arbiter-server/src/grpc/operator/auth.rs | 368 +- .../arbiter-server/src/grpc/operator/evm.rs | 480 +- .../src/grpc/operator/inbound.rs | 348 +- .../src/grpc/operator/outbound.rs | 222 +- .../src/grpc/operator/sdk_client.rs | 396 +- .../arbiter-server/src/grpc/operator/vault.rs | 118 +- .../src/grpc/operator/vault_gate.rs | 158 +- .../src/grpc/operator/vault_gate/inbound.rs | 258 +- .../src/grpc/operator/vault_gate/outbound.rs | 230 +- .../src/grpc/request_tracker.rs | 52 +- server/crates/arbiter-server/src/lib.rs | 40 +- server/crates/arbiter-server/src/main.rs | 114 +- .../arbiter-server/src/peers/client/auth.rs | 708 +- .../arbiter-server/src/peers/client/mod.rs | 112 +- .../src/peers/client/session.rs | 236 +- server/crates/arbiter-server/src/peers/mod.rs | 4 +- .../src/peers/operator/auth/mod.rs | 214 +- .../src/peers/operator/auth/state.rs | 392 +- .../arbiter-server/src/peers/operator/mod.rs | 370 +- .../src/peers/operator/session/handlers.rs | 546 +- .../src/peers/operator/session/mod.rs | 322 +- .../src/peers/operator/vault_gate/mod.rs | 576 +- .../src/peers/operator/vault_gate/state.rs | 22 +- server/crates/arbiter-server/src/utils.rs | 32 +- server/crates/arbiter-server/tests/client.rs | 8 +- .../arbiter-server/tests/client/auth.rs | 816 +- .../crates/arbiter-server/tests/common/mod.rs | 180 +- .../crates/arbiter-server/tests/operator.rs | 12 +- .../arbiter-server/tests/operator/auth.rs | 1016 +- .../arbiter-server/tests/operator/unseal.rs | 334 +- server/crates/arbiter-server/tests/vault.rs | 16 +- .../arbiter-server/tests/vault/concurrency.rs | 354 +- .../arbiter-server/tests/vault/lifecycle.rs | 282 +- .../arbiter-server/tests/vault/storage.rs | 322 +- .../crates/arbiter-tokens-registry/Cargo.toml | 22 +- .../arbiter-tokens-registry/src/evm/mod.rs | 2 +- .../src/evm/nonfungible.rs | 26 +- .../arbiter-tokens-registry/src/evm/tokens.rs | 26496 ++++++++-------- .../crates/arbiter-tokens-registry/src/lib.rs | 2 +- server/rules/safecell/new-inline.yaml | 18 +- server/rules/safecell/read-inline.yaml | 32 +- server/rules/safecell/write-inline.yaml | 24 +- server/sgconfig.yml | 4 +- server/supply-chain/audits.toml | 1986 +- server/supply-chain/config.toml | 908 +- server/supply-chain/imports.lock | 7264 ++--- useragent/.gitignore | 90 +- useragent/.metadata | 78 +- useragent/README.md | 32 +- useragent/analysis_options.yaml | 56 +- useragent/android/.gitignore | 28 +- useragent/android/app/build.gradle.kts | 88 +- .../android/app/src/debug/AndroidManifest.xml | 14 +- .../android/app/src/main/AndroidManifest.xml | 90 +- .../com/example/useragent/MainActivity.kt | 10 +- .../res/drawable-v21/launch_background.xml | 24 +- .../main/res/drawable/launch_background.xml | 24 +- .../app/src/main/res/values-night/styles.xml | 36 +- .../app/src/main/res/values/styles.xml | 36 +- .../app/src/profile/AndroidManifest.xml | 14 +- useragent/android/build.gradle.kts | 48 +- useragent/android/gradle.properties | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 10 +- useragent/android/settings.gradle.kts | 52 +- useragent/flutter_rust_bridge.yaml | 4 +- .../lib/features/callouts/active_callout.dart | 32 +- .../callouts/active_callout.freezed.dart | 608 +- .../lib/features/callouts/callout_event.dart | 46 +- .../callouts/callout_event.freezed.dart | 1204 +- .../features/callouts/callout_manager.dart | 114 +- .../features/callouts/callout_manager.g.dart | 134 +- .../lib/features/callouts/show_callout.dart | 198 +- .../features/callouts/show_callout_list.dart | 442 +- .../callouts/types/sdk_connect_approve.dart | 124 +- .../callouts/types/sdk_connect_approve.g.dart | 100 +- .../lib/features/connection/arbiter_url.dart | 116 +- useragent/lib/features/connection/auth.dart | 340 +- .../lib/features/connection/connection.dart | 272 +- useragent/lib/features/connection/evm.dart | 134 +- .../lib/features/connection/evm/grants.dart | 204 +- .../connection/evm/wallet_access.dart | 172 +- .../connection/server_info_storage.dart | 124 +- .../connection/server_info_storage.g.dart | 42 +- useragent/lib/features/connection/vault.dart | 320 +- .../lib/features/identity/hazmat_mldsa.dart | 142 +- .../lib/features/identity/pk_manager.dart | 22 +- useragent/lib/main.dart | 78 +- useragent/lib/proto/arbiter.pb.dart | 176 +- useragent/lib/proto/arbiter.pbenum.dart | 22 +- useragent/lib/proto/arbiter.pbgrpc.dart | 180 +- useragent/lib/proto/arbiter.pbjson.dart | 60 +- useragent/lib/proto/client.pb.dart | 528 +- useragent/lib/proto/client.pbenum.dart | 22 +- useragent/lib/proto/client.pbjson.dart | 232 +- useragent/lib/proto/client/auth.pb.dart | 796 +- useragent/lib/proto/client/auth.pbenum.dart | 104 +- useragent/lib/proto/client/auth.pbjson.dart | 308 +- useragent/lib/proto/client/evm.pb.dart | 416 +- useragent/lib/proto/client/evm.pbenum.dart | 22 +- useragent/lib/proto/client/evm.pbjson.dart | 172 +- useragent/lib/proto/client/vault.pb.dart | 322 +- useragent/lib/proto/client/vault.pbenum.dart | 22 +- useragent/lib/proto/client/vault.pbjson.dart | 128 +- useragent/lib/proto/evm.pb.dart | 3528 +- useragent/lib/proto/evm.pbenum.dart | 80 +- useragent/lib/proto/evm.pbjson.dart | 1300 +- useragent/lib/proto/shared/client.pb.dart | 198 +- useragent/lib/proto/shared/client.pbenum.dart | 22 +- useragent/lib/proto/shared/client.pbjson.dart | 104 +- useragent/lib/proto/shared/evm.pb.dart | 1890 +- useragent/lib/proto/shared/evm.pbenum.dart | 22 +- useragent/lib/proto/shared/evm.pbjson.dart | 684 +- useragent/lib/proto/shared/vault.pb.dart | 34 +- useragent/lib/proto/shared/vault.pbenum.dart | 92 +- useragent/lib/proto/shared/vault.pbjson.dart | 68 +- useragent/lib/proto/user_agent.pb.dart | 606 +- useragent/lib/proto/user_agent.pbenum.dart | 22 +- useragent/lib/proto/user_agent.pbjson.dart | 258 +- useragent/lib/proto/user_agent/auth.pb.dart | 788 +- .../lib/proto/user_agent/auth.pbenum.dart | 104 +- .../lib/proto/user_agent/auth.pbjson.dart | 318 +- useragent/lib/proto/user_agent/evm.pb.dart | 864 +- .../lib/proto/user_agent/evm.pbenum.dart | 22 +- .../lib/proto/user_agent/evm.pbjson.dart | 380 +- .../lib/proto/user_agent/sdk_client.pb.dart | 2394 +- .../proto/user_agent/sdk_client.pbenum.dart | 92 +- .../proto/user_agent/sdk_client.pbjson.dart | 876 +- .../proto/user_agent/vault/bootstrap.pb.dart | 442 +- .../user_agent/vault/bootstrap.pbenum.dart | 88 +- .../user_agent/vault/bootstrap.pbjson.dart | 178 +- .../lib/proto/user_agent/vault/unseal.pb.dart | 784 +- .../proto/user_agent/vault/unseal.pbenum.dart | 86 +- .../proto/user_agent/vault/unseal.pbjson.dart | 288 +- .../lib/proto/user_agent/vault/vault.pb.dart | 470 +- .../proto/user_agent/vault/vault.pbenum.dart | 22 +- .../proto/user_agent/vault/vault.pbjson.dart | 210 +- .../providers/connection/bootstrap_token.dart | 50 +- .../connection/bootstrap_token.g.dart | 124 +- .../connection/connection_manager.dart | 92 +- .../connection/connection_manager.g.dart | 108 +- useragent/lib/providers/evm/evm.dart | 92 +- useragent/lib/providers/evm/evm.g.dart | 110 +- useragent/lib/providers/evm/evm_grants.dart | 210 +- .../lib/providers/evm/evm_grants.freezed.dart | 560 +- useragent/lib/providers/evm/evm_grants.g.dart | 108 +- useragent/lib/providers/key.dart | 118 +- useragent/lib/providers/key.g.dart | 188 +- .../lib/providers/sdk_clients/details.dart | 38 +- .../lib/providers/sdk_clients/details.g.dart | 170 +- useragent/lib/providers/sdk_clients/list.dart | 78 +- .../lib/providers/sdk_clients/list.g.dart | 102 +- .../providers/sdk_clients/wallet_access.dart | 348 +- .../sdk_clients/wallet_access.g.dart | 560 +- .../sdk_clients/wallet_access_list.dart | 44 +- .../sdk_clients/wallet_access_list.g.dart | 102 +- useragent/lib/providers/server_info.dart | 106 +- useragent/lib/providers/server_info.g.dart | 204 +- useragent/lib/providers/vault_state.dart | 74 +- useragent/lib/providers/vault_state.g.dart | 98 +- useragent/lib/router.dart | 54 +- useragent/lib/router.gr.dart | 646 +- useragent/lib/screens/bootstrap.dart | 78 +- .../lib/screens/callouts/sdk_connect.dart | 286 +- useragent/lib/screens/dashboard.dart | 242 +- useragent/lib/screens/dashboard/about.dart | 26 +- .../screens/dashboard/clients/details.dart | 30 +- .../clients/details/client_details.dart | 112 +- .../widgets/client_details_content.dart | 110 +- .../widgets/client_details_header.dart | 46 +- .../widgets/client_details_state_panel.dart | 74 +- .../details/widgets/client_summary_card.dart | 138 +- .../details/widgets/wallet_access_list.dart | 66 +- .../widgets/wallet_access_save_bar.dart | 108 +- .../widgets/wallet_access_search_field.dart | 48 +- .../widgets/wallet_access_section.dart | 332 +- .../details/widgets/wallet_access_tile.dart | 56 +- .../lib/screens/dashboard/clients/table.dart | 1018 +- useragent/lib/screens/dashboard/evm/evm.dart | 200 +- .../grants/create/fields/chain_id_field.dart | 42 +- .../create/fields/client_picker_field.dart | 80 +- .../grants/create/fields/date_time_field.dart | 126 +- .../create/fields/gas_fee_options_field.dart | 78 +- .../fields/transaction_rate_limit_field.dart | 78 +- .../create/fields/validity_window_field.dart | 58 +- .../fields/wallet_access_picker_field.dart | 114 +- .../create/grants/ether_transfer_grant.dart | 450 +- .../create/grants/ether_transfer_grant.g.dart | 126 +- .../create/grants/grant_form_handler.dart | 52 +- .../create/grants/token_transfer_grant.dart | 482 +- .../create/grants/token_transfer_grant.g.dart | 126 +- .../dashboard/evm/grants/create/provider.dart | 48 +- .../evm/grants/create/provider.freezed.dart | 548 +- .../evm/grants/create/provider.g.dart | 124 +- .../dashboard/evm/grants/create/screen.dart | 702 +- .../grants/create/shared_grant_fields.dart | 42 +- .../dashboard/evm/grants/create/utils.dart | 146 +- .../screens/dashboard/evm/grants/grants.dart | 314 +- .../evm/grants/widgets/grant_card.dart | 438 +- .../screens/dashboard/evm/wallets/header.dart | 192 +- .../screens/dashboard/evm/wallets/table.dart | 400 +- useragent/lib/screens/server_connection.dart | 118 +- useragent/lib/screens/server_info_setup.dart | 588 +- useragent/lib/screens/vault_setup.dart | 820 +- useragent/lib/src/rust/api.dart | 60 +- useragent/lib/src/rust/frb_generated.dart | 1260 +- useragent/lib/src/rust/frb_generated.io.dart | 440 +- useragent/lib/src/rust/frb_generated.web.dart | 424 +- useragent/lib/theme/palette.dart | 24 +- useragent/lib/widgets/bottom_popup.dart | 186 +- useragent/lib/widgets/cream_frame.dart | 64 +- useragent/lib/widgets/page_header.dart | 126 +- useragent/lib/widgets/state_panel.dart | 138 +- useragent/macos/.gitignore | 14 +- .../macos/Flutter/Flutter-Debug.xcconfig | 4 +- .../macos/Flutter/Flutter-Release.xcconfig | 4 +- .../Flutter/GeneratedPluginRegistrant.swift | 40 +- useragent/macos/Podfile | 84 +- useragent/macos/Podfile.lock | 106 +- .../macos/Runner.xcodeproj/project.pbxproj | 1672 +- .../xcshareddata/IDEWorkspaceChecks.plist | 16 +- .../xcshareddata/xcschemes/Runner.xcscheme | 198 +- .../contents.xcworkspacedata | 20 +- .../xcshareddata/IDEWorkspaceChecks.plist | 16 +- useragent/macos/Runner/AppDelegate.swift | 26 +- .../AppIcon.appiconset/Contents.json | 136 +- .../macos/Runner/Base.lproj/MainMenu.xib | 686 +- .../macos/Runner/Configs/AppInfo.xcconfig | 28 +- useragent/macos/Runner/Configs/Debug.xcconfig | 4 +- .../macos/Runner/Configs/Release.xcconfig | 4 +- .../macos/Runner/Configs/Warnings.xcconfig | 26 +- .../macos/Runner/DebugProfile.entitlements | 16 +- useragent/macos/Runner/Info.plist | 64 +- .../macos/Runner/MainFlutterWindow.swift | 30 +- useragent/macos/Runner/Release.entitlements | 16 +- useragent/macos/RunnerTests/RunnerTests.swift | 24 +- useragent/mise.toml | 8 +- useragent/pubspec.lock | 2578 +- useragent/pubspec.yaml | 108 +- useragent/rust/.gitignore | 2 +- useragent/rust/Cargo.lock | 10436 +++--- useragent/rust/Cargo.toml | 34 +- useragent/rust/src/api/mod.rs | 76 +- useragent/rust/src/frb_generated.rs | 1214 +- useragent/rust/src/lib.rs | 4 +- useragent/rust_builder/.gitignore | 58 +- useragent/rust_builder/android/.gitignore | 18 +- useragent/rust_builder/android/build.gradle | 112 +- .../rust_builder/android/settings.gradle | 2 +- .../android/src/main/AndroidManifest.xml | 6 +- useragent/rust_builder/cargokit/.gitignore | 8 +- useragent/rust_builder/cargokit/LICENSE | 84 +- useragent/rust_builder/cargokit/README | 22 +- useragent/rust_builder/cargokit/build_pod.sh | 116 +- .../cargokit/build_tool/README.md | 10 +- .../cargokit/build_tool/analysis_options.yaml | 68 +- .../cargokit/build_tool/bin/build_tool.dart | 16 +- .../cargokit/build_tool/lib/build_tool.dart | 16 +- .../lib/src/android_environment.dart | 390 +- .../lib/src/artifacts_provider.dart | 532 +- .../build_tool/lib/src/build_cmake.dart | 80 +- .../build_tool/lib/src/build_gradle.dart | 98 +- .../build_tool/lib/src/build_pod.dart | 178 +- .../build_tool/lib/src/build_tool.dart | 552 +- .../cargokit/build_tool/lib/src/builder.dart | 418 +- .../cargokit/build_tool/lib/src/cargo.dart | 96 +- .../build_tool/lib/src/crate_hash.dart | 248 +- .../build_tool/lib/src/environment.dart | 136 +- .../cargokit/build_tool/lib/src/logging.dart | 104 +- .../cargokit/build_tool/lib/src/options.dart | 618 +- .../lib/src/precompile_binaries.dart | 410 +- .../cargokit/build_tool/lib/src/rustup.dart | 298 +- .../cargokit/build_tool/lib/src/target.dart | 294 +- .../cargokit/build_tool/lib/src/util.dart | 344 +- .../build_tool/lib/src/verify_binaries.dart | 168 +- .../cargokit/build_tool/pubspec.lock | 906 +- .../cargokit/build_tool/pubspec.yaml | 66 +- .../cargokit/cmake/cargokit.cmake | 198 +- .../cargokit/cmake/resolve_symlinks.ps1 | 68 +- .../cargokit/gradle/plugin.gradle | 368 +- .../rust_builder/cargokit/run_build_tool.cmd | 182 +- .../rust_builder/cargokit/run_build_tool.sh | 198 +- .../rust_builder/ios/Classes/dummy_file.c | 2 +- .../rust_builder/ios/rust_lib_arbiter.podspec | 88 +- useragent/rust_builder/linux/CMakeLists.txt | 38 +- .../rust_builder/macos/Classes/dummy_file.c | 2 +- .../macos/rust_lib_arbiter.podspec | 86 +- useragent/rust_builder/pubspec.yaml | 68 +- useragent/rust_builder/windows/.gitignore | 34 +- useragent/rust_builder/windows/CMakeLists.txt | 40 +- .../details/client_details_screen_test.dart | 138 +- .../client_wallet_access_controller_test.dart | 210 +- useragent/test_driver/integration_test.dart | 6 +- useragent/web/index.html | 76 +- useragent/web/manifest.json | 70 +- useragent/windows/.gitignore | 34 +- useragent/windows/CMakeLists.txt | 216 +- useragent/windows/flutter/CMakeLists.txt | 218 +- .../flutter/generated_plugin_registrant.cc | 52 +- .../flutter/generated_plugin_registrant.h | 30 +- .../windows/flutter/generated_plugins.cmake | 58 +- useragent/windows/runner/CMakeLists.txt | 80 +- useragent/windows/runner/Runner.rc | 242 +- useragent/windows/runner/flutter_window.cpp | 142 +- useragent/windows/runner/flutter_window.h | 66 +- useragent/windows/runner/main.cpp | 86 +- useragent/windows/runner/resource.h | 32 +- useragent/windows/runner/runner.exe.manifest | 28 +- useragent/windows/runner/utils.cpp | 130 +- useragent/windows/runner/utils.h | 38 +- useragent/windows/runner/win32_window.cpp | 576 +- useragent/windows/runner/win32_window.h | 204 +- 425 files changed, 79190 insertions(+), 79190 deletions(-) diff --git a/.claude/memory/feedback_widget_decomposition.md b/.claude/memory/feedback_widget_decomposition.md index a6ea5f0..5032d4e 100644 --- a/.claude/memory/feedback_widget_decomposition.md +++ b/.claude/memory/feedback_widget_decomposition.md @@ -1,11 +1,11 @@ ---- -name: Widget decomposition and provider subscriptions -description: Prefer splitting screens into multiple focused files/widgets; each widget subscribes to its own relevant providers -type: feedback ---- - -Split screens into multiple smaller widgets across multiple files. Each widget should subscribe only to the providers it needs (`ref.watch` at lowest possible level), rather than having one large screen widget that watches everything and passes data down as parameters. - -**Why:** Reduces unnecessary rebuilds; improves readability; each file has one clear responsibility. - -**How to apply:** When building a new screen, identify which sub-widgets need their own provider subscriptions and extract them into separate files (e.g., `widgets/grant_card.dart` watches enrichment providers itself, rather than the screen doing it and passing resolved strings down). +--- +name: Widget decomposition and provider subscriptions +description: Prefer splitting screens into multiple focused files/widgets; each widget subscribes to its own relevant providers +type: feedback +--- + +Split screens into multiple smaller widgets across multiple files. Each widget should subscribe only to the providers it needs (`ref.watch` at lowest possible level), rather than having one large screen widget that watches everything and passes data down as parameters. + +**Why:** Reduces unnecessary rebuilds; improves readability; each file has one clear responsibility. + +**How to apply:** When building a new screen, identify which sub-widgets need their own provider subscriptions and extract them into separate files (e.g., `widgets/grant_card.dart` watches enrichment providers itself, rather than the screen doing it and passing resolved strings down). diff --git a/.gitignore b/.gitignore index d73db15..f2edc13 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -target/ -scripts/__pycache__/ -.DS_Store -.cargo/config.toml -.vscode/ -docs/superpowers +target/ +scripts/__pycache__/ +.DS_Store +.cargo/config.toml +.vscode/ +docs/superpowers diff --git a/.woodpecker/server-audit.yaml b/.woodpecker/server-audit.yaml index 7a83ab3..b7cb295 100644 --- a/.woodpecker/server-audit.yaml +++ b/.woodpecker/server-audit.yaml @@ -1,26 +1,26 @@ -when: - - event: pull_request - path: - include: ['.woodpecker/server-*.yaml', 'server/**'] - - event: push - branch: main - path: - include: ['.woodpecker/server-*.yaml', 'server/**'] - -steps: - - name: audit - image: jdxcode/mise:latest - directory: server - environment: - CARGO_TERM_COLOR: always - CARGO_TARGET_DIR: /usr/local/cargo/target - CARGO_HOME: /usr/local/cargo/registry - volumes: - - cargo-target:/usr/local/cargo/target - - cargo-registry:/usr/local/cargo/registry - commands: - - apt-get update && apt-get install -y pkg-config - # Install only the necessary Rust toolchain and test runner to speed up the CI - - mise install rust - - mise install cargo:cargo-audit +when: + - event: pull_request + path: + include: ['.woodpecker/server-*.yaml', 'server/**'] + - event: push + branch: main + path: + include: ['.woodpecker/server-*.yaml', 'server/**'] + +steps: + - name: audit + image: jdxcode/mise:latest + directory: server + environment: + CARGO_TERM_COLOR: always + CARGO_TARGET_DIR: /usr/local/cargo/target + CARGO_HOME: /usr/local/cargo/registry + volumes: + - cargo-target:/usr/local/cargo/target + - cargo-registry:/usr/local/cargo/registry + commands: + - apt-get update && apt-get install -y pkg-config + # Install only the necessary Rust toolchain and test runner to speed up the CI + - mise install rust + - mise install cargo:cargo-audit - mise exec cargo:cargo-audit -- cargo audit \ No newline at end of file diff --git a/.woodpecker/server-clippy-fix.yaml b/.woodpecker/server-clippy-fix.yaml index 4793343..384556c 100644 --- a/.woodpecker/server-clippy-fix.yaml +++ b/.woodpecker/server-clippy-fix.yaml @@ -1,45 +1,45 @@ -when: - - event: push - branch: main - path: - include: ['.woodpecker/server-*.yaml', 'server/**'] - -steps: - - name: clippy-fix - image: jdxcode/mise:latest - directory: server - environment: - CARGO_TERM_COLOR: always - CARGO_TARGET_DIR: /usr/local/cargo/target - CARGO_HOME: /usr/local/cargo/registry - GITEA_TOKEN: - from_secret: GITEA_TOKEN - GITEA_URL: - from_secret: GITEA_URL - volumes: - - cargo-target:/usr/local/cargo/target - - cargo-registry:/usr/local/cargo/registry - commands: - - apt-get update && apt-get install -y pkg-config curl - - mise install rust - - mise install protoc - - mise exec rust -- cargo clippy --fix --allow-dirty --all - - | - cd .. - if git diff --quiet HEAD; then - echo "No machine-applicable clippy fixes found, nothing to do." - exit 0 - fi - git config user.email "bot@arbiter" - git config user.name "Clippy Bot" - git add -A - git commit -m "fix(clippy): apply auto-fixable linting suggestions" - git config http.extraHeader "Authorization: token ${GITEA_TOKEN}" - git push --force origin HEAD:refs/heads/bot/clippy-fixes - HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ - -X POST "${GITEA_URL}/api/v1/repos/${CI_REPO}/pulls" \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - -d "{\"title\":\"fix(clippy): apply auto-fixable linting suggestions\",\"head\":\"bot/clippy-fixes\",\"base\":\"main\",\"body\":\"Automated clippy fixes generated by CI bot.\"}") - echo "Gitea API response: ${HTTP_STATUS}" - [ "$HTTP_STATUS" = "201" ] || [ "$HTTP_STATUS" = "409" ] || [ "$HTTP_STATUS" = "422" ] || exit 1 +when: + - event: push + branch: main + path: + include: ['.woodpecker/server-*.yaml', 'server/**'] + +steps: + - name: clippy-fix + image: jdxcode/mise:latest + directory: server + environment: + CARGO_TERM_COLOR: always + CARGO_TARGET_DIR: /usr/local/cargo/target + CARGO_HOME: /usr/local/cargo/registry + GITEA_TOKEN: + from_secret: GITEA_TOKEN + GITEA_URL: + from_secret: GITEA_URL + volumes: + - cargo-target:/usr/local/cargo/target + - cargo-registry:/usr/local/cargo/registry + commands: + - apt-get update && apt-get install -y pkg-config curl + - mise install rust + - mise install protoc + - mise exec rust -- cargo clippy --fix --allow-dirty --all + - | + cd .. + if git diff --quiet HEAD; then + echo "No machine-applicable clippy fixes found, nothing to do." + exit 0 + fi + git config user.email "bot@arbiter" + git config user.name "Clippy Bot" + git add -A + git commit -m "fix(clippy): apply auto-fixable linting suggestions" + git config http.extraHeader "Authorization: token ${GITEA_TOKEN}" + git push --force origin HEAD:refs/heads/bot/clippy-fixes + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ + -X POST "${GITEA_URL}/api/v1/repos/${CI_REPO}/pulls" \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "{\"title\":\"fix(clippy): apply auto-fixable linting suggestions\",\"head\":\"bot/clippy-fixes\",\"base\":\"main\",\"body\":\"Automated clippy fixes generated by CI bot.\"}") + echo "Gitea API response: ${HTTP_STATUS}" + [ "$HTTP_STATUS" = "201" ] || [ "$HTTP_STATUS" = "409" ] || [ "$HTTP_STATUS" = "422" ] || exit 1 diff --git a/.woodpecker/server-lint.yaml b/.woodpecker/server-lint.yaml index 3b74047..ef382f0 100644 --- a/.woodpecker/server-lint.yaml +++ b/.woodpecker/server-lint.yaml @@ -1,25 +1,25 @@ -when: - - event: pull_request - path: - include: ['.woodpecker/server-*.yaml', 'server/**'] - - event: push - branch: main - path: - include: ['.woodpecker/server-*.yaml', 'server/**'] - -steps: - - name: lint - image: jdxcode/mise:latest - directory: server - environment: - CARGO_TERM_COLOR: always - CARGO_TARGET_DIR: /usr/local/cargo/target - CARGO_HOME: /usr/local/cargo/registry - volumes: - - cargo-target:/usr/local/cargo/target - - cargo-registry:/usr/local/cargo/registry - commands: - - apt-get update && apt-get install -y pkg-config - - mise install rust - - mise install protoc +when: + - event: pull_request + path: + include: ['.woodpecker/server-*.yaml', 'server/**'] + - event: push + branch: main + path: + include: ['.woodpecker/server-*.yaml', 'server/**'] + +steps: + - name: lint + image: jdxcode/mise:latest + directory: server + environment: + CARGO_TERM_COLOR: always + CARGO_TARGET_DIR: /usr/local/cargo/target + CARGO_HOME: /usr/local/cargo/registry + volumes: + - cargo-target:/usr/local/cargo/target + - cargo-registry:/usr/local/cargo/registry + commands: + - apt-get update && apt-get install -y pkg-config + - mise install rust + - mise install protoc - mise exec rust -- cargo clippy --all -- -D warnings \ No newline at end of file diff --git a/.woodpecker/server-test.yaml b/.woodpecker/server-test.yaml index 027cf87..64643cd 100644 --- a/.woodpecker/server-test.yaml +++ b/.woodpecker/server-test.yaml @@ -1,27 +1,27 @@ -when: - - event: pull_request - path: - include: ['.woodpecker/server-*.yaml', 'server/**'] - - event: push - branch: main - path: - include: ['.woodpecker/server-*.yaml', 'server/**'] - -steps: - - name: test - image: jdxcode/mise:latest - directory: server - environment: - CARGO_TERM_COLOR: always - CARGO_TARGET_DIR: /usr/local/cargo/target - CARGO_HOME: /usr/local/cargo/registry - volumes: - - cargo-target:/usr/local/cargo/target - - cargo-registry:/usr/local/cargo/registry - commands: - - apt-get update && apt-get install -y pkg-config - # Install only the necessary Rust toolchain and test runner to speed up the CI - - mise install rust - - mise install protoc - - mise install cargo:cargo-nextest +when: + - event: pull_request + path: + include: ['.woodpecker/server-*.yaml', 'server/**'] + - event: push + branch: main + path: + include: ['.woodpecker/server-*.yaml', 'server/**'] + +steps: + - name: test + image: jdxcode/mise:latest + directory: server + environment: + CARGO_TERM_COLOR: always + CARGO_TARGET_DIR: /usr/local/cargo/target + CARGO_HOME: /usr/local/cargo/registry + volumes: + - cargo-target:/usr/local/cargo/target + - cargo-registry:/usr/local/cargo/registry + commands: + - apt-get update && apt-get install -y pkg-config + # Install only the necessary Rust toolchain and test runner to speed up the CI + - mise install rust + - mise install protoc + - mise install cargo:cargo-nextest - mise exec cargo:cargo-nextest -- cargo nextest run --no-fail-fast --all-features \ No newline at end of file diff --git a/.woodpecker/server-vet.yaml b/.woodpecker/server-vet.yaml index dcb45f3..fd79394 100644 --- a/.woodpecker/server-vet.yaml +++ b/.woodpecker/server-vet.yaml @@ -1,26 +1,26 @@ -when: - - event: pull_request - path: - include: ['.woodpecker/server-*.yaml', 'server/**'] - - event: push - branch: main - path: - include: ['.woodpecker/server-*.yaml', 'server/**'] - -steps: - - name: vet - image: jdxcode/mise:latest - directory: server - environment: - CARGO_TERM_COLOR: always - CARGO_TARGET_DIR: /usr/local/cargo/target - CARGO_HOME: /usr/local/cargo/registry - volumes: - - cargo-target:/usr/local/cargo/target - - cargo-registry:/usr/local/cargo/registry - commands: - - apt-get update && apt-get install -y pkg-config - # Install only the necessary Rust toolchain and test runner to speed up the CI - - mise install rust - - mise install cargo:cargo-vet +when: + - event: pull_request + path: + include: ['.woodpecker/server-*.yaml', 'server/**'] + - event: push + branch: main + path: + include: ['.woodpecker/server-*.yaml', 'server/**'] + +steps: + - name: vet + image: jdxcode/mise:latest + directory: server + environment: + CARGO_TERM_COLOR: always + CARGO_TARGET_DIR: /usr/local/cargo/target + CARGO_HOME: /usr/local/cargo/registry + volumes: + - cargo-target:/usr/local/cargo/target + - cargo-registry:/usr/local/cargo/registry + commands: + - apt-get update && apt-get install -y pkg-config + # Install only the necessary Rust toolchain and test runner to speed up the CI + - mise install rust + - mise install cargo:cargo-vet - mise exec cargo:cargo-vet -- cargo vet \ No newline at end of file diff --git a/.woodpecker/useragent-analyze.yaml b/.woodpecker/useragent-analyze.yaml index 73230a2..7b7e5fa 100644 --- a/.woodpecker/useragent-analyze.yaml +++ b/.woodpecker/useragent-analyze.yaml @@ -1,18 +1,18 @@ -when: - - event: pull_request - path: - include: ['.woodpecker/useragent-*.yaml', 'useragent/**'] - - event: push - branch: main - path: - include: ['.woodpecker/useragent-*.yaml', 'useragent/**'] - -steps: - - name: analyze - image: jdxcode/mise:latest - commands: - - mise install flutter - - mise install protoc - # Reruns codegen to catch protocol drift - - mise codegen +when: + - event: pull_request + path: + include: ['.woodpecker/useragent-*.yaml', 'useragent/**'] + - event: push + branch: main + path: + include: ['.woodpecker/useragent-*.yaml', 'useragent/**'] + +steps: + - name: analyze + image: jdxcode/mise:latest + commands: + - mise install flutter + - mise install protoc + # Reruns codegen to catch protocol drift + - mise codegen - cd useragent/ && flutter analyze \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 5148908..5ea5ec4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,149 +1,149 @@ -# AGENTS.md - -This file provides guidance to Codex (Codex.ai/code) when working with code in this repository. - -## Project Overview - -Arbiter is a **permissioned signing service** for cryptocurrency wallets. It consists of: -- **`server/`** — Rust gRPC daemon that holds encrypted keys and enforces policies -- **`operator/`** — Flutter desktop app (macOS/Windows) with a Rust backend via Rinf -- **`protobufs/`** — Protocol Buffer definitions shared between server and client - -The vault never exposes key material; it only produces signatures when requests satisfy configured policies. - -## Toolchain Setup - -Tools are managed via [mise](https://mise.jdx.dev/). Install all required tools: -```sh -mise install -``` - -Key versions: Rust 1.93.0 (with clippy), Flutter 3.38.9-stable, protoc 29.6, diesel_cli 2.3.6 (sqlite). - -## Server (Rust workspace at `server/`) - -### Crates - -| Crate | Purpose | -|---|---| -| `arbiter-proto` | Generated gRPC stubs + protobuf types; compiled from `protobufs/*.proto` via `tonic-prost-build` | -| `arbiter-server` | Main daemon — actors, DB, EVM policy engine, gRPC service implementation | -| `arbiter-operator` | Rust client library for the operator side of the gRPC protocol | -| `arbiter-client` | Rust client library for SDK clients | - -### Common Commands - -```sh -cd server - -# Build -cargo build - -# Run the server daemon -cargo run -p arbiter-server - -# Run all tests (preferred over cargo test) -cargo nextest run - -# Run a single test -cargo nextest run - -# Lint -cargo clippy - -# Security audit -cargo audit - -# Check unused dependencies -cargo shear - -# Run snapshot tests and update snapshots -cargo insta review -``` - -### Architecture - -The server is actor-based using the **kameo** crate. All long-lived state lives in `GlobalActors`: - -- **`Bootstrapper`** — Manages the one-time bootstrap token written to `~/.arbiter/bootstrap_token` on first run. -- **`Vault`** — Holds the encrypted root key and manages the Sealed/Unsealed vault state machine. On unseal, decrypts the root key into a `memsafe` hardened memory cell. -- **`FlowCoordinator`** — Coordinates cross-connection flow between operators and SDK clients. -- **`EvmActor`** — Handles EVM transaction policy enforcement and signing. - -Per-connection actors live under `actors/operator/` and `actors/client/`, each with `auth` (challenge-response authentication) and `session` (post-auth operations) sub-modules. - -**Database:** SQLite via `diesel-async` + `bb8` connection pool. Schema managed by embedded Diesel migrations in `crates/arbiter-server/migrations/`. DB file lives at `~/.arbiter/arbiter.sqlite`. Tests use a temp-file DB via `db::create_test_pool()`. - -**Cryptography:** -- Authentication: ed25519 (challenge-response, nonce-tracked per peer) -- Encryption at rest: XChaCha20-Poly1305 (versioned via `scheme` field for transparent migration on unseal) -- Password KDF: Argon2 -- Unseal transport: X25519 ephemeral key exchange -- TLS: self-signed certificate (aws-lc-rs backend), fingerprint distributed via `ArbiterUrl` - -**Protocol:** gRPC with Protocol Buffers. The `ArbiterUrl` type encodes host, port, CA cert, and bootstrap token into a single shareable string (printed to console on first run). - -### Proto Regeneration - -When `.proto` files in `protobufs/` change, rebuild to regenerate: -```sh -cd server && cargo build -p arbiter-proto -``` - -### Database Migrations - -```sh -# Create a new migration -diesel migration generate --migration-dir crates/arbiter-server/migrations - -# Run migrations manually (server also runs them on startup) -diesel migration run --migration-dir crates/arbiter-server/migrations -``` - -### Code Conventions - -**`#[must_use]` Attribute:** -Apply the `#[must_use]` attribute to return types of functions where the return value is critical and should not be accidentally ignored. This is commonly used for: - -- Methods that return `bool` indicating success/failure or validation state -- Any function where ignoring the return value indicates a logic error - -Do not apply `#[must_use]` redundantly to items (types or functions) that are already annotated with `#[must_use]`. - -Example: - -```rust -#[must_use] -pub fn verify(&self, nonce: i32, context: &[u8], signature: &Signature) -> bool { - // verification logic -} -``` - -This forces callers to either use the return value or explicitly ignore it with `let _ = ...;`, preventing silent failures. - -## Operator (Flutter + Rinf at `operator/`) - -The Flutter app uses [Rinf](https://rinf.cunarist.org) to call Rust code. The Rust logic lives in `operator/native/hub/` as a separate crate that uses `arbiter-operator` for the gRPC client. - -Communication between Dart and Rust uses typed **signals** defined in `operator/native/hub/src/signals/`. After modifying signal structs, regenerate Dart bindings: - -```sh -cd operator && rinf gen -``` - -### Common Commands - -```sh -cd operator - -# Run the app (macOS or Windows) -flutter run - -# Regenerate Rust↔Dart signal bindings -rinf gen - -# Analyze Dart code -flutter analyze -``` - -The Rinf Rust entry point is `operator/native/hub/src/lib.rs`. It spawns actors defined in `operator/native/hub/src/actors/` which handle Dart↔server communication via signals. +# AGENTS.md + +This file provides guidance to Codex (Codex.ai/code) when working with code in this repository. + +## Project Overview + +Arbiter is a **permissioned signing service** for cryptocurrency wallets. It consists of: +- **`server/`** — Rust gRPC daemon that holds encrypted keys and enforces policies +- **`operator/`** — Flutter desktop app (macOS/Windows) with a Rust backend via Rinf +- **`protobufs/`** — Protocol Buffer definitions shared between server and client + +The vault never exposes key material; it only produces signatures when requests satisfy configured policies. + +## Toolchain Setup + +Tools are managed via [mise](https://mise.jdx.dev/). Install all required tools: +```sh +mise install +``` + +Key versions: Rust 1.93.0 (with clippy), Flutter 3.38.9-stable, protoc 29.6, diesel_cli 2.3.6 (sqlite). + +## Server (Rust workspace at `server/`) + +### Crates + +| Crate | Purpose | +|---|---| +| `arbiter-proto` | Generated gRPC stubs + protobuf types; compiled from `protobufs/*.proto` via `tonic-prost-build` | +| `arbiter-server` | Main daemon — actors, DB, EVM policy engine, gRPC service implementation | +| `arbiter-operator` | Rust client library for the operator side of the gRPC protocol | +| `arbiter-client` | Rust client library for SDK clients | + +### Common Commands + +```sh +cd server + +# Build +cargo build + +# Run the server daemon +cargo run -p arbiter-server + +# Run all tests (preferred over cargo test) +cargo nextest run + +# Run a single test +cargo nextest run + +# Lint +cargo clippy + +# Security audit +cargo audit + +# Check unused dependencies +cargo shear + +# Run snapshot tests and update snapshots +cargo insta review +``` + +### Architecture + +The server is actor-based using the **kameo** crate. All long-lived state lives in `GlobalActors`: + +- **`Bootstrapper`** — Manages the one-time bootstrap token written to `~/.arbiter/bootstrap_token` on first run. +- **`Vault`** — Holds the encrypted root key and manages the Sealed/Unsealed vault state machine. On unseal, decrypts the root key into a `memsafe` hardened memory cell. +- **`FlowCoordinator`** — Coordinates cross-connection flow between operators and SDK clients. +- **`EvmActor`** — Handles EVM transaction policy enforcement and signing. + +Per-connection actors live under `actors/operator/` and `actors/client/`, each with `auth` (challenge-response authentication) and `session` (post-auth operations) sub-modules. + +**Database:** SQLite via `diesel-async` + `bb8` connection pool. Schema managed by embedded Diesel migrations in `crates/arbiter-server/migrations/`. DB file lives at `~/.arbiter/arbiter.sqlite`. Tests use a temp-file DB via `db::create_test_pool()`. + +**Cryptography:** +- Authentication: ed25519 (challenge-response, nonce-tracked per peer) +- Encryption at rest: XChaCha20-Poly1305 (versioned via `scheme` field for transparent migration on unseal) +- Password KDF: Argon2 +- Unseal transport: X25519 ephemeral key exchange +- TLS: self-signed certificate (aws-lc-rs backend), fingerprint distributed via `ArbiterUrl` + +**Protocol:** gRPC with Protocol Buffers. The `ArbiterUrl` type encodes host, port, CA cert, and bootstrap token into a single shareable string (printed to console on first run). + +### Proto Regeneration + +When `.proto` files in `protobufs/` change, rebuild to regenerate: +```sh +cd server && cargo build -p arbiter-proto +``` + +### Database Migrations + +```sh +# Create a new migration +diesel migration generate --migration-dir crates/arbiter-server/migrations + +# Run migrations manually (server also runs them on startup) +diesel migration run --migration-dir crates/arbiter-server/migrations +``` + +### Code Conventions + +**`#[must_use]` Attribute:** +Apply the `#[must_use]` attribute to return types of functions where the return value is critical and should not be accidentally ignored. This is commonly used for: + +- Methods that return `bool` indicating success/failure or validation state +- Any function where ignoring the return value indicates a logic error + +Do not apply `#[must_use]` redundantly to items (types or functions) that are already annotated with `#[must_use]`. + +Example: + +```rust +#[must_use] +pub fn verify(&self, nonce: i32, context: &[u8], signature: &Signature) -> bool { + // verification logic +} +``` + +This forces callers to either use the return value or explicitly ignore it with `let _ = ...;`, preventing silent failures. + +## Operator (Flutter + Rinf at `operator/`) + +The Flutter app uses [Rinf](https://rinf.cunarist.org) to call Rust code. The Rust logic lives in `operator/native/hub/` as a separate crate that uses `arbiter-operator` for the gRPC client. + +Communication between Dart and Rust uses typed **signals** defined in `operator/native/hub/src/signals/`. After modifying signal structs, regenerate Dart bindings: + +```sh +cd operator && rinf gen +``` + +### Common Commands + +```sh +cd operator + +# Run the app (macOS or Windows) +flutter run + +# Regenerate Rust↔Dart signal bindings +rinf gen + +# Analyze Dart code +flutter analyze +``` + +The Rinf Rust entry point is `operator/native/hub/src/lib.rs`. It spawns actors defined in `operator/native/hub/src/actors/` which handle Dart↔server communication via signals. diff --git a/CLAUDE.md b/CLAUDE.md index 95ed972..bc9a6ca 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1 +1 @@ -Refer to @AGENTS.md for instructions. +Refer to @AGENTS.md for instructions. diff --git a/LICENSE b/LICENSE index a064703..4da7f05 100644 --- a/LICENSE +++ b/LICENSE @@ -1,190 +1,190 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2026 MarketTakers - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2026 MarketTakers + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 389aac0..1aa5093 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ -# Arbiter -> Policy-first multi-client wallet daemon, allowing permissioned transactions across blockchains - -## Security warning -Arbiter can't meaningfully protect against host compromise. Potential attack flow: -- Attacker steals TLS keys from database -- Pretends to be server; just accepts operator challenge solutions -- Pretend to be in sealed state and performing DH with client -- Steals user password and derives seal key - -While this attack is highly targetive, it's still possible. - +# Arbiter +> Policy-first multi-client wallet daemon, allowing permissioned transactions across blockchains + +## Security warning +Arbiter can't meaningfully protect against host compromise. Potential attack flow: +- Attacker steals TLS keys from database +- Pretends to be server; just accepts operator challenge solutions +- Pretend to be in sealed state and performing DH with client +- Steals user password and derives seal key + +While this attack is highly targetive, it's still possible. + > This software is experimental. Do not use with funds you cannot afford to lose. \ No newline at end of file diff --git a/app/.dart_tool/extension_discovery/README.md b/app/.dart_tool/extension_discovery/README.md index 9dc6757..6cbf37a 100644 --- a/app/.dart_tool/extension_discovery/README.md +++ b/app/.dart_tool/extension_discovery/README.md @@ -1,31 +1,31 @@ -Extension Discovery Cache -========================= - -This folder is used by `package:extension_discovery` to cache lists of -packages that contains extensions for other packages. - -DO NOT USE THIS FOLDER ----------------------- - - * Do not read (or rely) the contents of this folder. - * Do write to this folder. - -If you're interested in the lists of extensions stored in this folder use the -API offered by package `extension_discovery` to get this information. - -If this package doesn't work for your use-case, then don't try to read the -contents of this folder. It may change, and will not remain stable. - -Use package `extension_discovery` ---------------------------------- - -If you want to access information from this folder. - -Feel free to delete this folder -------------------------------- - -Files in this folder act as a cache, and the cache is discarded if the files -are older than the modification time of `.dart_tool/package_config.json`. - -Hence, it should never be necessary to clear this cache manually, if you find a -need to do please file a bug. +Extension Discovery Cache +========================= + +This folder is used by `package:extension_discovery` to cache lists of +packages that contains extensions for other packages. + +DO NOT USE THIS FOLDER +---------------------- + + * Do not read (or rely) the contents of this folder. + * Do write to this folder. + +If you're interested in the lists of extensions stored in this folder use the +API offered by package `extension_discovery` to get this information. + +If this package doesn't work for your use-case, then don't try to read the +contents of this folder. It may change, and will not remain stable. + +Use package `extension_discovery` +--------------------------------- + +If you want to access information from this folder. + +Feel free to delete this folder +------------------------------- + +Files in this folder act as a cache, and the cache is discarded if the files +are older than the modification time of `.dart_tool/package_config.json`. + +Hence, it should never be necessary to clear this cache manually, if you find a +need to do please file a bug. diff --git a/app/.dart_tool/package_config.json b/app/.dart_tool/package_config.json index 258edaf..a85a0f4 100644 --- a/app/.dart_tool/package_config.json +++ b/app/.dart_tool/package_config.json @@ -1,178 +1,178 @@ -{ - "configVersion": 2, - "packages": [ - { - "name": "async", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/async-2.13.0", - "packageUri": "lib/", - "languageVersion": "3.4" - }, - { - "name": "boolean_selector", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2", - "packageUri": "lib/", - "languageVersion": "3.1" - }, - { - "name": "characters", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/characters-1.4.0", - "packageUri": "lib/", - "languageVersion": "3.4" - }, - { - "name": "clock", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/clock-1.1.2", - "packageUri": "lib/", - "languageVersion": "3.4" - }, - { - "name": "collection", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/collection-1.19.1", - "packageUri": "lib/", - "languageVersion": "3.4" - }, - { - "name": "cupertino_icons", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8", - "packageUri": "lib/", - "languageVersion": "3.1" - }, - { - "name": "fake_async", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/fake_async-1.3.3", - "packageUri": "lib/", - "languageVersion": "3.3" - }, - { - "name": "flutter", - "rootUri": "file:///Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable/packages/flutter", - "packageUri": "lib/", - "languageVersion": "3.8" - }, - { - "name": "flutter_lints", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/flutter_lints-6.0.0", - "packageUri": "lib/", - "languageVersion": "3.8" - }, - { - "name": "flutter_test", - "rootUri": "file:///Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable/packages/flutter_test", - "packageUri": "lib/", - "languageVersion": "3.8" - }, - { - "name": "leak_tracker", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/leak_tracker-11.0.2", - "packageUri": "lib/", - "languageVersion": "3.2" - }, - { - "name": "leak_tracker_flutter_testing", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10", - "packageUri": "lib/", - "languageVersion": "3.2" - }, - { - "name": "leak_tracker_testing", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.2", - "packageUri": "lib/", - "languageVersion": "3.2" - }, - { - "name": "lints", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/lints-6.1.0", - "packageUri": "lib/", - "languageVersion": "3.8" - }, - { - "name": "matcher", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/matcher-0.12.17", - "packageUri": "lib/", - "languageVersion": "3.4" - }, - { - "name": "material_color_utilities", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", - "packageUri": "lib/", - "languageVersion": "2.17" - }, - { - "name": "meta", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/meta-1.17.0", - "packageUri": "lib/", - "languageVersion": "3.5" - }, - { - "name": "path", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/path-1.9.1", - "packageUri": "lib/", - "languageVersion": "3.4" - }, - { - "name": "sky_engine", - "rootUri": "file:///Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable/bin/cache/pkg/sky_engine", - "packageUri": "lib/", - "languageVersion": "3.8" - }, - { - "name": "source_span", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/source_span-1.10.2", - "packageUri": "lib/", - "languageVersion": "3.1" - }, - { - "name": "stack_trace", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/stack_trace-1.12.1", - "packageUri": "lib/", - "languageVersion": "3.4" - }, - { - "name": "stream_channel", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/stream_channel-2.1.4", - "packageUri": "lib/", - "languageVersion": "3.3" - }, - { - "name": "string_scanner", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/string_scanner-1.4.1", - "packageUri": "lib/", - "languageVersion": "3.1" - }, - { - "name": "term_glyph", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/term_glyph-1.2.2", - "packageUri": "lib/", - "languageVersion": "3.1" - }, - { - "name": "test_api", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/test_api-0.7.7", - "packageUri": "lib/", - "languageVersion": "3.5" - }, - { - "name": "vector_math", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/vector_math-2.2.0", - "packageUri": "lib/", - "languageVersion": "3.1" - }, - { - "name": "vm_service", - "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/vm_service-15.0.2", - "packageUri": "lib/", - "languageVersion": "3.5" - }, - { - "name": "app", - "rootUri": "../", - "packageUri": "lib/", - "languageVersion": "3.10" - } - ], - "generator": "pub", - "generatorVersion": "3.10.8", - "flutterRoot": "file:///Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable", - "flutterVersion": "3.38.9", - "pubCache": "file:///Users/kaska/.pub-cache" -} +{ + "configVersion": 2, + "packages": [ + { + "name": "async", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/async-2.13.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "boolean_selector", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "characters", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/characters-1.4.0", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "clock", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/clock-1.1.2", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "collection", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/collection-1.19.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "cupertino_icons", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "fake_async", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/fake_async-1.3.3", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "flutter", + "rootUri": "file:///Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable/packages/flutter", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_lints", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/flutter_lints-6.0.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "flutter_test", + "rootUri": "file:///Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable/packages/flutter_test", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "leak_tracker", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/leak_tracker-11.0.2", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "leak_tracker_flutter_testing", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "leak_tracker_testing", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.2", + "packageUri": "lib/", + "languageVersion": "3.2" + }, + { + "name": "lints", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/lints-6.1.0", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "matcher", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/matcher-0.12.17", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "material_color_utilities", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", + "packageUri": "lib/", + "languageVersion": "2.17" + }, + { + "name": "meta", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/meta-1.17.0", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "path", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/path-1.9.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "sky_engine", + "rootUri": "file:///Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable/bin/cache/pkg/sky_engine", + "packageUri": "lib/", + "languageVersion": "3.8" + }, + { + "name": "source_span", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/source_span-1.10.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "stack_trace", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/stack_trace-1.12.1", + "packageUri": "lib/", + "languageVersion": "3.4" + }, + { + "name": "stream_channel", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/stream_channel-2.1.4", + "packageUri": "lib/", + "languageVersion": "3.3" + }, + { + "name": "string_scanner", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/string_scanner-1.4.1", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "term_glyph", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/term_glyph-1.2.2", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "test_api", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/test_api-0.7.7", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "vector_math", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/vector_math-2.2.0", + "packageUri": "lib/", + "languageVersion": "3.1" + }, + { + "name": "vm_service", + "rootUri": "file:///Users/kaska/.pub-cache/hosted/pub.dev/vm_service-15.0.2", + "packageUri": "lib/", + "languageVersion": "3.5" + }, + { + "name": "app", + "rootUri": "../", + "packageUri": "lib/", + "languageVersion": "3.10" + } + ], + "generator": "pub", + "generatorVersion": "3.10.8", + "flutterRoot": "file:///Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable", + "flutterVersion": "3.38.9", + "pubCache": "file:///Users/kaska/.pub-cache" +} diff --git a/app/.dart_tool/package_graph.json b/app/.dart_tool/package_graph.json index 2affe54..8687793 100644 --- a/app/.dart_tool/package_graph.json +++ b/app/.dart_tool/package_graph.json @@ -1,230 +1,230 @@ -{ - "roots": [ - "app" - ], - "packages": [ - { - "name": "app", - "version": "1.0.0+1", - "dependencies": [ - "cupertino_icons", - "flutter" - ], - "devDependencies": [ - "flutter_lints", - "flutter_test" - ] - }, - { - "name": "flutter_lints", - "version": "6.0.0", - "dependencies": [ - "lints" - ] - }, - { - "name": "flutter_test", - "version": "0.0.0", - "dependencies": [ - "clock", - "collection", - "fake_async", - "flutter", - "leak_tracker_flutter_testing", - "matcher", - "meta", - "path", - "stack_trace", - "stream_channel", - "test_api", - "vector_math" - ] - }, - { - "name": "cupertino_icons", - "version": "1.0.8", - "dependencies": [] - }, - { - "name": "flutter", - "version": "0.0.0", - "dependencies": [ - "characters", - "collection", - "material_color_utilities", - "meta", - "sky_engine", - "vector_math" - ] - }, - { - "name": "lints", - "version": "6.1.0", - "dependencies": [] - }, - { - "name": "stream_channel", - "version": "2.1.4", - "dependencies": [ - "async" - ] - }, - { - "name": "meta", - "version": "1.17.0", - "dependencies": [] - }, - { - "name": "collection", - "version": "1.19.1", - "dependencies": [] - }, - { - "name": "leak_tracker_flutter_testing", - "version": "3.0.10", - "dependencies": [ - "flutter", - "leak_tracker", - "leak_tracker_testing", - "matcher", - "meta" - ] - }, - { - "name": "vector_math", - "version": "2.2.0", - "dependencies": [] - }, - { - "name": "stack_trace", - "version": "1.12.1", - "dependencies": [ - "path" - ] - }, - { - "name": "clock", - "version": "1.1.2", - "dependencies": [] - }, - { - "name": "fake_async", - "version": "1.3.3", - "dependencies": [ - "clock", - "collection" - ] - }, - { - "name": "path", - "version": "1.9.1", - "dependencies": [] - }, - { - "name": "matcher", - "version": "0.12.17", - "dependencies": [ - "async", - "meta", - "stack_trace", - "term_glyph", - "test_api" - ] - }, - { - "name": "test_api", - "version": "0.7.7", - "dependencies": [ - "async", - "boolean_selector", - "collection", - "meta", - "source_span", - "stack_trace", - "stream_channel", - "string_scanner", - "term_glyph" - ] - }, - { - "name": "sky_engine", - "version": "0.0.0", - "dependencies": [] - }, - { - "name": "material_color_utilities", - "version": "0.11.1", - "dependencies": [ - "collection" - ] - }, - { - "name": "characters", - "version": "1.4.0", - "dependencies": [] - }, - { - "name": "async", - "version": "2.13.0", - "dependencies": [ - "collection", - "meta" - ] - }, - { - "name": "leak_tracker_testing", - "version": "3.0.2", - "dependencies": [ - "leak_tracker", - "matcher", - "meta" - ] - }, - { - "name": "leak_tracker", - "version": "11.0.2", - "dependencies": [ - "clock", - "collection", - "meta", - "path", - "vm_service" - ] - }, - { - "name": "term_glyph", - "version": "1.2.2", - "dependencies": [] - }, - { - "name": "string_scanner", - "version": "1.4.1", - "dependencies": [ - "source_span" - ] - }, - { - "name": "source_span", - "version": "1.10.2", - "dependencies": [ - "collection", - "path", - "term_glyph" - ] - }, - { - "name": "boolean_selector", - "version": "2.1.2", - "dependencies": [ - "source_span", - "string_scanner" - ] - }, - { - "name": "vm_service", - "version": "15.0.2", - "dependencies": [] - } - ], - "configVersion": 1 +{ + "roots": [ + "app" + ], + "packages": [ + { + "name": "app", + "version": "1.0.0+1", + "dependencies": [ + "cupertino_icons", + "flutter" + ], + "devDependencies": [ + "flutter_lints", + "flutter_test" + ] + }, + { + "name": "flutter_lints", + "version": "6.0.0", + "dependencies": [ + "lints" + ] + }, + { + "name": "flutter_test", + "version": "0.0.0", + "dependencies": [ + "clock", + "collection", + "fake_async", + "flutter", + "leak_tracker_flutter_testing", + "matcher", + "meta", + "path", + "stack_trace", + "stream_channel", + "test_api", + "vector_math" + ] + }, + { + "name": "cupertino_icons", + "version": "1.0.8", + "dependencies": [] + }, + { + "name": "flutter", + "version": "0.0.0", + "dependencies": [ + "characters", + "collection", + "material_color_utilities", + "meta", + "sky_engine", + "vector_math" + ] + }, + { + "name": "lints", + "version": "6.1.0", + "dependencies": [] + }, + { + "name": "stream_channel", + "version": "2.1.4", + "dependencies": [ + "async" + ] + }, + { + "name": "meta", + "version": "1.17.0", + "dependencies": [] + }, + { + "name": "collection", + "version": "1.19.1", + "dependencies": [] + }, + { + "name": "leak_tracker_flutter_testing", + "version": "3.0.10", + "dependencies": [ + "flutter", + "leak_tracker", + "leak_tracker_testing", + "matcher", + "meta" + ] + }, + { + "name": "vector_math", + "version": "2.2.0", + "dependencies": [] + }, + { + "name": "stack_trace", + "version": "1.12.1", + "dependencies": [ + "path" + ] + }, + { + "name": "clock", + "version": "1.1.2", + "dependencies": [] + }, + { + "name": "fake_async", + "version": "1.3.3", + "dependencies": [ + "clock", + "collection" + ] + }, + { + "name": "path", + "version": "1.9.1", + "dependencies": [] + }, + { + "name": "matcher", + "version": "0.12.17", + "dependencies": [ + "async", + "meta", + "stack_trace", + "term_glyph", + "test_api" + ] + }, + { + "name": "test_api", + "version": "0.7.7", + "dependencies": [ + "async", + "boolean_selector", + "collection", + "meta", + "source_span", + "stack_trace", + "stream_channel", + "string_scanner", + "term_glyph" + ] + }, + { + "name": "sky_engine", + "version": "0.0.0", + "dependencies": [] + }, + { + "name": "material_color_utilities", + "version": "0.11.1", + "dependencies": [ + "collection" + ] + }, + { + "name": "characters", + "version": "1.4.0", + "dependencies": [] + }, + { + "name": "async", + "version": "2.13.0", + "dependencies": [ + "collection", + "meta" + ] + }, + { + "name": "leak_tracker_testing", + "version": "3.0.2", + "dependencies": [ + "leak_tracker", + "matcher", + "meta" + ] + }, + { + "name": "leak_tracker", + "version": "11.0.2", + "dependencies": [ + "clock", + "collection", + "meta", + "path", + "vm_service" + ] + }, + { + "name": "term_glyph", + "version": "1.2.2", + "dependencies": [] + }, + { + "name": "string_scanner", + "version": "1.4.1", + "dependencies": [ + "source_span" + ] + }, + { + "name": "source_span", + "version": "1.10.2", + "dependencies": [ + "collection", + "path", + "term_glyph" + ] + }, + { + "name": "boolean_selector", + "version": "2.1.2", + "dependencies": [ + "source_span", + "string_scanner" + ] + }, + { + "name": "vm_service", + "version": "15.0.2", + "dependencies": [] + } + ], + "configVersion": 1 } \ No newline at end of file diff --git a/app/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/app/macos/Flutter/ephemeral/Flutter-Generated.xcconfig index 6da0bad..45cc6f2 100644 --- a/app/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ b/app/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -1,11 +1,11 @@ -// This is a generated file; do not edit or check into version control. -FLUTTER_ROOT=/Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable -FLUTTER_APPLICATION_PATH=/Users/kaska/Documents/Projects/Major/arbiter/app -COCOAPODS_PARALLEL_CODE_SIGN=true -FLUTTER_BUILD_DIR=build -FLUTTER_BUILD_NAME=1.0.0 -FLUTTER_BUILD_NUMBER=1 -DART_OBFUSCATION=false -TRACK_WIDGET_CREATION=true -TREE_SHAKE_ICONS=false -PACKAGE_CONFIG=.dart_tool/package_config.json +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=/Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable +FLUTTER_APPLICATION_PATH=/Users/kaska/Documents/Projects/Major/arbiter/app +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=1.0.0 +FLUTTER_BUILD_NUMBER=1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/app/macos/Flutter/ephemeral/flutter_export_environment.sh b/app/macos/Flutter/ephemeral/flutter_export_environment.sh index 1062508..3b5926d 100755 --- a/app/macos/Flutter/ephemeral/flutter_export_environment.sh +++ b/app/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -1,12 +1,12 @@ -#!/bin/sh -# This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=/Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable" -export "FLUTTER_APPLICATION_PATH=/Users/kaska/Documents/Projects/Major/arbiter/app" -export "COCOAPODS_PARALLEL_CODE_SIGN=true" -export "FLUTTER_BUILD_DIR=build" -export "FLUTTER_BUILD_NAME=1.0.0" -export "FLUTTER_BUILD_NUMBER=1" -export "DART_OBFUSCATION=false" -export "TRACK_WIDGET_CREATION=true" -export "TREE_SHAKE_ICONS=false" -export "PACKAGE_CONFIG=.dart_tool/package_config.json" +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=/Users/kaska/.local/share/mise/installs/flutter/3.38.9-stable" +export "FLUTTER_APPLICATION_PATH=/Users/kaska/Documents/Projects/Major/arbiter/app" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=1.0.0" +export "FLUTTER_BUILD_NUMBER=1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index c4f4c8f..1e1afb6 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -1,334 +1,334 @@ -# Arbiter - -Arbiter is a permissioned signing service for cryptocurrency wallets. It runs as a background service on the user's machine with an optional client application for vault management. - -**Core principle:** The vault NEVER exposes key material. It only produces signatures when a request satisfies the configured policies. ---- - -## 1. Peer Types - -Arbiter distinguishes two kinds of peers: - -- **Operator** — A client application used by the owner to manage the vault (create wallets, approve SDK clients, configure policies). -- **SDK Client** — A consumer of signing capabilities, typically an automation tool. In the future, this could include a browser-based wallet. -- **Recovery Operator** — A dormant recovery participant with narrowly scoped authority used only for custody recovery and operator replacement. - ---- - -## 2. Authentication - -### 2.1 Challenge-Response - -All peers authenticate via public-key cryptography using a challenge-response protocol: - -1. The peer sends its public key and requests a challenge. -2. The server looks up the key in its database. If found, it generates a fresh challenge from random bytes plus the current timestamp. -3. The peer signs the canonical challenge payload with its private key and sends the signature back. -4. The server verifies the signature: - - **Pass:** The connection is considered authenticated. - - **Fail:** The server closes the connection. - -Authentication challenges are per-connection, ephemeral values. They are not persisted in the peer tables, and peer records store no challenge state. - -### 2.2 Operator Bootstrap - -On first run — when no Operators are registered — the server generates a one-time bootstrap token. It is made available in two ways: - -- **Local setup:** Written to `~/.arbiter/bootstrap_token` for automatic discovery by a co-located Operator. -- **Remote setup:** Printed to the server's console output. - -The first Operator must present this token alongside the standard challenge-response to complete registration. - -### 2.3 SDK Client Registration - -There is no bootstrap mechanism for SDK clients. They must be explicitly approved by an already-registered Operator. - ---- - -## 3. Multi-Operator Governance - -When more than one Operator is registered, the vault is treated as having multiple operators. In that mode, sensitive actions are governed by voting rather than by a single operator decision. - -### 3.1 Voting Rules - -Voting is based on the total number of registered operators: - -- **1 operator:** no vote is needed; the single operator decides directly. -- **2 operators:** full consensus is required; both operators must approve. -- **3 or more operators:** quorum is `floor(N / 2) + 1`. - -For a decision to count, the operator's approval or rejection must be signed by that operator's associated key. Unsigned votes, or votes that fail signature verification, are ignored. - -Examples: - -- **3 operators:** 2 approvals required -- **4 operators:** 3 approvals required - -### 3.2 Actions Requiring a Vote - -In multi-operator mode, a successful vote is required for: - -- approving new SDK clients -- granting an SDK client visibility to a wallet -- approving a one-off transaction -- approving creation of a persistent grant -- approving operator replacement -- approving server updates -- updating Shamir secret-sharing parameters - -### 3.3 Special Rule for Key Rotation - -Key rotation always requires full quorum, regardless of the normal voting threshold. - -This is stricter than ordinary governance actions because rotating the root key requires every operator to participate in coordinated share refresh/update steps. The root key itself is not redistributed directly, but each operator's share material must be changed consistently. - -### 3.4 Root Key Custody - -When the vault has multiple operators, the vault root key is protected using Shamir secret sharing. - -The vault root key is encrypted in a way that requires reconstruction from user-held shares rather than from a single shared password. - -For ordinary operators, the Shamir threshold matches the ordinary governance quorum. For example: - -- **2 operators:** `2-of-2` -- **3 operators:** `2-of-3` -- **4 operators:** `3-of-4` - -In practice, the Shamir share set also includes Recovery Operator shares. This means the effective Shamir parameters are computed over the combined share pool while keeping the same threshold. For example: - -- **3 ordinary operators + 2 recovery shares:** `2-of-5` - -This ensures that the normal custody threshold follows the ordinary operator quorum, while still allowing dormant recovery shares to exist for break-glass recovery flows. - -### 3.5 Recovery Operators - -Recovery Operators are a separate peer type from ordinary vault operators. - -Their role is intentionally narrow. They can only: - -- participate in unsealing the vault -- vote for operator replacement - -Recovery Operators do not participate in routine governance such as approving SDK clients, granting wallet visibility, approving transactions, creating grants, approving server updates, or changing Shamir parameters. - -### 3.6 Sleeping and Waking Recovery Operators - -By default, Recovery Operators are **sleeping** and do not participate in any active flow. - -Any ordinary operator may request that Recovery Operators **wake up**. - -Any ordinary operator may also cancel a pending wake-up request. - -This creates a dispute window before recovery powers become active. The default wake-up delay is **14 days**. - -Recovery Operators are therefore part of the break-glass recovery path rather than the normal operating quorum. - -The high-level recovery flow is: - -```mermaid -sequenceDiagram - autonumber - actor Op as Ordinary Operator - participant Server - actor Other as Other Operator - actor Rec as Recovery Operator - - Op->>Server: Request recovery wake-up - Server-->>Op: Wake-up pending - Note over Server: Default dispute window: 14 days - - alt Wake-up cancelled during dispute window - Other->>Server: Cancel wake-up - Server-->>Op: Recovery cancelled - Server-->>Rec: Stay sleeping - else No cancellation for 14 days - Server-->>Rec: Wake up - Rec->>Server: Join recovery flow - critical Recovery authority - Rec->>Server: Participate in unseal - Rec->>Server: Vote on operator replacement - end - Server-->>Op: Recovery mode active - end -``` - -### 3.7 Committee Formation - -There are two ways to form a multi-operator committee: - -- convert an existing single-operator vault by adding new operators -- bootstrap an unbootstrapped vault directly into multi-operator mode - -In both cases, committee formation is a coordinated process. Arbiter does not allow multi-operator custody to emerge implicitly from unrelated registrations. - -### 3.8 Bootstrapping an Unbootstrapped Vault into Multi-Operator Mode - -When an unbootstrapped vault is initialized as a multi-operator vault, the setup proceeds as follows: - -1. An operator connects to the unbootstrapped vault using an Operator and the bootstrap token. -2. During bootstrap setup, that operator declares: - - the total number of ordinary operators - - the total number of Recovery Operators -3. The vault enters **multi-bootstrap mode**. -4. While in multi-bootstrap mode: - - every ordinary operator must connect with an Operator using the bootstrap token - - every Recovery Operator must also connect using the bootstrap token - - each participant is registered individually - - each participant's share is created and protected with that participant's credentials -5. The vault is considered fully bootstrapped only after all declared operator and recovery-share registrations have completed successfully. - -This means the operator and recovery set is fixed at bootstrap completion time, based on the counts declared when multi-bootstrap mode was entered. - -### 3.9 Special Bootstrap Constraint for Two-Operator Vaults - -If a vault is declared with exactly **2 ordinary operators**, Arbiter requires at least **1 Recovery Operator** to be configured during bootstrap. - -This prevents the worst-case custody failure in which a `2-of-2` operator set becomes permanently unrecoverable after loss of a single operator. - ---- - -## 4. Server Identity - -The server proves its identity using TLS with a self-signed certificate. The TLS private key is generated on first run and is long-term; no rotation mechanism exists yet due to the complexity of multi-peer coordination. - -Peers verify the server by its **public key fingerprint**: - -- **Operator (local):** Receives the fingerprint automatically through the bootstrap token. -- **Operator (remote) / SDK Client:** Must receive the fingerprint out-of-band. - -> A streamlined setup mechanism using a single connection string is planned but not yet implemented. - ---- - -## 5. Key Management - -### 5.1 Key Hierarchy - -There are three layers of keys: - -| Key | Encrypts | Encrypted by | -|---|---|---| -| **User key** (password) | Root key | — (derived from user input) | -| **Root key** | Wallet keys | User key | -| **Wallet keys** | — (used for signing) | Root key | - -This layered design enables: - -- **Password rotation** without re-encrypting every wallet key (only the root key is re-encrypted). -- **Root key rotation** without requiring the user to change their password. - -### 5.2 Encryption at Rest - -The database stores everything in encrypted form using symmetric AEAD. The encryption scheme is versioned to support transparent migration — when the vault unseals, Arbiter automatically re-encrypts any entries that are behind the current scheme version. See [IMPLEMENTATION.md](IMPLEMENTATION.md) for the specific scheme and versioning mechanism. - ---- - -## 6. Vault Lifecycle - -### 6.1 Sealed State - -On boot, the root key is encrypted and the server cannot perform any signing operations. This state is called **Sealed**. - -### 6.2 Unseal Flow - -To transition to the **Unsealed** state, an Operator must provide the password: - -1. The Operator initiates an unseal request. -2. The server generates a one-time key pair and returns the public key. -3. The Operator encrypts the user's password with this one-time public key and sends the ciphertext to the server. -4. The server decrypts and verifies the password: - - **Success:** The root key is decrypted and placed into a hardened memory cell. The server transitions to `Unsealed`. Any entries pending encryption scheme migration are re-encrypted. - - **Failure:** The server returns an error indicating the password is incorrect. - -### 6.3 Memory Protection - -Once unsealed, the root key must be protected in memory against: - -- Memory dumps -- Page swaps to disk -- Hibernation files - -See [IMPLEMENTATION.md](IMPLEMENTATION.md) for the current and planned memory protection approaches. - ---- - -## 7. Permission Engine - -### 7.1 Fundamental Rules - -- SDK clients have **no access by default**. -- Access is granted **explicitly** by an Operator. -- Grants are scoped to **specific wallets** and governed by **policies**. - -Each blockchain requires its own policy system due to differences in static transaction analysis. Currently, only EVM is supported; Solana support is planned. - -Arbiter is also responsible for ensuring that **transaction nonces are never reused**. - -### 7.2 EVM Policies - -Every EVM grant is scoped to a specific **wallet** and **chain ID**. - -#### 7.2.0 Transaction Signing Sequence - -The high-level interaction order is: - -```mermaid -sequenceDiagram - autonumber - actor SDK as SDK Client - participant Server - participant operator as Operator - - SDK->>Server: SignTransactionRequest - Server->>Server: Resolve wallet and wallet visibility - alt Visibility approval required - Server->>operator: Ask for wallet visibility approval - operator-->>Server: Vote result - end - Server->>Server: Evaluate transaction - Server->>Server: Load grant and limits context - alt Grant approval required - Server->>operator: Ask for execution / grant approval - operator-->>Server: Vote result - opt Create persistent grant - Server->>Server: Create and store grant - end - Server->>Server: Retry evaluation - end - critical Final authorization path - Server->>Server: Check limits and record execution - Server-->>Server: Signature or evaluation error - end - Server-->>SDK: Signature or error -``` - -#### 7.2.1 Transaction Sub-Grants - -Arbiter maintains an ever-expanding database of known contracts and their ABIs. Based on contract knowledge, transaction requests fall into three categories: - -**1. Known contract (ABI available)** - -The transaction can be decoded and presented with semantic meaning. For example: *"Client X wants to transfer Y USDT to address Z."* - -Available restrictions: -- Volume limits (e.g., "no more than 10,000 tokens ever") -- Rate limits (e.g., "no more than 100 tokens per hour") - -**2. Unknown contract (no ABI)** - -The transaction cannot be decoded, so its effects are opaque — it could do anything, including draining all tokens. The user is warned, and if approved, access is granted to all interactions with the contract (matched by the `to` field). - -Available restrictions: -- Transaction count limits (e.g., "no more than 100 transactions ever") -- Rate limits (e.g., "no more than 5 transactions per hour") - -**3. Plain ether transfer (no calldata)** - -These transactions have no `calldata` and therefore cannot interact with contracts. They can be subject to the same volume and rate restrictions as above. - -#### 7.2.2 Global Limits - -In addition to sub-grant-specific restrictions, the following limits can be applied across all grant types: - -- **Gas limit** — Maximum gas per transaction. -- **Time-window restrictions** — e.g., signing allowed only 08:00–20:00 on Mondays and Thursdays. +# Arbiter + +Arbiter is a permissioned signing service for cryptocurrency wallets. It runs as a background service on the user's machine with an optional client application for vault management. + +**Core principle:** The vault NEVER exposes key material. It only produces signatures when a request satisfies the configured policies. +--- + +## 1. Peer Types + +Arbiter distinguishes two kinds of peers: + +- **Operator** — A client application used by the owner to manage the vault (create wallets, approve SDK clients, configure policies). +- **SDK Client** — A consumer of signing capabilities, typically an automation tool. In the future, this could include a browser-based wallet. +- **Recovery Operator** — A dormant recovery participant with narrowly scoped authority used only for custody recovery and operator replacement. + +--- + +## 2. Authentication + +### 2.1 Challenge-Response + +All peers authenticate via public-key cryptography using a challenge-response protocol: + +1. The peer sends its public key and requests a challenge. +2. The server looks up the key in its database. If found, it generates a fresh challenge from random bytes plus the current timestamp. +3. The peer signs the canonical challenge payload with its private key and sends the signature back. +4. The server verifies the signature: + - **Pass:** The connection is considered authenticated. + - **Fail:** The server closes the connection. + +Authentication challenges are per-connection, ephemeral values. They are not persisted in the peer tables, and peer records store no challenge state. + +### 2.2 Operator Bootstrap + +On first run — when no Operators are registered — the server generates a one-time bootstrap token. It is made available in two ways: + +- **Local setup:** Written to `~/.arbiter/bootstrap_token` for automatic discovery by a co-located Operator. +- **Remote setup:** Printed to the server's console output. + +The first Operator must present this token alongside the standard challenge-response to complete registration. + +### 2.3 SDK Client Registration + +There is no bootstrap mechanism for SDK clients. They must be explicitly approved by an already-registered Operator. + +--- + +## 3. Multi-Operator Governance + +When more than one Operator is registered, the vault is treated as having multiple operators. In that mode, sensitive actions are governed by voting rather than by a single operator decision. + +### 3.1 Voting Rules + +Voting is based on the total number of registered operators: + +- **1 operator:** no vote is needed; the single operator decides directly. +- **2 operators:** full consensus is required; both operators must approve. +- **3 or more operators:** quorum is `floor(N / 2) + 1`. + +For a decision to count, the operator's approval or rejection must be signed by that operator's associated key. Unsigned votes, or votes that fail signature verification, are ignored. + +Examples: + +- **3 operators:** 2 approvals required +- **4 operators:** 3 approvals required + +### 3.2 Actions Requiring a Vote + +In multi-operator mode, a successful vote is required for: + +- approving new SDK clients +- granting an SDK client visibility to a wallet +- approving a one-off transaction +- approving creation of a persistent grant +- approving operator replacement +- approving server updates +- updating Shamir secret-sharing parameters + +### 3.3 Special Rule for Key Rotation + +Key rotation always requires full quorum, regardless of the normal voting threshold. + +This is stricter than ordinary governance actions because rotating the root key requires every operator to participate in coordinated share refresh/update steps. The root key itself is not redistributed directly, but each operator's share material must be changed consistently. + +### 3.4 Root Key Custody + +When the vault has multiple operators, the vault root key is protected using Shamir secret sharing. + +The vault root key is encrypted in a way that requires reconstruction from user-held shares rather than from a single shared password. + +For ordinary operators, the Shamir threshold matches the ordinary governance quorum. For example: + +- **2 operators:** `2-of-2` +- **3 operators:** `2-of-3` +- **4 operators:** `3-of-4` + +In practice, the Shamir share set also includes Recovery Operator shares. This means the effective Shamir parameters are computed over the combined share pool while keeping the same threshold. For example: + +- **3 ordinary operators + 2 recovery shares:** `2-of-5` + +This ensures that the normal custody threshold follows the ordinary operator quorum, while still allowing dormant recovery shares to exist for break-glass recovery flows. + +### 3.5 Recovery Operators + +Recovery Operators are a separate peer type from ordinary vault operators. + +Their role is intentionally narrow. They can only: + +- participate in unsealing the vault +- vote for operator replacement + +Recovery Operators do not participate in routine governance such as approving SDK clients, granting wallet visibility, approving transactions, creating grants, approving server updates, or changing Shamir parameters. + +### 3.6 Sleeping and Waking Recovery Operators + +By default, Recovery Operators are **sleeping** and do not participate in any active flow. + +Any ordinary operator may request that Recovery Operators **wake up**. + +Any ordinary operator may also cancel a pending wake-up request. + +This creates a dispute window before recovery powers become active. The default wake-up delay is **14 days**. + +Recovery Operators are therefore part of the break-glass recovery path rather than the normal operating quorum. + +The high-level recovery flow is: + +```mermaid +sequenceDiagram + autonumber + actor Op as Ordinary Operator + participant Server + actor Other as Other Operator + actor Rec as Recovery Operator + + Op->>Server: Request recovery wake-up + Server-->>Op: Wake-up pending + Note over Server: Default dispute window: 14 days + + alt Wake-up cancelled during dispute window + Other->>Server: Cancel wake-up + Server-->>Op: Recovery cancelled + Server-->>Rec: Stay sleeping + else No cancellation for 14 days + Server-->>Rec: Wake up + Rec->>Server: Join recovery flow + critical Recovery authority + Rec->>Server: Participate in unseal + Rec->>Server: Vote on operator replacement + end + Server-->>Op: Recovery mode active + end +``` + +### 3.7 Committee Formation + +There are two ways to form a multi-operator committee: + +- convert an existing single-operator vault by adding new operators +- bootstrap an unbootstrapped vault directly into multi-operator mode + +In both cases, committee formation is a coordinated process. Arbiter does not allow multi-operator custody to emerge implicitly from unrelated registrations. + +### 3.8 Bootstrapping an Unbootstrapped Vault into Multi-Operator Mode + +When an unbootstrapped vault is initialized as a multi-operator vault, the setup proceeds as follows: + +1. An operator connects to the unbootstrapped vault using an Operator and the bootstrap token. +2. During bootstrap setup, that operator declares: + - the total number of ordinary operators + - the total number of Recovery Operators +3. The vault enters **multi-bootstrap mode**. +4. While in multi-bootstrap mode: + - every ordinary operator must connect with an Operator using the bootstrap token + - every Recovery Operator must also connect using the bootstrap token + - each participant is registered individually + - each participant's share is created and protected with that participant's credentials +5. The vault is considered fully bootstrapped only after all declared operator and recovery-share registrations have completed successfully. + +This means the operator and recovery set is fixed at bootstrap completion time, based on the counts declared when multi-bootstrap mode was entered. + +### 3.9 Special Bootstrap Constraint for Two-Operator Vaults + +If a vault is declared with exactly **2 ordinary operators**, Arbiter requires at least **1 Recovery Operator** to be configured during bootstrap. + +This prevents the worst-case custody failure in which a `2-of-2` operator set becomes permanently unrecoverable after loss of a single operator. + +--- + +## 4. Server Identity + +The server proves its identity using TLS with a self-signed certificate. The TLS private key is generated on first run and is long-term; no rotation mechanism exists yet due to the complexity of multi-peer coordination. + +Peers verify the server by its **public key fingerprint**: + +- **Operator (local):** Receives the fingerprint automatically through the bootstrap token. +- **Operator (remote) / SDK Client:** Must receive the fingerprint out-of-band. + +> A streamlined setup mechanism using a single connection string is planned but not yet implemented. + +--- + +## 5. Key Management + +### 5.1 Key Hierarchy + +There are three layers of keys: + +| Key | Encrypts | Encrypted by | +|---|---|---| +| **User key** (password) | Root key | — (derived from user input) | +| **Root key** | Wallet keys | User key | +| **Wallet keys** | — (used for signing) | Root key | + +This layered design enables: + +- **Password rotation** without re-encrypting every wallet key (only the root key is re-encrypted). +- **Root key rotation** without requiring the user to change their password. + +### 5.2 Encryption at Rest + +The database stores everything in encrypted form using symmetric AEAD. The encryption scheme is versioned to support transparent migration — when the vault unseals, Arbiter automatically re-encrypts any entries that are behind the current scheme version. See [IMPLEMENTATION.md](IMPLEMENTATION.md) for the specific scheme and versioning mechanism. + +--- + +## 6. Vault Lifecycle + +### 6.1 Sealed State + +On boot, the root key is encrypted and the server cannot perform any signing operations. This state is called **Sealed**. + +### 6.2 Unseal Flow + +To transition to the **Unsealed** state, an Operator must provide the password: + +1. The Operator initiates an unseal request. +2. The server generates a one-time key pair and returns the public key. +3. The Operator encrypts the user's password with this one-time public key and sends the ciphertext to the server. +4. The server decrypts and verifies the password: + - **Success:** The root key is decrypted and placed into a hardened memory cell. The server transitions to `Unsealed`. Any entries pending encryption scheme migration are re-encrypted. + - **Failure:** The server returns an error indicating the password is incorrect. + +### 6.3 Memory Protection + +Once unsealed, the root key must be protected in memory against: + +- Memory dumps +- Page swaps to disk +- Hibernation files + +See [IMPLEMENTATION.md](IMPLEMENTATION.md) for the current and planned memory protection approaches. + +--- + +## 7. Permission Engine + +### 7.1 Fundamental Rules + +- SDK clients have **no access by default**. +- Access is granted **explicitly** by an Operator. +- Grants are scoped to **specific wallets** and governed by **policies**. + +Each blockchain requires its own policy system due to differences in static transaction analysis. Currently, only EVM is supported; Solana support is planned. + +Arbiter is also responsible for ensuring that **transaction nonces are never reused**. + +### 7.2 EVM Policies + +Every EVM grant is scoped to a specific **wallet** and **chain ID**. + +#### 7.2.0 Transaction Signing Sequence + +The high-level interaction order is: + +```mermaid +sequenceDiagram + autonumber + actor SDK as SDK Client + participant Server + participant operator as Operator + + SDK->>Server: SignTransactionRequest + Server->>Server: Resolve wallet and wallet visibility + alt Visibility approval required + Server->>operator: Ask for wallet visibility approval + operator-->>Server: Vote result + end + Server->>Server: Evaluate transaction + Server->>Server: Load grant and limits context + alt Grant approval required + Server->>operator: Ask for execution / grant approval + operator-->>Server: Vote result + opt Create persistent grant + Server->>Server: Create and store grant + end + Server->>Server: Retry evaluation + end + critical Final authorization path + Server->>Server: Check limits and record execution + Server-->>Server: Signature or evaluation error + end + Server-->>SDK: Signature or error +``` + +#### 7.2.1 Transaction Sub-Grants + +Arbiter maintains an ever-expanding database of known contracts and their ABIs. Based on contract knowledge, transaction requests fall into three categories: + +**1. Known contract (ABI available)** + +The transaction can be decoded and presented with semantic meaning. For example: *"Client X wants to transfer Y USDT to address Z."* + +Available restrictions: +- Volume limits (e.g., "no more than 10,000 tokens ever") +- Rate limits (e.g., "no more than 100 tokens per hour") + +**2. Unknown contract (no ABI)** + +The transaction cannot be decoded, so its effects are opaque — it could do anything, including draining all tokens. The user is warned, and if approved, access is granted to all interactions with the contract (matched by the `to` field). + +Available restrictions: +- Transaction count limits (e.g., "no more than 100 transactions ever") +- Rate limits (e.g., "no more than 5 transactions per hour") + +**3. Plain ether transfer (no calldata)** + +These transactions have no `calldata` and therefore cannot interact with contracts. They can be subject to the same volume and rate restrictions as above. + +#### 7.2.2 Global Limits + +In addition to sub-grant-specific restrictions, the following limits can be applied across all grant types: + +- **Gas limit** — Maximum gas per transaction. +- **Time-window restrictions** — e.g., signing allowed only 08:00–20:00 on Mondays and Thursdays. diff --git a/docs/IMPLEMENTATION.md b/docs/IMPLEMENTATION.md index b55f9bd..ef90589 100644 --- a/docs/IMPLEMENTATION.md +++ b/docs/IMPLEMENTATION.md @@ -1,226 +1,226 @@ -# Implementation Details - -This document covers concrete technology choices and dependencies. For the architectural design, see [ARCHITECTURE.md](ARCHITECTURE.md). - ---- - -## Client Connection Flow - -### Authentication Result Semantics - -Authentication no longer uses an implicit success-only response shape. Both `client` and `operator` return explicit auth status enums over the wire. - -- **Client:** `AuthResult` may return `SUCCESS`, `INVALID_KEY`, `INVALID_SIGNATURE`, `APPROVAL_DENIED`, `NO_OPERATORS_ONLINE`, or `INTERNAL` -- **Operator:** `AuthResult` may return `SUCCESS`, `INVALID_KEY`, `INVALID_SIGNATURE`, `BOOTSTRAP_REQUIRED`, `TOKEN_INVALID`, or `INTERNAL` - -This makes transport-level failures and actor/domain-level auth failures distinct: - -- **Transport/protocol failures** are surfaced as stream/status errors -- **Authentication failures** are surfaced as successful protocol responses carrying an explicit auth status - -Clients are expected to handle these status codes directly and present the concrete failure reason to the user. - -### New Client Approval - -When a client whose public key is not yet in the database connects, all connected operators are asked to approve the connection. The first operator to respond determines the outcome; remaining requests are cancelled via a watch channel. - -```mermaid -flowchart TD - A([Client connects]) --> B[Receive AuthChallengeRequest] - B --> C{pubkey in DB?} - - C -- yes --> G[Generate AuthChallenge] - - C -- no --> E[Ask all Operators:\nClientConnectionRequest] - E --> F{First response} - F -- denied --> Z([Reject connection]) - F -- approved --> F2[Cancel remaining\nOperator requests] - F2 --> F3[INSERT client] - F3 --> G - - G --> H[Send AuthChallenge\ntimestamp + random bytes] - H --> I[Receive AuthChallengeSolution] - I --> K{Signature valid?} - K -- no --> Z - K -- yes --> J([Session started]) -``` - -Auth challenges are generated from fresh random bytes plus a nanosecond timestamp. The server keeps the issued challenge only in the in-flight authentication state for that connection, then verifies the signature against the same canonical challenge payload. - -The authentication schema stores peer identity, not replay counters: - -- `program_client` stores the SDK client's public key, metadata binding, and timestamps. -- `operator_client` stores the Operator public key and timestamps. -- Neither table stores an authentication nonce, and challenge generation does not update either table. - ---- - -## Cryptography - -### Authentication -- **Client protocol:** ML-DSA - -### User-Agent Authentication - -Operator authentication supports multiple signature schemes because platform-provided "hardware-bound" keys do not expose a uniform algorithm across operating systems and hardware. - -- **Supported schemes:** ML-DSA -- **Why:** Secure Enclave (MacOS) support them natively, on other platforms we could emulate while they roll-out - -### Encryption at Rest -- **Scheme:** Symmetric AEAD — currently **XChaCha20-Poly1305** -- **Version tracking:** Each `aead_encrypted` database entry carries a `scheme` field denoting the version, enabling transparent migration on unseal - -### Server Identity -- **Transport:** TLS with a self-signed certificate -- **Key type:** Generated on first run; long-term (no rotation mechanism yet) - ---- - -## Communication - -- **Protocol:** gRPC with Protocol Buffers -- **Request/response matching:** multiplexed over a single bidirectional stream using per-connection request IDs -- **Server identity distribution:** `ServerInfo` protobuf struct containing the TLS public key fingerprint -- **Future consideration:** grpc-web lacks bidirectional stream support, so a browser-based wallet may require protojson over WebSocket - -### Request Multiplexing - -Both `client` and `operator` connections support multiple in-flight requests over one gRPC bidi stream. - -- Every request carries a monotonically increasing request ID -- Every normal response echoes the request ID it corresponds to -- Out-of-band server messages omit the response ID entirely -- The server rejects already-seen request IDs at the transport adapter boundary before business logic sees the message - -This keeps request correlation entirely in transport/client connection code while leaving actor and domain handlers unaware of request IDs. - ---- - -## EVM Policy Engine - -### Overview - -The EVM engine classifies incoming transactions, enforces grant constraints, and records executions. It is the sole path through which a wallet key is used for signing. - -The central abstraction is the `Policy` trait. Each implementation handles one semantic transaction category and owns its own database tables for grant storage and transaction logging. - -### Transaction Evaluation Flow - -`Engine::evaluate_transaction` runs the following steps in order: - -1. **Classify** — Each registered policy's `analyze(context)` inspects the transaction fields (`chain`, `to`, `value`, `calldata`). The first one returning `Some(meaning)` wins. If none match, the transaction is rejected as `UnsupportedTransactionType`. -2. **Find grant** — `Policy::try_find_grant` queries for a non-revoked grant covering this wallet, client, chain, and target address. -3. **Check shared constraints** — `check_shared_constraints` runs in the engine before any policy-specific logic. It enforces the validity window, gas fee caps, and transaction count rate limit (see below). -4. **Evaluate** — `Policy::evaluate` checks the decoded meaning against the grant's policy-specific constraints and returns any violations. -5. **Record** — If `RunKind::Execution` and there are no violations, the engine writes to `evm_transaction_log` and calls `Policy::record_transaction` for any policy-specific logging (e.g., token transfer volume). - -The detailed branch structure is shown below: - -```mermaid -flowchart TD - A[SDK Client sends sign transaction request] --> B[Server resolves wallet] - B --> C{Wallet exists?} - - C -- No --> Z1[Return wallet not found error] - C -- Yes --> D[Check SDK client wallet visibility] - - D --> E{Wallet visible to SDK client?} - E -- No --> F[Start wallet visibility voting flow] - F --> G{Vote approved?} - G -- No --> Z2[Return wallet access denied error] - G -- Yes --> H[Persist wallet visibility] - E -- Yes --> I[Classify transaction meaning] - H --> I - - I --> J{Meaning supported?} - J -- No --> Z3[Return unsupported transaction error] - J -- Yes --> K[Find matching grant] - - K --> L{Grant exists?} - L -- Yes --> M[Check grant limits] - L -- No --> N[Start execution or grant voting flow] - - N --> O{Operator decision} - O -- Reject --> Z4[Return no matching grant error] - O -- Allow once --> M - O -- Create grant --> P[Create grant with user-selected limits] - P --> Q[Persist grant] - Q --> M - - M --> R{Limits exceeded?} - R -- Yes --> Z5[Return evaluation error] - R -- No --> S[Record transaction in logs] - S --> T[Produce signature] - T --> U[Return signature to SDK client] - - note1[Limit checks include volume, count, and gas constraints.] - note2[Grant lookup depends on classified meaning, such as ether transfer or token transfer.] - - K -. uses .-> note2 - M -. checks .-> note1 -``` - -### Policy Trait - -| Method | Purpose | -|---|---| -| `analyze` | Pure — classifies a transaction into a typed `Meaning`, or `None` if this policy doesn't apply | -| `evaluate` | Checks the `Meaning` against a `Grant`; returns a list of `EvalViolation`s | -| `create_grant` | Inserts policy-specific rows; returns the specific grant ID | -| `try_find_grant` | Finds a matching non-revoked grant for the given `EvalContext` | -| `find_all_grants` | Returns all non-revoked grants (used for listing) | -| `record_transaction` | Persists policy-specific data after execution | - -`analyze` and `evaluate` are intentionally separate: classification is pure and cheap, while evaluation may involve DB queries (e.g., fetching past transfer volume). - -### Registered Policies - -**EtherTransfer** — plain ETH transfers (empty calldata) - -- Grant requires: allowlist of recipient addresses + one volumetric rate limit (max ETH over a time window) -- Violations: recipient not in allowlist, cumulative ETH volume exceeded - -**TokenTransfer** — ERC-20 `transfer(address,uint256)` calls - -- Recognised by ABI-decoding the `transfer(address,uint256)` selector against a static registry of known token contracts (`arbiter_tokens_registry`) -- Grant requires: token contract address, optional recipient restriction, zero or more volumetric rate limits -- Violations: recipient mismatch, any volumetric limit exceeded - -### Grant Model - -Every grant has two layers: - -- **Shared (`evm_basic_grant`)** — wallet, chain, validity period, gas fee caps, transaction count rate limit. One row per grant regardless of type. -- **Specific** — policy-owned tables (`evm_ether_transfer_grant`, `evm_token_transfer_grant`) holding type-specific configuration. - -`find_all_grants` uses a `#[diesel::auto_type]` base join between the specific and shared tables, then batch-loads related rows (targets, volume limits) in two additional queries to avoid N+1. - -The engine exposes `list_all_grants` which collects across all policy types into `Vec>` via a blanket `From> for Grant` conversion. - -### Shared Constraints (enforced by the engine) - -These are checked centrally in `check_shared_constraints` before policy evaluation: - -| Constraint | Fields | Behaviour | -|---|---|---| -| Validity window | `valid_from`, `valid_until` | Emits `InvalidTime` if current time is outside the range | -| Gas fee cap | `max_gas_fee_per_gas`, `max_priority_fee_per_gas` | Emits `GasLimitExceeded` if either cap is breached | -| Tx count rate limit | `rate_limit` (`count` + `window`) | Counts rows in `evm_transaction_log` within the window; emits `RateLimitExceeded` if at or above the limit | - ---- - -### Known Limitations - -- **Only EIP-1559 transactions are supported.** Legacy and EIP-2930 types are rejected outright. -- **No opaque-calldata (unknown contract) grant type.** The architecture describes a category for unrecognised contracts, but no policy implements it yet. Any transaction that is not a plain ETH transfer or a known ERC-20 transfer is unconditionally rejected. -- **Token registry is static.** Tokens are recognised only if they appear in the hard-coded `arbiter_tokens_registry` crate. There is no mechanism to register additional contracts at runtime. - ---- - -## Memory Protection - -The unsealed root key must be held in a hardened memory cell resistant to dumps, page swaps, and hibernation. - -- **Current:** A dedicated memory-protection abstraction is in place, with `memsafe` used behind that abstraction today -- **Planned:** Additional backends can be introduced behind the same abstraction, including a custom implementation based on `mlock` (Unix) and `VirtualProtect` (Windows) +# Implementation Details + +This document covers concrete technology choices and dependencies. For the architectural design, see [ARCHITECTURE.md](ARCHITECTURE.md). + +--- + +## Client Connection Flow + +### Authentication Result Semantics + +Authentication no longer uses an implicit success-only response shape. Both `client` and `operator` return explicit auth status enums over the wire. + +- **Client:** `AuthResult` may return `SUCCESS`, `INVALID_KEY`, `INVALID_SIGNATURE`, `APPROVAL_DENIED`, `NO_OPERATORS_ONLINE`, or `INTERNAL` +- **Operator:** `AuthResult` may return `SUCCESS`, `INVALID_KEY`, `INVALID_SIGNATURE`, `BOOTSTRAP_REQUIRED`, `TOKEN_INVALID`, or `INTERNAL` + +This makes transport-level failures and actor/domain-level auth failures distinct: + +- **Transport/protocol failures** are surfaced as stream/status errors +- **Authentication failures** are surfaced as successful protocol responses carrying an explicit auth status + +Clients are expected to handle these status codes directly and present the concrete failure reason to the user. + +### New Client Approval + +When a client whose public key is not yet in the database connects, all connected operators are asked to approve the connection. The first operator to respond determines the outcome; remaining requests are cancelled via a watch channel. + +```mermaid +flowchart TD + A([Client connects]) --> B[Receive AuthChallengeRequest] + B --> C{pubkey in DB?} + + C -- yes --> G[Generate AuthChallenge] + + C -- no --> E[Ask all Operators:\nClientConnectionRequest] + E --> F{First response} + F -- denied --> Z([Reject connection]) + F -- approved --> F2[Cancel remaining\nOperator requests] + F2 --> F3[INSERT client] + F3 --> G + + G --> H[Send AuthChallenge\ntimestamp + random bytes] + H --> I[Receive AuthChallengeSolution] + I --> K{Signature valid?} + K -- no --> Z + K -- yes --> J([Session started]) +``` + +Auth challenges are generated from fresh random bytes plus a nanosecond timestamp. The server keeps the issued challenge only in the in-flight authentication state for that connection, then verifies the signature against the same canonical challenge payload. + +The authentication schema stores peer identity, not replay counters: + +- `program_client` stores the SDK client's public key, metadata binding, and timestamps. +- `operator_client` stores the Operator public key and timestamps. +- Neither table stores an authentication nonce, and challenge generation does not update either table. + +--- + +## Cryptography + +### Authentication +- **Client protocol:** ML-DSA + +### User-Agent Authentication + +Operator authentication supports multiple signature schemes because platform-provided "hardware-bound" keys do not expose a uniform algorithm across operating systems and hardware. + +- **Supported schemes:** ML-DSA +- **Why:** Secure Enclave (MacOS) support them natively, on other platforms we could emulate while they roll-out + +### Encryption at Rest +- **Scheme:** Symmetric AEAD — currently **XChaCha20-Poly1305** +- **Version tracking:** Each `aead_encrypted` database entry carries a `scheme` field denoting the version, enabling transparent migration on unseal + +### Server Identity +- **Transport:** TLS with a self-signed certificate +- **Key type:** Generated on first run; long-term (no rotation mechanism yet) + +--- + +## Communication + +- **Protocol:** gRPC with Protocol Buffers +- **Request/response matching:** multiplexed over a single bidirectional stream using per-connection request IDs +- **Server identity distribution:** `ServerInfo` protobuf struct containing the TLS public key fingerprint +- **Future consideration:** grpc-web lacks bidirectional stream support, so a browser-based wallet may require protojson over WebSocket + +### Request Multiplexing + +Both `client` and `operator` connections support multiple in-flight requests over one gRPC bidi stream. + +- Every request carries a monotonically increasing request ID +- Every normal response echoes the request ID it corresponds to +- Out-of-band server messages omit the response ID entirely +- The server rejects already-seen request IDs at the transport adapter boundary before business logic sees the message + +This keeps request correlation entirely in transport/client connection code while leaving actor and domain handlers unaware of request IDs. + +--- + +## EVM Policy Engine + +### Overview + +The EVM engine classifies incoming transactions, enforces grant constraints, and records executions. It is the sole path through which a wallet key is used for signing. + +The central abstraction is the `Policy` trait. Each implementation handles one semantic transaction category and owns its own database tables for grant storage and transaction logging. + +### Transaction Evaluation Flow + +`Engine::evaluate_transaction` runs the following steps in order: + +1. **Classify** — Each registered policy's `analyze(context)` inspects the transaction fields (`chain`, `to`, `value`, `calldata`). The first one returning `Some(meaning)` wins. If none match, the transaction is rejected as `UnsupportedTransactionType`. +2. **Find grant** — `Policy::try_find_grant` queries for a non-revoked grant covering this wallet, client, chain, and target address. +3. **Check shared constraints** — `check_shared_constraints` runs in the engine before any policy-specific logic. It enforces the validity window, gas fee caps, and transaction count rate limit (see below). +4. **Evaluate** — `Policy::evaluate` checks the decoded meaning against the grant's policy-specific constraints and returns any violations. +5. **Record** — If `RunKind::Execution` and there are no violations, the engine writes to `evm_transaction_log` and calls `Policy::record_transaction` for any policy-specific logging (e.g., token transfer volume). + +The detailed branch structure is shown below: + +```mermaid +flowchart TD + A[SDK Client sends sign transaction request] --> B[Server resolves wallet] + B --> C{Wallet exists?} + + C -- No --> Z1[Return wallet not found error] + C -- Yes --> D[Check SDK client wallet visibility] + + D --> E{Wallet visible to SDK client?} + E -- No --> F[Start wallet visibility voting flow] + F --> G{Vote approved?} + G -- No --> Z2[Return wallet access denied error] + G -- Yes --> H[Persist wallet visibility] + E -- Yes --> I[Classify transaction meaning] + H --> I + + I --> J{Meaning supported?} + J -- No --> Z3[Return unsupported transaction error] + J -- Yes --> K[Find matching grant] + + K --> L{Grant exists?} + L -- Yes --> M[Check grant limits] + L -- No --> N[Start execution or grant voting flow] + + N --> O{Operator decision} + O -- Reject --> Z4[Return no matching grant error] + O -- Allow once --> M + O -- Create grant --> P[Create grant with user-selected limits] + P --> Q[Persist grant] + Q --> M + + M --> R{Limits exceeded?} + R -- Yes --> Z5[Return evaluation error] + R -- No --> S[Record transaction in logs] + S --> T[Produce signature] + T --> U[Return signature to SDK client] + + note1[Limit checks include volume, count, and gas constraints.] + note2[Grant lookup depends on classified meaning, such as ether transfer or token transfer.] + + K -. uses .-> note2 + M -. checks .-> note1 +``` + +### Policy Trait + +| Method | Purpose | +|---|---| +| `analyze` | Pure — classifies a transaction into a typed `Meaning`, or `None` if this policy doesn't apply | +| `evaluate` | Checks the `Meaning` against a `Grant`; returns a list of `EvalViolation`s | +| `create_grant` | Inserts policy-specific rows; returns the specific grant ID | +| `try_find_grant` | Finds a matching non-revoked grant for the given `EvalContext` | +| `find_all_grants` | Returns all non-revoked grants (used for listing) | +| `record_transaction` | Persists policy-specific data after execution | + +`analyze` and `evaluate` are intentionally separate: classification is pure and cheap, while evaluation may involve DB queries (e.g., fetching past transfer volume). + +### Registered Policies + +**EtherTransfer** — plain ETH transfers (empty calldata) + +- Grant requires: allowlist of recipient addresses + one volumetric rate limit (max ETH over a time window) +- Violations: recipient not in allowlist, cumulative ETH volume exceeded + +**TokenTransfer** — ERC-20 `transfer(address,uint256)` calls + +- Recognised by ABI-decoding the `transfer(address,uint256)` selector against a static registry of known token contracts (`arbiter_tokens_registry`) +- Grant requires: token contract address, optional recipient restriction, zero or more volumetric rate limits +- Violations: recipient mismatch, any volumetric limit exceeded + +### Grant Model + +Every grant has two layers: + +- **Shared (`evm_basic_grant`)** — wallet, chain, validity period, gas fee caps, transaction count rate limit. One row per grant regardless of type. +- **Specific** — policy-owned tables (`evm_ether_transfer_grant`, `evm_token_transfer_grant`) holding type-specific configuration. + +`find_all_grants` uses a `#[diesel::auto_type]` base join between the specific and shared tables, then batch-loads related rows (targets, volume limits) in two additional queries to avoid N+1. + +The engine exposes `list_all_grants` which collects across all policy types into `Vec>` via a blanket `From> for Grant` conversion. + +### Shared Constraints (enforced by the engine) + +These are checked centrally in `check_shared_constraints` before policy evaluation: + +| Constraint | Fields | Behaviour | +|---|---|---| +| Validity window | `valid_from`, `valid_until` | Emits `InvalidTime` if current time is outside the range | +| Gas fee cap | `max_gas_fee_per_gas`, `max_priority_fee_per_gas` | Emits `GasLimitExceeded` if either cap is breached | +| Tx count rate limit | `rate_limit` (`count` + `window`) | Counts rows in `evm_transaction_log` within the window; emits `RateLimitExceeded` if at or above the limit | + +--- + +### Known Limitations + +- **Only EIP-1559 transactions are supported.** Legacy and EIP-2930 types are rejected outright. +- **No opaque-calldata (unknown contract) grant type.** The architecture describes a category for unrecognised contracts, but no policy implements it yet. Any transaction that is not a plain ETH transfer or a known ERC-20 transfer is unconditionally rejected. +- **Token registry is static.** Tokens are recognised only if they appear in the hard-coded `arbiter_tokens_registry` crate. There is no mechanism to register additional contracts at runtime. + +--- + +## Memory Protection + +The unsealed root key must be held in a hardened memory cell resistant to dumps, page swaps, and hibernation. + +- **Current:** A dedicated memory-protection abstraction is in place, with `memsafe` used behind that abstraction today +- **Planned:** Additional backends can be introduced behind the same abstraction, including a custom implementation based on `mlock` (Unix) and `VirtualProtect` (Windows) diff --git a/docs/superpowers/plans/2026-03-28-grant-creation-refactor.md b/docs/superpowers/plans/2026-03-28-grant-creation-refactor.md index 6783949..674ac9d 100644 --- a/docs/superpowers/plans/2026-03-28-grant-creation-refactor.md +++ b/docs/superpowers/plans/2026-03-28-grant-creation-refactor.md @@ -1,1308 +1,1308 @@ -# Grant Creation Screen Refactor Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Decompose the monolithic `create/screen.dart` into a Riverpod-managed provider, composable `flutter_form_builder` field widgets, and per-grant-type handlers with a clean interface. - -**Architecture:** A `GrantCreation` provider manages only the state that cannot live in a form field: `selectedClientId` (drives wallet-access filtering) and `grantType` (SegmentedButton). All other shared settings — including validity dates — are `FormBuilder` fields; the custom `FormBuilderDateTimeField` wraps the native date/time picker dialog. Token volume limits are owned by a `TokenGrantLimits` provider that lives entirely inside `token_transfer_grant.dart`. Each grant type implements `GrantFormHandler`, whose `buildSpecificGrant` receives `formValues` and a `WidgetRef` so handlers can read their own providers. - -**Tech Stack:** Flutter, Riverpod (riverpod_annotation 4.x), flutter_form_builder 10.x, freezed 3.x, flutter_hooks, Protobuf (Dart), fixnum - ---- - -## File Map - -| Path | Action | Responsibility | -|------|--------|----------------| -| `create/utils.dart` | Create | Parsing/conversion helpers (hex addresses, big-int bytes, timestamps, rate limits) | -| `create/provider.dart` | Create | `GrantCreationState` (freezed), `GrantCreation` (@riverpod) — only `selectedClientId` + `grantType` | -| `create/fields/client_picker_field.dart` | Create | `FormBuilderDropdown` for SDK client; syncs selection to `GrantCreation` provider | -| `create/fields/wallet_access_picker_field.dart` | Create | `FormBuilderDropdown` for wallet access; filters by provider's `selectedClientId` | -| `create/fields/chain_id_field.dart` | Create | `FormBuilderTextField` for chain ID | -| `create/fields/date_time_field.dart` | Create | Custom `FormBuilderDateTimeField` — wraps date+time picker dialogs as a `FormBuilderField` | -| `create/fields/validity_window_field.dart` | Create | Row of two `FormBuilderDateTimeField` widgets (names `validFrom`, `validUntil`) | -| `create/fields/gas_fee_options_field.dart` | Create | Two `FormBuilderTextField` fields for gas fee and priority fee | -| `create/fields/transaction_rate_limit_field.dart` | Create | Two `FormBuilderTextField` fields for tx count and window | -| `create/shared_grant_fields.dart` | Create | Composes all shared field widgets | -| `create/grants/grant_form_handler.dart` | Create | Abstract `GrantFormHandler` with `buildSpecificGrant(formValues, WidgetRef)` | -| `create/grants/ether_transfer_grant.dart` | Create | `EtherTransferGrantHandler` + `_EtherTransferForm` | -| `create/grants/token_transfer_grant.dart` | Create | `TokenGrantLimits` provider, `TokenTransferGrantHandler`, `_TokenTransferForm` + volume limit widgets | -| `create/screen.dart` | Modify | Thin orchestration: `FormBuilder` root, section layout, submit logic, dispatch handler | - ---- - -## Task 1: Create `utils.dart` — Parsing helpers - -**Files:** -- Create: `lib/screens/dashboard/evm/grants/create/utils.dart` - -- [ ] **Step 1: Create `utils.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/utils.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:fixnum/fixnum.dart'; -import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart'; - -Timestamp toTimestamp(DateTime value) { - final utc = value.toUtc(); - return Timestamp() - ..seconds = Int64(utc.millisecondsSinceEpoch ~/ 1000) - ..nanos = (utc.microsecondsSinceEpoch % 1000000) * 1000; -} - -TransactionRateLimit? buildRateLimit(String countText, String windowText) { - if (countText.trim().isEmpty || windowText.trim().isEmpty) return null; - return TransactionRateLimit( - count: int.parse(countText.trim()), - windowSecs: Int64.parseInt(windowText.trim()), - ); -} - -VolumeRateLimit? buildVolumeLimit(String amountText, String windowText) { - if (amountText.trim().isEmpty || windowText.trim().isEmpty) return null; - return VolumeRateLimit( - maxVolume: parseBigIntBytes(amountText), - windowSecs: Int64.parseInt(windowText.trim()), - ); -} - -List? optionalBigIntBytes(String value) { - if (value.trim().isEmpty) return null; - return parseBigIntBytes(value); -} - -List parseBigIntBytes(String value) { - final number = BigInt.parse(value.trim()); - if (number < BigInt.zero) throw Exception('Numeric values must be positive.'); - if (number == BigInt.zero) return [0]; - var remaining = number; - final bytes = []; - while (remaining > BigInt.zero) { - bytes.insert(0, (remaining & BigInt.from(0xff)).toInt()); - remaining >>= 8; - } - return bytes; -} - -List> parseAddresses(String input) { - final parts = input - .split(RegExp(r'[\n,]')) - .map((p) => p.trim()) - .where((p) => p.isNotEmpty); - return parts.map(parseHexAddress).toList(); -} - -List parseHexAddress(String value) { - final normalized = value.trim().replaceFirst(RegExp(r'^0x'), ''); - if (normalized.length != 40) throw Exception('Expected a 20-byte hex address.'); - return [ - for (var i = 0; i < normalized.length; i += 2) - int.parse(normalized.substring(i, i + 2), radix: 16), - ]; -} - -String shortAddress(List bytes) { - final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); - return '0x${hex.substring(0, 6)}...${hex.substring(hex.length - 4)}'; -} -``` - -- [ ] **Step 2: Verify** - -```sh -cd operator && dart analyze lib/screens/dashboard/evm/grants/create/utils.dart -``` - -Expected: no errors. - -- [ ] **Step 3: Commit** - -```sh -jj describe -m "refactor(grants): extract parsing helpers to utils.dart" -``` - ---- - -## Task 2: Create `provider.dart` — Grant creation state - -**Files:** -- Create: `lib/screens/dashboard/evm/grants/create/provider.dart` -- Create (generated): `lib/screens/dashboard/evm/grants/create/provider.freezed.dart` -- Create (generated): `lib/screens/dashboard/evm/grants/create/provider.g.dart` - -The provider holds only what cannot live in a `FormBuilder` field: -- `selectedClientId` — a helper for filtering the wallet access dropdown; not part of `SharedSettings` proto -- `grantType` — driven by a `SegmentedButton`, not a form input - -- [ ] **Step 1: Create `provider.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/provider.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'provider.freezed.dart'; -part 'provider.g.dart'; - -@freezed -abstract class GrantCreationState with _$GrantCreationState { - const factory GrantCreationState({ - int? selectedClientId, - @Default(SpecificGrant_Grant.etherTransfer) SpecificGrant_Grant grantType, - }) = _GrantCreationState; -} - -@riverpod -class GrantCreation extends _$GrantCreation { - @override - GrantCreationState build() => const GrantCreationState(); - - void setClientId(int? id) => state = state.copyWith(selectedClientId: id); - void setGrantType(SpecificGrant_Grant type) => - state = state.copyWith(grantType: type); -} -``` - -- [ ] **Step 2: Run code generator** - -```sh -cd operator && dart run build_runner build --delete-conflicting-outputs -``` - -Expected: generates `provider.freezed.dart` and `provider.g.dart`, no errors. - -- [ ] **Step 3: Verify** - -```sh -cd operator && dart analyze lib/screens/dashboard/evm/grants/create/provider.dart -``` - -Expected: no errors. - -- [ ] **Step 4: Commit** - -```sh -jj describe -m "feat(grants): add GrantCreation provider (client selection + grant type)" -``` - ---- - -## Task 3: Create field widgets - -**Files:** -- Create: `lib/screens/dashboard/evm/grants/create/fields/client_picker_field.dart` -- Create: `lib/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart` -- Create: `lib/screens/dashboard/evm/grants/create/fields/chain_id_field.dart` -- Create: `lib/screens/dashboard/evm/grants/create/fields/date_time_field.dart` -- Create: `lib/screens/dashboard/evm/grants/create/fields/validity_window_field.dart` -- Create: `lib/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart` -- Create: `lib/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart` - -- [ ] **Step 1: Create `client_picker_field.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/fields/client_picker_field.dart -import 'package:arbiter/proto/operator.pb.dart'; -import 'package:arbiter/providers/sdk_clients/list.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -class ClientPickerField extends ConsumerWidget { - const ClientPickerField({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final clients = - ref.watch(sdkClientsProvider).asData?.value ?? const []; - - return FormBuilderDropdown( - name: 'clientId', - decoration: const InputDecoration( - labelText: 'Client', - border: OutlineInputBorder(), - ), - items: [ - for (final c in clients) - DropdownMenuItem( - value: c.id, - child: Text(c.info.name.isEmpty ? 'Client #${c.id}' : c.info.name), - ), - ], - onChanged: clients.isEmpty - ? null - : (value) => - ref.read(grantCreationProvider.notifier).setClientId(value), - ); - } -} -``` - -- [ ] **Step 2: Create `wallet_access_picker_field.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/proto/operator.pb.dart'; -import 'package:arbiter/providers/evm/evm.dart'; -import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -class WalletAccessPickerField extends ConsumerWidget { - const WalletAccessPickerField({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final state = ref.watch(grantCreationProvider); - final allAccesses = - ref.watch(walletAccessListProvider).asData?.value ?? - const []; - final wallets = - ref.watch(evmProvider).asData?.value ?? const []; - - final walletById = {for (final w in wallets) w.id: w}; - final accesses = state.selectedClientId == null - ? const [] - : allAccesses - .where((a) => a.access.sdkClientId == state.selectedClientId) - .toList(); - - return FormBuilderDropdown( - name: 'walletAccessId', - decoration: InputDecoration( - labelText: 'Wallet access', - helperText: state.selectedClientId == null - ? 'Select a client first' - : accesses.isEmpty - ? 'No wallet accesses for this client' - : null, - border: const OutlineInputBorder(), - ), - items: [ - for (final a in accesses) - DropdownMenuItem( - value: a.id, - child: Text(() { - final wallet = walletById[a.access.walletId]; - return wallet != null - ? shortAddress(wallet.address) - : 'Wallet #${a.access.walletId}'; - }()), - ), - ], - ); - } -} -``` - -- [ ] **Step 3: Create `chain_id_field.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/fields/chain_id_field.dart -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; - -class ChainIdField extends StatelessWidget { - const ChainIdField({super.key}); - - @override - Widget build(BuildContext context) { - return FormBuilderTextField( - name: 'chainId', - initialValue: '1', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Chain ID', - hintText: '1', - border: OutlineInputBorder(), - ), - ); - } -} -``` - -- [ ] **Step 4: Create `date_time_field.dart`** - -`flutter_form_builder` has no built-in date+time picker that matches the existing UX (separate date then time dialog, long-press to clear). Implement one via `FormBuilderField`. - -```dart -// lib/screens/dashboard/evm/grants/create/fields/date_time_field.dart -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:sizer/sizer.dart'; - -/// A [FormBuilderField] that opens a date picker followed by a time picker. -/// Long-press clears the value. -class FormBuilderDateTimeField extends FormBuilderField { - final String label; - - FormBuilderDateTimeField({ - super.key, - required super.name, - required this.label, - super.initialValue, - super.onChanged, - super.validator, - }) : super( - builder: (FormFieldState field) { - final value = field.value; - return OutlinedButton( - onPressed: () async { - final now = DateTime.now(); - final date = await showDatePicker( - context: field.context, - firstDate: DateTime(now.year - 5), - lastDate: DateTime(now.year + 10), - initialDate: value ?? now, - ); - if (date == null) return; - // ignore: use_build_context_synchronously — field.context is - // still valid as long as the widget is in the tree. - if (!field.context.mounted) return; - final time = await showTimePicker( - context: field.context, - initialTime: TimeOfDay.fromDateTime(value ?? now), - ); - if (time == null) return; - field.didChange(DateTime( - date.year, - date.month, - date.day, - time.hour, - time.minute, - )); - }, - onLongPress: value == null ? null : () => field.didChange(null), - child: Padding( - padding: EdgeInsets.symmetric(vertical: 1.8.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(label), - SizedBox(height: 0.6.h), - Text(value?.toLocal().toString() ?? 'Not set'), - ], - ), - ), - ); - }, - ); -} -``` - -- [ ] **Step 5: Create `validity_window_field.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/fields/validity_window_field.dart -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/date_time_field.dart'; -import 'package:flutter/material.dart'; -import 'package:sizer/sizer.dart'; - -class ValidityWindowField extends StatelessWidget { - const ValidityWindowField({super.key}); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: FormBuilderDateTimeField( - name: 'validFrom', - label: 'Valid from', - ), - ), - SizedBox(width: 1.w), - Expanded( - child: FormBuilderDateTimeField( - name: 'validUntil', - label: 'Valid until', - ), - ), - ], - ); - } -} -``` - -- [ ] **Step 6: Create `gas_fee_options_field.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:sizer/sizer.dart'; - -class GasFeeOptionsField extends StatelessWidget { - const GasFeeOptionsField({super.key}); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: FormBuilderTextField( - name: 'maxGasFeePerGas', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Max gas fee / gas', - hintText: '1000000000', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 1.w), - Expanded( - child: FormBuilderTextField( - name: 'maxPriorityFeePerGas', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Max priority fee / gas', - hintText: '100000000', - border: OutlineInputBorder(), - ), - ), - ), - ], - ); - } -} -``` - -- [ ] **Step 7: Create `transaction_rate_limit_field.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:sizer/sizer.dart'; - -class TransactionRateLimitField extends StatelessWidget { - const TransactionRateLimitField({super.key}); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: FormBuilderTextField( - name: 'txCount', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Tx count limit', - hintText: '10', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 1.w), - Expanded( - child: FormBuilderTextField( - name: 'txWindow', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Window (seconds)', - hintText: '3600', - border: OutlineInputBorder(), - ), - ), - ), - ], - ); - } -} -``` - -- [ ] **Step 8: Verify all field widgets** - -```sh -cd operator && dart analyze lib/screens/dashboard/evm/grants/create/fields/ -``` - -Expected: no errors. - -- [ ] **Step 9: Commit** - -```sh -jj describe -m "feat(grants): add composable FormBuilder field widgets incl. custom DateTimeField" -``` - ---- - -## Task 4: Create `SharedGrantFields` widget - -**Files:** -- Create: `lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart` - -- [ ] **Step 1: Create `shared_grant_fields.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/chain_id_field.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/client_picker_field.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/validity_window_field.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart'; -import 'package:flutter/material.dart'; -import 'package:sizer/sizer.dart'; - -/// All shared grant fields in a single vertical layout. -/// -/// Every [FormBuilderField] descendant auto-registers with the nearest -/// [FormBuilder] ancestor via [BuildContext] — no controllers passed. -class SharedGrantFields extends StatelessWidget { - const SharedGrantFields({super.key}); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const ClientPickerField(), - SizedBox(height: 1.6.h), - const WalletAccessPickerField(), - SizedBox(height: 1.6.h), - const ChainIdField(), - SizedBox(height: 1.6.h), - const ValidityWindowField(), - SizedBox(height: 1.6.h), - const GasFeeOptionsField(), - SizedBox(height: 1.6.h), - const TransactionRateLimitField(), - ], - ); - } -} -``` - -- [ ] **Step 2: Verify** - -```sh -cd operator && dart analyze lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart -``` - -Expected: no errors. - -- [ ] **Step 3: Commit** - -```sh -jj describe -m "feat(grants): add SharedGrantFields composite widget" -``` - ---- - -## Task 5: Create grant form handlers - -**Files:** -- Create: `lib/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart` -- Create: `lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart` -- Create: `lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart` -- Create (generated): `lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.g.dart` - -- [ ] **Step 1: Create `grant_form_handler.dart`** - -`buildSpecificGrant` takes `WidgetRef` so each handler can read its own providers (e.g., token volume limits) without coupling to a shared state object. - -```dart -// lib/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:flutter/widgets.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -abstract class GrantFormHandler { - /// Renders the grant-specific form section. - /// - /// The returned widget must be a descendant of the [FormBuilder] in the - /// screen so its [FormBuilderField] children register automatically. - Widget buildForm(BuildContext context, WidgetRef ref); - - /// Assembles a [SpecificGrant] proto. - /// - /// [formValues] — `formKey.currentState!.value` after `saveAndValidate()`. - /// [ref] — read any provider the handler owns (e.g. token volume limits). - SpecificGrant buildSpecificGrant( - Map formValues, - WidgetRef ref, - ); -} -``` - -- [ ] **Step 2: Create `ether_transfer_grant.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -class EtherTransferGrantHandler implements GrantFormHandler { - const EtherTransferGrantHandler(); - - @override - Widget buildForm(BuildContext context, WidgetRef ref) => - const _EtherTransferForm(); - - @override - SpecificGrant buildSpecificGrant( - Map formValues, - WidgetRef ref, - ) { - return SpecificGrant( - etherTransfer: EtherTransferSettings( - targets: parseAddresses(formValues['etherRecipients'] as String? ?? ''), - limit: buildVolumeLimit( - formValues['etherVolume'] as String? ?? '', - formValues['etherVolumeWindow'] as String? ?? '', - ), - ), - ); - } -} - -class _EtherTransferForm extends StatelessWidget { - const _EtherTransferForm(); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - FormBuilderTextField( - name: 'etherRecipients', - minLines: 3, - maxLines: 6, - decoration: const InputDecoration( - labelText: 'Ether recipients', - hintText: - 'One 0x address per line. Leave empty for unrestricted targets.', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 1.6.h), - Text( - 'Ether volume limit', - style: Theme.of(context).textTheme.labelLarge?.copyWith( - fontWeight: FontWeight.w800, - ), - ), - SizedBox(height: 0.8.h), - Row( - children: [ - Expanded( - child: FormBuilderTextField( - name: 'etherVolume', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Max volume', - hintText: '1000000000000000000', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 1.w), - Expanded( - child: FormBuilderTextField( - name: 'etherVolumeWindow', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Window (seconds)', - hintText: '86400', - border: OutlineInputBorder(), - ), - ), - ), - ], - ), - ], - ); - } -} -``` - -- [ ] **Step 3: Create `token_transfer_grant.dart`** - -`TokenGrantLimits` is a scoped `@riverpod` provider (auto-dispose) that owns the dynamic volume limit list for the token grant form. `TokenTransferGrantHandler.buildSpecificGrant` reads it via `ref`. - -```dart -// lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; -import 'package:fixnum/fixnum.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:sizer/sizer.dart'; - -part 'token_transfer_grant.g.dart'; - -// --------------------------------------------------------------------------- -// Volume limit entry — a single row's data -// --------------------------------------------------------------------------- - -class VolumeLimitEntry { - const VolumeLimitEntry({this.amount = '', this.windowSeconds = ''}); - - final String amount; - final String windowSeconds; - - VolumeLimitEntry copyWith({String? amount, String? windowSeconds}) => - VolumeLimitEntry( - amount: amount ?? this.amount, - windowSeconds: windowSeconds ?? this.windowSeconds, - ); -} - -// --------------------------------------------------------------------------- -// Provider — owns token volume limits; auto-disposed when screen pops -// --------------------------------------------------------------------------- - -@riverpod -class TokenGrantLimits extends _$TokenGrantLimits { - @override - List build() => const [VolumeLimitEntry()]; - - void add() => state = [...state, const VolumeLimitEntry()]; - - void update(int index, VolumeLimitEntry entry) { - final updated = [...state]; - updated[index] = entry; - state = updated; - } - - void remove(int index) => state = [...state]..removeAt(index); -} - -// --------------------------------------------------------------------------- -// Handler -// --------------------------------------------------------------------------- - -class TokenTransferGrantHandler implements GrantFormHandler { - const TokenTransferGrantHandler(); - - @override - Widget buildForm(BuildContext context, WidgetRef ref) => - const _TokenTransferForm(); - - @override - SpecificGrant buildSpecificGrant( - Map formValues, - WidgetRef ref, - ) { - final limits = ref.read(tokenGrantLimitsProvider); - final targetText = formValues['tokenTarget'] as String? ?? ''; - - return SpecificGrant( - tokenTransfer: TokenTransferSettings( - tokenContract: - parseHexAddress(formValues['tokenContract'] as String? ?? ''), - target: targetText.trim().isEmpty ? null : parseHexAddress(targetText), - volumeLimits: limits - .where((e) => e.amount.trim().isNotEmpty) - .map( - (e) => VolumeRateLimit( - maxVolume: parseBigIntBytes(e.amount), - windowSecs: Int64.parseInt(e.windowSeconds), - ), - ) - .toList(), - ), - ); - } -} - -// --------------------------------------------------------------------------- -// Form widget -// --------------------------------------------------------------------------- - -class _TokenTransferForm extends ConsumerWidget { - const _TokenTransferForm(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final limits = ref.watch(tokenGrantLimitsProvider); - final notifier = ref.read(tokenGrantLimitsProvider.notifier); - - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - FormBuilderTextField( - name: 'tokenContract', - decoration: const InputDecoration( - labelText: 'Token contract', - hintText: '0x...', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 1.6.h), - FormBuilderTextField( - name: 'tokenTarget', - decoration: const InputDecoration( - labelText: 'Token recipient', - hintText: '0x... or leave empty for any recipient', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 1.6.h), - _TokenVolumeLimitsField( - values: limits, - onAdd: notifier.add, - onUpdate: notifier.update, - onRemove: notifier.remove, - ), - ], - ); - } -} - -// --------------------------------------------------------------------------- -// Volume limits list widget -// --------------------------------------------------------------------------- - -class _TokenVolumeLimitsField extends StatelessWidget { - const _TokenVolumeLimitsField({ - required this.values, - required this.onAdd, - required this.onUpdate, - required this.onRemove, - }); - - final List values; - final VoidCallback onAdd; - final void Function(int index, VolumeLimitEntry entry) onUpdate; - final void Function(int index) onRemove; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Text( - 'Token volume limits', - style: Theme.of(context).textTheme.labelLarge?.copyWith( - fontWeight: FontWeight.w800, - ), - ), - ), - TextButton.icon( - onPressed: onAdd, - icon: const Icon(Icons.add_rounded), - label: const Text('Add'), - ), - ], - ), - SizedBox(height: 0.8.h), - for (var i = 0; i < values.length; i++) - Padding( - padding: EdgeInsets.only(bottom: 1.h), - child: _TokenVolumeLimitRow( - key: ValueKey(i), - value: values[i], - onChanged: (entry) => onUpdate(i, entry), - onRemove: values.length == 1 ? null : () => onRemove(i), - ), - ), - ], - ); - } -} - -class _TokenVolumeLimitRow extends HookWidget { - const _TokenVolumeLimitRow({ - super.key, - required this.value, - required this.onChanged, - required this.onRemove, - }); - - final VolumeLimitEntry value; - final ValueChanged onChanged; - final VoidCallback? onRemove; - - @override - Widget build(BuildContext context) { - final amountController = useTextEditingController(text: value.amount); - final windowController = useTextEditingController(text: value.windowSeconds); - - return Row( - children: [ - Expanded( - child: TextField( - controller: amountController, - onChanged: (next) => onChanged(value.copyWith(amount: next)), - decoration: const InputDecoration( - labelText: 'Max volume', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 1.w), - Expanded( - child: TextField( - controller: windowController, - onChanged: (next) => - onChanged(value.copyWith(windowSeconds: next)), - decoration: const InputDecoration( - labelText: 'Window (seconds)', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 0.4.w), - IconButton( - onPressed: onRemove, - icon: const Icon(Icons.remove_circle_outline_rounded), - ), - ], - ); - } -} -``` - -- [ ] **Step 4: Run code generator for token_transfer_grant.g.dart** - -```sh -cd operator && dart run build_runner build --delete-conflicting-outputs -``` - -Expected: generates `token_transfer_grant.g.dart`, no errors. - -- [ ] **Step 5: Verify** - -```sh -cd operator && dart analyze lib/screens/dashboard/evm/grants/create/grants/ -``` - -Expected: no errors. - -- [ ] **Step 6: Commit** - -```sh -jj describe -m "feat(grants): add GrantFormHandler interface and per-type implementations" -``` - ---- - -## Task 6: Rewrite `screen.dart` - -**Files:** -- Modify: `lib/screens/dashboard/evm/grants/create/screen.dart` - -The screen owns `FormBuilder`, dispatches to the active handler, and assembles `SharedSettings` on submit. `validFrom`/`validUntil` are now read from `formValues['validFrom']` etc. — no more provider reads for dates. - -- [ ] **Step 1: Replace `screen.dart`** - -```dart -// lib/screens/dashboard/evm/grants/create/screen.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/providers/evm/evm_grants.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/shared_grant_fields.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:fixnum/fixnum.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; -import 'package:sizer/sizer.dart'; - -const _etherHandler = EtherTransferGrantHandler(); -const _tokenHandler = TokenTransferGrantHandler(); - -GrantFormHandler _handlerFor(SpecificGrant_Grant type) => switch (type) { - SpecificGrant_Grant.etherTransfer => _etherHandler, - SpecificGrant_Grant.tokenTransfer => _tokenHandler, - _ => throw ArgumentError('Unsupported grant type: $type'), - }; - -@RoutePage() -class CreateEvmGrantScreen extends HookConsumerWidget { - const CreateEvmGrantScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final formKey = useMemoized(() => GlobalKey()); - final createMutation = ref.watch(createEvmGrantMutation); - final state = ref.watch(grantCreationProvider); - final notifier = ref.read(grantCreationProvider.notifier); - final handler = _handlerFor(state.grantType); - - Future submit() async { - if (!(formKey.currentState?.saveAndValidate() ?? false)) return; - final formValues = formKey.currentState!.value; - - final accessId = formValues['walletAccessId'] as int?; - if (accessId == null) { - _showSnackBar(context, 'Select a client and wallet access.'); - return; - } - - try { - final specific = handler.buildSpecificGrant(formValues, ref); - final sharedSettings = SharedSettings( - walletAccessId: accessId, - chainId: Int64.parseInt( - (formValues['chainId'] as String? ?? '').trim(), - ), - ); - final validFrom = formValues['validFrom'] as DateTime?; - final validUntil = formValues['validUntil'] as DateTime?; - if (validFrom != null) sharedSettings.validFrom = toTimestamp(validFrom); - if (validUntil != null) { - sharedSettings.validUntil = toTimestamp(validUntil); - } - final gasBytes = - optionalBigIntBytes(formValues['maxGasFeePerGas'] as String? ?? ''); - if (gasBytes != null) sharedSettings.maxGasFeePerGas = gasBytes; - final priorityBytes = optionalBigIntBytes( - formValues['maxPriorityFeePerGas'] as String? ?? '', - ); - if (priorityBytes != null) { - sharedSettings.maxPriorityFeePerGas = priorityBytes; - } - final rateLimit = buildRateLimit( - formValues['txCount'] as String? ?? '', - formValues['txWindow'] as String? ?? '', - ); - if (rateLimit != null) sharedSettings.rateLimit = rateLimit; - - await executeCreateEvmGrant( - ref, - sharedSettings: sharedSettings, - specific: specific, - ); - if (!context.mounted) return; - context.router.pop(); - } catch (error) { - if (!context.mounted) return; - _showSnackBar(context, _formatError(error)); - } - } - - return Scaffold( - appBar: AppBar(title: const Text('Create EVM Grant')), - body: SafeArea( - child: FormBuilder( - key: formKey, - child: ListView( - padding: EdgeInsets.fromLTRB(2.4.w, 2.h, 2.4.w, 3.2.h), - children: [ - const _IntroCard(), - SizedBox(height: 1.8.h), - const _Section( - title: 'Shared grant options', - child: SharedGrantFields(), - ), - SizedBox(height: 1.8.h), - _GrantTypeSelector( - value: state.grantType, - onChanged: notifier.setGrantType, - ), - SizedBox(height: 1.8.h), - _Section( - title: 'Grant-specific options', - child: handler.buildForm(context, ref), - ), - SizedBox(height: 2.2.h), - Align( - alignment: Alignment.centerRight, - child: FilledButton.icon( - onPressed: - createMutation is MutationPending ? null : submit, - icon: createMutation is MutationPending - ? SizedBox( - width: 1.8.h, - height: 1.8.h, - child: const CircularProgressIndicator( - strokeWidth: 2.2, - ), - ) - : const Icon(Icons.check_rounded), - label: Text( - createMutation is MutationPending - ? 'Creating...' - : 'Create grant', - ), - ), - ), - ], - ), - ), - ), - ); - } -} - -// --------------------------------------------------------------------------- -// Layout helpers -// --------------------------------------------------------------------------- - -class _IntroCard extends StatelessWidget { - const _IntroCard(); - - @override - Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.all(2.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), - gradient: const LinearGradient( - colors: [Color(0xFFF7F9FC), Color(0xFFFDF5EA)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - border: Border.all(color: const Color(0x1A17324A)), - ), - child: Text( - 'Pick a client, then select one of the wallet accesses already granted ' - 'to it. Compose shared constraints once, then switch between Ether and ' - 'token transfer rules.', - style: Theme.of(context).textTheme.bodyLarge?.copyWith(height: 1.5), - ), - ); - } -} - -class _Section extends StatelessWidget { - const _Section({required this.title, required this.child}); - - final String title; - final Widget child; - - @override - Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.all(2.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), - color: Colors.white, - border: Border.all(color: const Color(0x1A17324A)), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: Theme.of(context).textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.w800, - ), - ), - SizedBox(height: 1.4.h), - child, - ], - ), - ); - } -} - -class _GrantTypeSelector extends StatelessWidget { - const _GrantTypeSelector({required this.value, required this.onChanged}); - - final SpecificGrant_Grant value; - final ValueChanged onChanged; - - @override - Widget build(BuildContext context) { - return SegmentedButton( - segments: const [ - ButtonSegment( - value: SpecificGrant_Grant.etherTransfer, - label: Text('Ether'), - icon: Icon(Icons.bolt_rounded), - ), - ButtonSegment( - value: SpecificGrant_Grant.tokenTransfer, - label: Text('Token'), - icon: Icon(Icons.token_rounded), - ), - ], - selected: {value}, - onSelectionChanged: (selection) => onChanged(selection.first), - ); - } -} - -// --------------------------------------------------------------------------- -// Utilities -// --------------------------------------------------------------------------- - -void _showSnackBar(BuildContext context, String message) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), - ); -} - -String _formatError(Object error) { - final text = error.toString(); - return text.startsWith('Exception: ') - ? text.substring('Exception: '.length) - : text; -} -``` - -- [ ] **Step 2: Verify the full create/ directory** - -```sh -cd operator && dart analyze lib/screens/dashboard/evm/grants/create/ -``` - -Expected: no errors. - -- [ ] **Step 3: Commit** - -```sh -jj describe -m "refactor(grants): decompose CreateEvmGrantScreen into provider + field widgets + grant handlers" -``` - ---- - -## Self-Review - -### Spec coverage - -| Requirement | Task | -|-------------|------| -| Riverpod provider for grant creation state | Task 2 (`GrantCreation`) | -| flutter_form_builder in composable manner | Tasks 3–4 | -| `fields/` folder for shared fields | Task 3 | -| Custom `FormBuilderDateTimeField` (no built-in) | Task 3, Step 4 | -| `validFrom`/`validUntil` as form fields | Task 3 (`ValidityWindowField` uses `FormBuilderDateTimeField`) | -| `tokenVolumeLimits` in grant-specific implementation | Task 5 (`TokenGrantLimits` in `token_transfer_grant.dart`) | -| Grant handler with `buildForm` + `buildSpecificGrant` | Task 5 | -| `SharedGrantFields` widget | Task 4 | -| Thin main screen | Task 6 | -| Class renamed to `GrantCreation` (provider: `grantCreationProvider`) | Task 2 | - -### Placeholder scan - -No TODOs, TBDs, or "similar to task N" references found. - -### Type consistency - -- `VolumeLimitEntry` defined in `token_transfer_grant.dart`, used only within that file ✓ -- `GrantFormHandler` interface: `buildSpecificGrant(Map, WidgetRef)` matches both implementations ✓ -- `grantCreationProvider` (from `@riverpod class GrantCreation`) used in `client_picker_field.dart`, `wallet_access_picker_field.dart`, `screen.dart` ✓ -- `tokenGrantLimitsProvider` (from `@riverpod class TokenGrantLimits`) used in `_TokenTransferForm.build` and `TokenTransferGrantHandler.buildSpecificGrant` ✓ -- FormBuilder field names in `screen.dart` (`validFrom`, `validUntil`, `walletAccessId`, `chainId`, `maxGasFeePerGas`, `maxPriorityFeePerGas`, `txCount`, `txWindow`) match the `name:` params in field widgets ✓ +# Grant Creation Screen Refactor Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Decompose the monolithic `create/screen.dart` into a Riverpod-managed provider, composable `flutter_form_builder` field widgets, and per-grant-type handlers with a clean interface. + +**Architecture:** A `GrantCreation` provider manages only the state that cannot live in a form field: `selectedClientId` (drives wallet-access filtering) and `grantType` (SegmentedButton). All other shared settings — including validity dates — are `FormBuilder` fields; the custom `FormBuilderDateTimeField` wraps the native date/time picker dialog. Token volume limits are owned by a `TokenGrantLimits` provider that lives entirely inside `token_transfer_grant.dart`. Each grant type implements `GrantFormHandler`, whose `buildSpecificGrant` receives `formValues` and a `WidgetRef` so handlers can read their own providers. + +**Tech Stack:** Flutter, Riverpod (riverpod_annotation 4.x), flutter_form_builder 10.x, freezed 3.x, flutter_hooks, Protobuf (Dart), fixnum + +--- + +## File Map + +| Path | Action | Responsibility | +|------|--------|----------------| +| `create/utils.dart` | Create | Parsing/conversion helpers (hex addresses, big-int bytes, timestamps, rate limits) | +| `create/provider.dart` | Create | `GrantCreationState` (freezed), `GrantCreation` (@riverpod) — only `selectedClientId` + `grantType` | +| `create/fields/client_picker_field.dart` | Create | `FormBuilderDropdown` for SDK client; syncs selection to `GrantCreation` provider | +| `create/fields/wallet_access_picker_field.dart` | Create | `FormBuilderDropdown` for wallet access; filters by provider's `selectedClientId` | +| `create/fields/chain_id_field.dart` | Create | `FormBuilderTextField` for chain ID | +| `create/fields/date_time_field.dart` | Create | Custom `FormBuilderDateTimeField` — wraps date+time picker dialogs as a `FormBuilderField` | +| `create/fields/validity_window_field.dart` | Create | Row of two `FormBuilderDateTimeField` widgets (names `validFrom`, `validUntil`) | +| `create/fields/gas_fee_options_field.dart` | Create | Two `FormBuilderTextField` fields for gas fee and priority fee | +| `create/fields/transaction_rate_limit_field.dart` | Create | Two `FormBuilderTextField` fields for tx count and window | +| `create/shared_grant_fields.dart` | Create | Composes all shared field widgets | +| `create/grants/grant_form_handler.dart` | Create | Abstract `GrantFormHandler` with `buildSpecificGrant(formValues, WidgetRef)` | +| `create/grants/ether_transfer_grant.dart` | Create | `EtherTransferGrantHandler` + `_EtherTransferForm` | +| `create/grants/token_transfer_grant.dart` | Create | `TokenGrantLimits` provider, `TokenTransferGrantHandler`, `_TokenTransferForm` + volume limit widgets | +| `create/screen.dart` | Modify | Thin orchestration: `FormBuilder` root, section layout, submit logic, dispatch handler | + +--- + +## Task 1: Create `utils.dart` — Parsing helpers + +**Files:** +- Create: `lib/screens/dashboard/evm/grants/create/utils.dart` + +- [ ] **Step 1: Create `utils.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/utils.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:fixnum/fixnum.dart'; +import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart'; + +Timestamp toTimestamp(DateTime value) { + final utc = value.toUtc(); + return Timestamp() + ..seconds = Int64(utc.millisecondsSinceEpoch ~/ 1000) + ..nanos = (utc.microsecondsSinceEpoch % 1000000) * 1000; +} + +TransactionRateLimit? buildRateLimit(String countText, String windowText) { + if (countText.trim().isEmpty || windowText.trim().isEmpty) return null; + return TransactionRateLimit( + count: int.parse(countText.trim()), + windowSecs: Int64.parseInt(windowText.trim()), + ); +} + +VolumeRateLimit? buildVolumeLimit(String amountText, String windowText) { + if (amountText.trim().isEmpty || windowText.trim().isEmpty) return null; + return VolumeRateLimit( + maxVolume: parseBigIntBytes(amountText), + windowSecs: Int64.parseInt(windowText.trim()), + ); +} + +List? optionalBigIntBytes(String value) { + if (value.trim().isEmpty) return null; + return parseBigIntBytes(value); +} + +List parseBigIntBytes(String value) { + final number = BigInt.parse(value.trim()); + if (number < BigInt.zero) throw Exception('Numeric values must be positive.'); + if (number == BigInt.zero) return [0]; + var remaining = number; + final bytes = []; + while (remaining > BigInt.zero) { + bytes.insert(0, (remaining & BigInt.from(0xff)).toInt()); + remaining >>= 8; + } + return bytes; +} + +List> parseAddresses(String input) { + final parts = input + .split(RegExp(r'[\n,]')) + .map((p) => p.trim()) + .where((p) => p.isNotEmpty); + return parts.map(parseHexAddress).toList(); +} + +List parseHexAddress(String value) { + final normalized = value.trim().replaceFirst(RegExp(r'^0x'), ''); + if (normalized.length != 40) throw Exception('Expected a 20-byte hex address.'); + return [ + for (var i = 0; i < normalized.length; i += 2) + int.parse(normalized.substring(i, i + 2), radix: 16), + ]; +} + +String shortAddress(List bytes) { + final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); + return '0x${hex.substring(0, 6)}...${hex.substring(hex.length - 4)}'; +} +``` + +- [ ] **Step 2: Verify** + +```sh +cd operator && dart analyze lib/screens/dashboard/evm/grants/create/utils.dart +``` + +Expected: no errors. + +- [ ] **Step 3: Commit** + +```sh +jj describe -m "refactor(grants): extract parsing helpers to utils.dart" +``` + +--- + +## Task 2: Create `provider.dart` — Grant creation state + +**Files:** +- Create: `lib/screens/dashboard/evm/grants/create/provider.dart` +- Create (generated): `lib/screens/dashboard/evm/grants/create/provider.freezed.dart` +- Create (generated): `lib/screens/dashboard/evm/grants/create/provider.g.dart` + +The provider holds only what cannot live in a `FormBuilder` field: +- `selectedClientId` — a helper for filtering the wallet access dropdown; not part of `SharedSettings` proto +- `grantType` — driven by a `SegmentedButton`, not a form input + +- [ ] **Step 1: Create `provider.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/provider.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'provider.freezed.dart'; +part 'provider.g.dart'; + +@freezed +abstract class GrantCreationState with _$GrantCreationState { + const factory GrantCreationState({ + int? selectedClientId, + @Default(SpecificGrant_Grant.etherTransfer) SpecificGrant_Grant grantType, + }) = _GrantCreationState; +} + +@riverpod +class GrantCreation extends _$GrantCreation { + @override + GrantCreationState build() => const GrantCreationState(); + + void setClientId(int? id) => state = state.copyWith(selectedClientId: id); + void setGrantType(SpecificGrant_Grant type) => + state = state.copyWith(grantType: type); +} +``` + +- [ ] **Step 2: Run code generator** + +```sh +cd operator && dart run build_runner build --delete-conflicting-outputs +``` + +Expected: generates `provider.freezed.dart` and `provider.g.dart`, no errors. + +- [ ] **Step 3: Verify** + +```sh +cd operator && dart analyze lib/screens/dashboard/evm/grants/create/provider.dart +``` + +Expected: no errors. + +- [ ] **Step 4: Commit** + +```sh +jj describe -m "feat(grants): add GrantCreation provider (client selection + grant type)" +``` + +--- + +## Task 3: Create field widgets + +**Files:** +- Create: `lib/screens/dashboard/evm/grants/create/fields/client_picker_field.dart` +- Create: `lib/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart` +- Create: `lib/screens/dashboard/evm/grants/create/fields/chain_id_field.dart` +- Create: `lib/screens/dashboard/evm/grants/create/fields/date_time_field.dart` +- Create: `lib/screens/dashboard/evm/grants/create/fields/validity_window_field.dart` +- Create: `lib/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart` +- Create: `lib/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart` + +- [ ] **Step 1: Create `client_picker_field.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/fields/client_picker_field.dart +import 'package:arbiter/proto/operator.pb.dart'; +import 'package:arbiter/providers/sdk_clients/list.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +class ClientPickerField extends ConsumerWidget { + const ClientPickerField({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final clients = + ref.watch(sdkClientsProvider).asData?.value ?? const []; + + return FormBuilderDropdown( + name: 'clientId', + decoration: const InputDecoration( + labelText: 'Client', + border: OutlineInputBorder(), + ), + items: [ + for (final c in clients) + DropdownMenuItem( + value: c.id, + child: Text(c.info.name.isEmpty ? 'Client #${c.id}' : c.info.name), + ), + ], + onChanged: clients.isEmpty + ? null + : (value) => + ref.read(grantCreationProvider.notifier).setClientId(value), + ); + } +} +``` + +- [ ] **Step 2: Create `wallet_access_picker_field.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/proto/operator.pb.dart'; +import 'package:arbiter/providers/evm/evm.dart'; +import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +class WalletAccessPickerField extends ConsumerWidget { + const WalletAccessPickerField({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final state = ref.watch(grantCreationProvider); + final allAccesses = + ref.watch(walletAccessListProvider).asData?.value ?? + const []; + final wallets = + ref.watch(evmProvider).asData?.value ?? const []; + + final walletById = {for (final w in wallets) w.id: w}; + final accesses = state.selectedClientId == null + ? const [] + : allAccesses + .where((a) => a.access.sdkClientId == state.selectedClientId) + .toList(); + + return FormBuilderDropdown( + name: 'walletAccessId', + decoration: InputDecoration( + labelText: 'Wallet access', + helperText: state.selectedClientId == null + ? 'Select a client first' + : accesses.isEmpty + ? 'No wallet accesses for this client' + : null, + border: const OutlineInputBorder(), + ), + items: [ + for (final a in accesses) + DropdownMenuItem( + value: a.id, + child: Text(() { + final wallet = walletById[a.access.walletId]; + return wallet != null + ? shortAddress(wallet.address) + : 'Wallet #${a.access.walletId}'; + }()), + ), + ], + ); + } +} +``` + +- [ ] **Step 3: Create `chain_id_field.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/fields/chain_id_field.dart +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; + +class ChainIdField extends StatelessWidget { + const ChainIdField({super.key}); + + @override + Widget build(BuildContext context) { + return FormBuilderTextField( + name: 'chainId', + initialValue: '1', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Chain ID', + hintText: '1', + border: OutlineInputBorder(), + ), + ); + } +} +``` + +- [ ] **Step 4: Create `date_time_field.dart`** + +`flutter_form_builder` has no built-in date+time picker that matches the existing UX (separate date then time dialog, long-press to clear). Implement one via `FormBuilderField`. + +```dart +// lib/screens/dashboard/evm/grants/create/fields/date_time_field.dart +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:sizer/sizer.dart'; + +/// A [FormBuilderField] that opens a date picker followed by a time picker. +/// Long-press clears the value. +class FormBuilderDateTimeField extends FormBuilderField { + final String label; + + FormBuilderDateTimeField({ + super.key, + required super.name, + required this.label, + super.initialValue, + super.onChanged, + super.validator, + }) : super( + builder: (FormFieldState field) { + final value = field.value; + return OutlinedButton( + onPressed: () async { + final now = DateTime.now(); + final date = await showDatePicker( + context: field.context, + firstDate: DateTime(now.year - 5), + lastDate: DateTime(now.year + 10), + initialDate: value ?? now, + ); + if (date == null) return; + // ignore: use_build_context_synchronously — field.context is + // still valid as long as the widget is in the tree. + if (!field.context.mounted) return; + final time = await showTimePicker( + context: field.context, + initialTime: TimeOfDay.fromDateTime(value ?? now), + ); + if (time == null) return; + field.didChange(DateTime( + date.year, + date.month, + date.day, + time.hour, + time.minute, + )); + }, + onLongPress: value == null ? null : () => field.didChange(null), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 1.8.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label), + SizedBox(height: 0.6.h), + Text(value?.toLocal().toString() ?? 'Not set'), + ], + ), + ), + ); + }, + ); +} +``` + +- [ ] **Step 5: Create `validity_window_field.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/fields/validity_window_field.dart +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/date_time_field.dart'; +import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; + +class ValidityWindowField extends StatelessWidget { + const ValidityWindowField({super.key}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: FormBuilderDateTimeField( + name: 'validFrom', + label: 'Valid from', + ), + ), + SizedBox(width: 1.w), + Expanded( + child: FormBuilderDateTimeField( + name: 'validUntil', + label: 'Valid until', + ), + ), + ], + ); + } +} +``` + +- [ ] **Step 6: Create `gas_fee_options_field.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:sizer/sizer.dart'; + +class GasFeeOptionsField extends StatelessWidget { + const GasFeeOptionsField({super.key}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: FormBuilderTextField( + name: 'maxGasFeePerGas', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Max gas fee / gas', + hintText: '1000000000', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 1.w), + Expanded( + child: FormBuilderTextField( + name: 'maxPriorityFeePerGas', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Max priority fee / gas', + hintText: '100000000', + border: OutlineInputBorder(), + ), + ), + ), + ], + ); + } +} +``` + +- [ ] **Step 7: Create `transaction_rate_limit_field.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:sizer/sizer.dart'; + +class TransactionRateLimitField extends StatelessWidget { + const TransactionRateLimitField({super.key}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: FormBuilderTextField( + name: 'txCount', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Tx count limit', + hintText: '10', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 1.w), + Expanded( + child: FormBuilderTextField( + name: 'txWindow', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Window (seconds)', + hintText: '3600', + border: OutlineInputBorder(), + ), + ), + ), + ], + ); + } +} +``` + +- [ ] **Step 8: Verify all field widgets** + +```sh +cd operator && dart analyze lib/screens/dashboard/evm/grants/create/fields/ +``` + +Expected: no errors. + +- [ ] **Step 9: Commit** + +```sh +jj describe -m "feat(grants): add composable FormBuilder field widgets incl. custom DateTimeField" +``` + +--- + +## Task 4: Create `SharedGrantFields` widget + +**Files:** +- Create: `lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart` + +- [ ] **Step 1: Create `shared_grant_fields.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/chain_id_field.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/client_picker_field.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/validity_window_field.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart'; +import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; + +/// All shared grant fields in a single vertical layout. +/// +/// Every [FormBuilderField] descendant auto-registers with the nearest +/// [FormBuilder] ancestor via [BuildContext] — no controllers passed. +class SharedGrantFields extends StatelessWidget { + const SharedGrantFields({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const ClientPickerField(), + SizedBox(height: 1.6.h), + const WalletAccessPickerField(), + SizedBox(height: 1.6.h), + const ChainIdField(), + SizedBox(height: 1.6.h), + const ValidityWindowField(), + SizedBox(height: 1.6.h), + const GasFeeOptionsField(), + SizedBox(height: 1.6.h), + const TransactionRateLimitField(), + ], + ); + } +} +``` + +- [ ] **Step 2: Verify** + +```sh +cd operator && dart analyze lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart +``` + +Expected: no errors. + +- [ ] **Step 3: Commit** + +```sh +jj describe -m "feat(grants): add SharedGrantFields composite widget" +``` + +--- + +## Task 5: Create grant form handlers + +**Files:** +- Create: `lib/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart` +- Create: `lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart` +- Create: `lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart` +- Create (generated): `lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.g.dart` + +- [ ] **Step 1: Create `grant_form_handler.dart`** + +`buildSpecificGrant` takes `WidgetRef` so each handler can read its own providers (e.g., token volume limits) without coupling to a shared state object. + +```dart +// lib/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:flutter/widgets.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +abstract class GrantFormHandler { + /// Renders the grant-specific form section. + /// + /// The returned widget must be a descendant of the [FormBuilder] in the + /// screen so its [FormBuilderField] children register automatically. + Widget buildForm(BuildContext context, WidgetRef ref); + + /// Assembles a [SpecificGrant] proto. + /// + /// [formValues] — `formKey.currentState!.value` after `saveAndValidate()`. + /// [ref] — read any provider the handler owns (e.g. token volume limits). + SpecificGrant buildSpecificGrant( + Map formValues, + WidgetRef ref, + ); +} +``` + +- [ ] **Step 2: Create `ether_transfer_grant.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +class EtherTransferGrantHandler implements GrantFormHandler { + const EtherTransferGrantHandler(); + + @override + Widget buildForm(BuildContext context, WidgetRef ref) => + const _EtherTransferForm(); + + @override + SpecificGrant buildSpecificGrant( + Map formValues, + WidgetRef ref, + ) { + return SpecificGrant( + etherTransfer: EtherTransferSettings( + targets: parseAddresses(formValues['etherRecipients'] as String? ?? ''), + limit: buildVolumeLimit( + formValues['etherVolume'] as String? ?? '', + formValues['etherVolumeWindow'] as String? ?? '', + ), + ), + ); + } +} + +class _EtherTransferForm extends StatelessWidget { + const _EtherTransferForm(); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + FormBuilderTextField( + name: 'etherRecipients', + minLines: 3, + maxLines: 6, + decoration: const InputDecoration( + labelText: 'Ether recipients', + hintText: + 'One 0x address per line. Leave empty for unrestricted targets.', + border: OutlineInputBorder(), + ), + ), + SizedBox(height: 1.6.h), + Text( + 'Ether volume limit', + style: Theme.of(context).textTheme.labelLarge?.copyWith( + fontWeight: FontWeight.w800, + ), + ), + SizedBox(height: 0.8.h), + Row( + children: [ + Expanded( + child: FormBuilderTextField( + name: 'etherVolume', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Max volume', + hintText: '1000000000000000000', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 1.w), + Expanded( + child: FormBuilderTextField( + name: 'etherVolumeWindow', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Window (seconds)', + hintText: '86400', + border: OutlineInputBorder(), + ), + ), + ), + ], + ), + ], + ); + } +} +``` + +- [ ] **Step 3: Create `token_transfer_grant.dart`** + +`TokenGrantLimits` is a scoped `@riverpod` provider (auto-dispose) that owns the dynamic volume limit list for the token grant form. `TokenTransferGrantHandler.buildSpecificGrant` reads it via `ref`. + +```dart +// lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; +import 'package:fixnum/fixnum.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:sizer/sizer.dart'; + +part 'token_transfer_grant.g.dart'; + +// --------------------------------------------------------------------------- +// Volume limit entry — a single row's data +// --------------------------------------------------------------------------- + +class VolumeLimitEntry { + const VolumeLimitEntry({this.amount = '', this.windowSeconds = ''}); + + final String amount; + final String windowSeconds; + + VolumeLimitEntry copyWith({String? amount, String? windowSeconds}) => + VolumeLimitEntry( + amount: amount ?? this.amount, + windowSeconds: windowSeconds ?? this.windowSeconds, + ); +} + +// --------------------------------------------------------------------------- +// Provider — owns token volume limits; auto-disposed when screen pops +// --------------------------------------------------------------------------- + +@riverpod +class TokenGrantLimits extends _$TokenGrantLimits { + @override + List build() => const [VolumeLimitEntry()]; + + void add() => state = [...state, const VolumeLimitEntry()]; + + void update(int index, VolumeLimitEntry entry) { + final updated = [...state]; + updated[index] = entry; + state = updated; + } + + void remove(int index) => state = [...state]..removeAt(index); +} + +// --------------------------------------------------------------------------- +// Handler +// --------------------------------------------------------------------------- + +class TokenTransferGrantHandler implements GrantFormHandler { + const TokenTransferGrantHandler(); + + @override + Widget buildForm(BuildContext context, WidgetRef ref) => + const _TokenTransferForm(); + + @override + SpecificGrant buildSpecificGrant( + Map formValues, + WidgetRef ref, + ) { + final limits = ref.read(tokenGrantLimitsProvider); + final targetText = formValues['tokenTarget'] as String? ?? ''; + + return SpecificGrant( + tokenTransfer: TokenTransferSettings( + tokenContract: + parseHexAddress(formValues['tokenContract'] as String? ?? ''), + target: targetText.trim().isEmpty ? null : parseHexAddress(targetText), + volumeLimits: limits + .where((e) => e.amount.trim().isNotEmpty) + .map( + (e) => VolumeRateLimit( + maxVolume: parseBigIntBytes(e.amount), + windowSecs: Int64.parseInt(e.windowSeconds), + ), + ) + .toList(), + ), + ); + } +} + +// --------------------------------------------------------------------------- +// Form widget +// --------------------------------------------------------------------------- + +class _TokenTransferForm extends ConsumerWidget { + const _TokenTransferForm(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final limits = ref.watch(tokenGrantLimitsProvider); + final notifier = ref.read(tokenGrantLimitsProvider.notifier); + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + FormBuilderTextField( + name: 'tokenContract', + decoration: const InputDecoration( + labelText: 'Token contract', + hintText: '0x...', + border: OutlineInputBorder(), + ), + ), + SizedBox(height: 1.6.h), + FormBuilderTextField( + name: 'tokenTarget', + decoration: const InputDecoration( + labelText: 'Token recipient', + hintText: '0x... or leave empty for any recipient', + border: OutlineInputBorder(), + ), + ), + SizedBox(height: 1.6.h), + _TokenVolumeLimitsField( + values: limits, + onAdd: notifier.add, + onUpdate: notifier.update, + onRemove: notifier.remove, + ), + ], + ); + } +} + +// --------------------------------------------------------------------------- +// Volume limits list widget +// --------------------------------------------------------------------------- + +class _TokenVolumeLimitsField extends StatelessWidget { + const _TokenVolumeLimitsField({ + required this.values, + required this.onAdd, + required this.onUpdate, + required this.onRemove, + }); + + final List values; + final VoidCallback onAdd; + final void Function(int index, VolumeLimitEntry entry) onUpdate; + final void Function(int index) onRemove; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + 'Token volume limits', + style: Theme.of(context).textTheme.labelLarge?.copyWith( + fontWeight: FontWeight.w800, + ), + ), + ), + TextButton.icon( + onPressed: onAdd, + icon: const Icon(Icons.add_rounded), + label: const Text('Add'), + ), + ], + ), + SizedBox(height: 0.8.h), + for (var i = 0; i < values.length; i++) + Padding( + padding: EdgeInsets.only(bottom: 1.h), + child: _TokenVolumeLimitRow( + key: ValueKey(i), + value: values[i], + onChanged: (entry) => onUpdate(i, entry), + onRemove: values.length == 1 ? null : () => onRemove(i), + ), + ), + ], + ); + } +} + +class _TokenVolumeLimitRow extends HookWidget { + const _TokenVolumeLimitRow({ + super.key, + required this.value, + required this.onChanged, + required this.onRemove, + }); + + final VolumeLimitEntry value; + final ValueChanged onChanged; + final VoidCallback? onRemove; + + @override + Widget build(BuildContext context) { + final amountController = useTextEditingController(text: value.amount); + final windowController = useTextEditingController(text: value.windowSeconds); + + return Row( + children: [ + Expanded( + child: TextField( + controller: amountController, + onChanged: (next) => onChanged(value.copyWith(amount: next)), + decoration: const InputDecoration( + labelText: 'Max volume', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 1.w), + Expanded( + child: TextField( + controller: windowController, + onChanged: (next) => + onChanged(value.copyWith(windowSeconds: next)), + decoration: const InputDecoration( + labelText: 'Window (seconds)', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 0.4.w), + IconButton( + onPressed: onRemove, + icon: const Icon(Icons.remove_circle_outline_rounded), + ), + ], + ); + } +} +``` + +- [ ] **Step 4: Run code generator for token_transfer_grant.g.dart** + +```sh +cd operator && dart run build_runner build --delete-conflicting-outputs +``` + +Expected: generates `token_transfer_grant.g.dart`, no errors. + +- [ ] **Step 5: Verify** + +```sh +cd operator && dart analyze lib/screens/dashboard/evm/grants/create/grants/ +``` + +Expected: no errors. + +- [ ] **Step 6: Commit** + +```sh +jj describe -m "feat(grants): add GrantFormHandler interface and per-type implementations" +``` + +--- + +## Task 6: Rewrite `screen.dart` + +**Files:** +- Modify: `lib/screens/dashboard/evm/grants/create/screen.dart` + +The screen owns `FormBuilder`, dispatches to the active handler, and assembles `SharedSettings` on submit. `validFrom`/`validUntil` are now read from `formValues['validFrom']` etc. — no more provider reads for dates. + +- [ ] **Step 1: Replace `screen.dart`** + +```dart +// lib/screens/dashboard/evm/grants/create/screen.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/providers/evm/evm_grants.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/shared_grant_fields.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:fixnum/fixnum.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; +import 'package:sizer/sizer.dart'; + +const _etherHandler = EtherTransferGrantHandler(); +const _tokenHandler = TokenTransferGrantHandler(); + +GrantFormHandler _handlerFor(SpecificGrant_Grant type) => switch (type) { + SpecificGrant_Grant.etherTransfer => _etherHandler, + SpecificGrant_Grant.tokenTransfer => _tokenHandler, + _ => throw ArgumentError('Unsupported grant type: $type'), + }; + +@RoutePage() +class CreateEvmGrantScreen extends HookConsumerWidget { + const CreateEvmGrantScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final formKey = useMemoized(() => GlobalKey()); + final createMutation = ref.watch(createEvmGrantMutation); + final state = ref.watch(grantCreationProvider); + final notifier = ref.read(grantCreationProvider.notifier); + final handler = _handlerFor(state.grantType); + + Future submit() async { + if (!(formKey.currentState?.saveAndValidate() ?? false)) return; + final formValues = formKey.currentState!.value; + + final accessId = formValues['walletAccessId'] as int?; + if (accessId == null) { + _showSnackBar(context, 'Select a client and wallet access.'); + return; + } + + try { + final specific = handler.buildSpecificGrant(formValues, ref); + final sharedSettings = SharedSettings( + walletAccessId: accessId, + chainId: Int64.parseInt( + (formValues['chainId'] as String? ?? '').trim(), + ), + ); + final validFrom = formValues['validFrom'] as DateTime?; + final validUntil = formValues['validUntil'] as DateTime?; + if (validFrom != null) sharedSettings.validFrom = toTimestamp(validFrom); + if (validUntil != null) { + sharedSettings.validUntil = toTimestamp(validUntil); + } + final gasBytes = + optionalBigIntBytes(formValues['maxGasFeePerGas'] as String? ?? ''); + if (gasBytes != null) sharedSettings.maxGasFeePerGas = gasBytes; + final priorityBytes = optionalBigIntBytes( + formValues['maxPriorityFeePerGas'] as String? ?? '', + ); + if (priorityBytes != null) { + sharedSettings.maxPriorityFeePerGas = priorityBytes; + } + final rateLimit = buildRateLimit( + formValues['txCount'] as String? ?? '', + formValues['txWindow'] as String? ?? '', + ); + if (rateLimit != null) sharedSettings.rateLimit = rateLimit; + + await executeCreateEvmGrant( + ref, + sharedSettings: sharedSettings, + specific: specific, + ); + if (!context.mounted) return; + context.router.pop(); + } catch (error) { + if (!context.mounted) return; + _showSnackBar(context, _formatError(error)); + } + } + + return Scaffold( + appBar: AppBar(title: const Text('Create EVM Grant')), + body: SafeArea( + child: FormBuilder( + key: formKey, + child: ListView( + padding: EdgeInsets.fromLTRB(2.4.w, 2.h, 2.4.w, 3.2.h), + children: [ + const _IntroCard(), + SizedBox(height: 1.8.h), + const _Section( + title: 'Shared grant options', + child: SharedGrantFields(), + ), + SizedBox(height: 1.8.h), + _GrantTypeSelector( + value: state.grantType, + onChanged: notifier.setGrantType, + ), + SizedBox(height: 1.8.h), + _Section( + title: 'Grant-specific options', + child: handler.buildForm(context, ref), + ), + SizedBox(height: 2.2.h), + Align( + alignment: Alignment.centerRight, + child: FilledButton.icon( + onPressed: + createMutation is MutationPending ? null : submit, + icon: createMutation is MutationPending + ? SizedBox( + width: 1.8.h, + height: 1.8.h, + child: const CircularProgressIndicator( + strokeWidth: 2.2, + ), + ) + : const Icon(Icons.check_rounded), + label: Text( + createMutation is MutationPending + ? 'Creating...' + : 'Create grant', + ), + ), + ), + ], + ), + ), + ), + ); + } +} + +// --------------------------------------------------------------------------- +// Layout helpers +// --------------------------------------------------------------------------- + +class _IntroCard extends StatelessWidget { + const _IntroCard(); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(2.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + gradient: const LinearGradient( + colors: [Color(0xFFF7F9FC), Color(0xFFFDF5EA)], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + border: Border.all(color: const Color(0x1A17324A)), + ), + child: Text( + 'Pick a client, then select one of the wallet accesses already granted ' + 'to it. Compose shared constraints once, then switch between Ether and ' + 'token transfer rules.', + style: Theme.of(context).textTheme.bodyLarge?.copyWith(height: 1.5), + ), + ); + } +} + +class _Section extends StatelessWidget { + const _Section({required this.title, required this.child}); + + final String title; + final Widget child; + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(2.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + color: Colors.white, + border: Border.all(color: const Color(0x1A17324A)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.w800, + ), + ), + SizedBox(height: 1.4.h), + child, + ], + ), + ); + } +} + +class _GrantTypeSelector extends StatelessWidget { + const _GrantTypeSelector({required this.value, required this.onChanged}); + + final SpecificGrant_Grant value; + final ValueChanged onChanged; + + @override + Widget build(BuildContext context) { + return SegmentedButton( + segments: const [ + ButtonSegment( + value: SpecificGrant_Grant.etherTransfer, + label: Text('Ether'), + icon: Icon(Icons.bolt_rounded), + ), + ButtonSegment( + value: SpecificGrant_Grant.tokenTransfer, + label: Text('Token'), + icon: Icon(Icons.token_rounded), + ), + ], + selected: {value}, + onSelectionChanged: (selection) => onChanged(selection.first), + ); + } +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- + +void _showSnackBar(BuildContext context, String message) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), + ); +} + +String _formatError(Object error) { + final text = error.toString(); + return text.startsWith('Exception: ') + ? text.substring('Exception: '.length) + : text; +} +``` + +- [ ] **Step 2: Verify the full create/ directory** + +```sh +cd operator && dart analyze lib/screens/dashboard/evm/grants/create/ +``` + +Expected: no errors. + +- [ ] **Step 3: Commit** + +```sh +jj describe -m "refactor(grants): decompose CreateEvmGrantScreen into provider + field widgets + grant handlers" +``` + +--- + +## Self-Review + +### Spec coverage + +| Requirement | Task | +|-------------|------| +| Riverpod provider for grant creation state | Task 2 (`GrantCreation`) | +| flutter_form_builder in composable manner | Tasks 3–4 | +| `fields/` folder for shared fields | Task 3 | +| Custom `FormBuilderDateTimeField` (no built-in) | Task 3, Step 4 | +| `validFrom`/`validUntil` as form fields | Task 3 (`ValidityWindowField` uses `FormBuilderDateTimeField`) | +| `tokenVolumeLimits` in grant-specific implementation | Task 5 (`TokenGrantLimits` in `token_transfer_grant.dart`) | +| Grant handler with `buildForm` + `buildSpecificGrant` | Task 5 | +| `SharedGrantFields` widget | Task 4 | +| Thin main screen | Task 6 | +| Class renamed to `GrantCreation` (provider: `grantCreationProvider`) | Task 2 | + +### Placeholder scan + +No TODOs, TBDs, or "similar to task N" references found. + +### Type consistency + +- `VolumeLimitEntry` defined in `token_transfer_grant.dart`, used only within that file ✓ +- `GrantFormHandler` interface: `buildSpecificGrant(Map, WidgetRef)` matches both implementations ✓ +- `grantCreationProvider` (from `@riverpod class GrantCreation`) used in `client_picker_field.dart`, `wallet_access_picker_field.dart`, `screen.dart` ✓ +- `tokenGrantLimitsProvider` (from `@riverpod class TokenGrantLimits`) used in `_TokenTransferForm.build` and `TokenTransferGrantHandler.buildSpecificGrant` ✓ +- FormBuilder field names in `screen.dart` (`validFrom`, `validUntil`, `walletAccessId`, `chainId`, `maxGasFeePerGas`, `maxPriorityFeePerGas`, `txCount`, `txWindow`) match the `name:` params in field widgets ✓ diff --git a/docs/superpowers/plans/2026-03-28-grant-grid-view.md b/docs/superpowers/plans/2026-03-28-grant-grid-view.md index babe563..adfc041 100644 --- a/docs/superpowers/plans/2026-03-28-grant-grid-view.md +++ b/docs/superpowers/plans/2026-03-28-grant-grid-view.md @@ -1,821 +1,821 @@ -# Grant Grid View Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Add an "EVM Grants" dashboard tab that displays all grants as enriched cards (type, chain, wallet address, client name) with per-card revoke support. - -**Architecture:** A new `walletAccessListProvider` fetches wallet accesses with their DB row IDs. The screen (`grants.dart`) watches only `evmGrantsProvider` for top-level state. Each `GrantCard` widget (its own file) watches enrichment providers (`walletAccessListProvider`, `evmProvider`, `sdkClientsProvider`) and the revoke mutation directly — keeping rebuilds scoped to the card. The screen is registered as a dashboard tab in `AdaptiveScaffold`. - -**Tech Stack:** Flutter, Riverpod (`riverpod_annotation` + `build_runner` codegen), `sizer` (adaptive sizing), `auto_route`, Protocol Buffers (Dart), `Palette` design tokens. - ---- - -## File Map - -| File | Action | Responsibility | -|---|---|---| -| `operator/lib/theme/palette.dart` | Modify | Add `Palette.token` (indigo accent for token-transfer cards) | -| `operator/lib/features/connection/evm/wallet_access.dart` | Modify | Add `listAllWalletAccesses()` function | -| `operator/lib/providers/sdk_clients/wallet_access_list.dart` | Create | `WalletAccessListProvider` — fetches full wallet access list with IDs | -| `operator/lib/screens/dashboard/evm/grants/widgets/grant_card.dart` | Create | `GrantCard` widget — watches enrichment providers + revoke mutation; one card per grant | -| `operator/lib/screens/dashboard/evm/grants/grants.dart` | Create | `EvmGrantsScreen` — watches `evmGrantsProvider`; handles loading/error/empty/data states; renders `GrantCard` list | -| `operator/lib/router.dart` | Modify | Register `EvmGrantsRoute` in dashboard children | -| `operator/lib/screens/dashboard.dart` | Modify | Add Grants entry to `routes` list and `NavigationDestination` list | - ---- - -## Task 1: Add `Palette.token` - -**Files:** -- Modify: `operator/lib/theme/palette.dart` - -- [ ] **Step 1: Add the color** - -Replace the contents of `operator/lib/theme/palette.dart` with: - -```dart -import 'package:flutter/material.dart'; - -class Palette { - static const ink = Color(0xFF15263C); - static const coral = Color(0xFFE26254); - static const cream = Color(0xFFFFFAF4); - static const line = Color(0x1A15263C); - static const token = Color(0xFF5C6BC0); -} -``` - -- [ ] **Step 2: Verify** - -```sh -cd operator && flutter analyze lib/theme/palette.dart -``` - -Expected: no issues. - -- [ ] **Step 3: Commit** - -```sh -jj describe -m "feat(theme): add Palette.token for token-transfer grant cards" -jj new -``` - ---- - -## Task 2: Add `listAllWalletAccesses` feature function - -**Files:** -- Modify: `operator/lib/features/connection/evm/wallet_access.dart` - -`readClientWalletAccess` (existing) filters the list to one client's wallet IDs and returns `Set`. This new function returns the complete unfiltered list with row IDs so the grant cards can resolve wallet_access_id → wallet + client. - -- [ ] **Step 1: Append function** - -Add at the bottom of `operator/lib/features/connection/evm/wallet_access.dart`: - -```dart -Future> listAllWalletAccesses( - Connection connection, -) async { - final response = await connection.ask( - OperatorRequest(listWalletAccess: Empty()), - ); - if (!response.hasListWalletAccessResponse()) { - throw Exception( - 'Expected list wallet access response, got ${response.whichPayload()}', - ); - } - return response.listWalletAccessResponse.accesses.toList(growable: false); -} -``` - -Each returned `SdkClientWalletAccess` has: -- `.id` — the `evm_wallet_access` row ID (same value as `wallet_access_id` in a `GrantEntry`) -- `.access.walletId` — the EVM wallet DB ID -- `.access.sdkClientId` — the SDK client DB ID - -- [ ] **Step 2: Verify** - -```sh -cd operator && flutter analyze lib/features/connection/evm/wallet_access.dart -``` - -Expected: no issues. - -- [ ] **Step 3: Commit** - -```sh -jj describe -m "feat(evm): add listAllWalletAccesses feature function" -jj new -``` - ---- - -## Task 3: Create `WalletAccessListProvider` - -**Files:** -- Create: `operator/lib/providers/sdk_clients/wallet_access_list.dart` -- Generated: `operator/lib/providers/sdk_clients/wallet_access_list.g.dart` - -Mirrors the structure of `EvmGrants` in `providers/evm/evm_grants.dart` — class-based `@riverpod` with a `refresh()` method. - -- [ ] **Step 1: Write the provider** - -Create `operator/lib/providers/sdk_clients/wallet_access_list.dart`: - -```dart -import 'package:arbiter/features/connection/evm/wallet_access.dart'; -import 'package:arbiter/proto/operator.pb.dart'; -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:mtcore/markettakers.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'wallet_access_list.g.dart'; - -@riverpod -class WalletAccessList extends _$WalletAccessList { - @override - Future?> build() async { - final connection = await ref.watch(connectionManagerProvider.future); - if (connection == null) { - return null; - } - - try { - return await listAllWalletAccesses(connection); - } catch (e, st) { - talker.handle(e, st); - rethrow; - } - } - - Future refresh() async { - final connection = await ref.read(connectionManagerProvider.future); - if (connection == null) { - state = const AsyncData(null); - return; - } - - state = const AsyncLoading(); - state = await AsyncValue.guard(() => listAllWalletAccesses(connection)); - } -} -``` - -- [ ] **Step 2: Run code generation** - -```sh -cd operator && dart run build_runner build --delete-conflicting-outputs -``` - -Expected: `operator/lib/providers/sdk_clients/wallet_access_list.g.dart` created. No errors. - -- [ ] **Step 3: Verify** - -```sh -cd operator && flutter analyze lib/providers/sdk_clients/ -``` - -Expected: no issues. - -- [ ] **Step 4: Commit** - -```sh -jj describe -m "feat(providers): add WalletAccessListProvider" -jj new -``` - ---- - -## Task 4: Create `GrantCard` widget - -**Files:** -- Create: `operator/lib/screens/dashboard/evm/grants/widgets/grant_card.dart` - -This widget owns all per-card logic: enrichment lookups, revoke action, and rebuild scope. The screen only passes it a `GrantEntry` — the card fetches everything else itself. - -**Key types:** -- `GrantEntry` (from `proto/evm.pb.dart`): `.id`, `.shared.walletAccessId`, `.shared.chainId`, `.specific.whichGrant()` -- `SpecificGrant_Grant.etherTransfer` / `.tokenTransfer` — enum values for the oneof -- `SdkClientWalletAccess` (from `proto/operator.pb.dart`): `.id`, `.access.walletId`, `.access.sdkClientId` -- `WalletEntry` (from `proto/evm.pb.dart`): `.id`, `.address` (List) -- `SdkClientEntry` (from `proto/operator.pb.dart`): `.id`, `.info.name` -- `revokeEvmGrantMutation` — `Mutation` (global; all revoke buttons disable together while any revoke is in flight) -- `executeRevokeEvmGrant(ref, grantId: int)` — `Future` - -- [ ] **Step 1: Write the widget** - -Create `operator/lib/screens/dashboard/evm/grants/widgets/grant_card.dart`: - -```dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/proto/operator.pb.dart'; -import 'package:arbiter/providers/evm/evm.dart'; -import 'package:arbiter/providers/evm/evm_grants.dart'; -import 'package:arbiter/providers/sdk_clients/list.dart'; -import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -String _shortAddress(List bytes) { - final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); - return '0x${hex.substring(0, 6)}...${hex.substring(hex.length - 4)}'; -} - -String _formatError(Object error) { - final message = error.toString(); - if (message.startsWith('Exception: ')) { - return message.substring('Exception: '.length); - } - return message; -} - -class GrantCard extends ConsumerWidget { - const GrantCard({super.key, required this.grant}); - - final GrantEntry grant; - - @override - Widget build(BuildContext context, WidgetRef ref) { - // Enrichment lookups — each watch scopes rebuilds to this card only - final walletAccesses = - ref.watch(walletAccessListProvider).asData?.value ?? const []; - final wallets = ref.watch(evmProvider).asData?.value ?? const []; - final clients = ref.watch(sdkClientsProvider).asData?.value ?? const []; - final revoking = ref.watch(revokeEvmGrantMutation) is MutationPending; - - final isEther = - grant.specific.whichGrant() == SpecificGrant_Grant.etherTransfer; - final accent = isEther ? Palette.coral : Palette.token; - final typeLabel = isEther ? 'Ether' : 'Token'; - final theme = Theme.of(context); - final muted = Palette.ink.withValues(alpha: 0.62); - - // Resolve wallet_access_id → wallet address + client name - final accessById = { - for (final a in walletAccesses) a.id: a, - }; - final walletById = { - for (final w in wallets) w.id: w, - }; - final clientNameById = { - for (final c in clients) c.id: c.info.name, - }; - - final accessId = grant.shared.walletAccessId; - final access = accessById[accessId]; - final wallet = access != null ? walletById[access.access.walletId] : null; - - final walletLabel = wallet != null - ? _shortAddress(wallet.address) - : 'Access #$accessId'; - - final clientLabel = () { - if (access == null) return ''; - final name = clientNameById[access.access.sdkClientId] ?? ''; - return name.isEmpty ? 'Client #${access.access.sdkClientId}' : name; - }(); - - void showError(String message) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), - ); - } - - Future revoke() async { - try { - await executeRevokeEvmGrant(ref, grantId: grant.id); - } catch (e) { - showError(_formatError(e)); - } - } - - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), - color: Palette.cream.withValues(alpha: 0.92), - border: Border.all(color: Palette.line), - ), - child: IntrinsicHeight( - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // Accent strip - Container( - width: 0.8.w, - decoration: BoxDecoration( - color: accent, - borderRadius: const BorderRadius.horizontal( - left: Radius.circular(24), - ), - ), - ), - // Card body - Expanded( - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: 1.6.w, - vertical: 1.4.h, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Row 1: type badge · chain · spacer · revoke button - Row( - children: [ - Container( - padding: EdgeInsets.symmetric( - horizontal: 1.w, - vertical: 0.4.h, - ), - decoration: BoxDecoration( - color: accent.withValues(alpha: 0.15), - borderRadius: BorderRadius.circular(8), - ), - child: Text( - typeLabel, - style: theme.textTheme.labelSmall?.copyWith( - color: accent, - fontWeight: FontWeight.w800, - ), - ), - ), - SizedBox(width: 1.w), - Container( - padding: EdgeInsets.symmetric( - horizontal: 1.w, - vertical: 0.4.h, - ), - decoration: BoxDecoration( - color: Palette.ink.withValues(alpha: 0.06), - borderRadius: BorderRadius.circular(8), - ), - child: Text( - 'Chain ${grant.shared.chainId}', - style: theme.textTheme.labelSmall?.copyWith( - color: muted, - fontWeight: FontWeight.w700, - ), - ), - ), - const Spacer(), - if (revoking) - SizedBox( - width: 1.8.h, - height: 1.8.h, - child: CircularProgressIndicator( - strokeWidth: 2, - color: Palette.coral, - ), - ) - else - OutlinedButton.icon( - onPressed: revoke, - style: OutlinedButton.styleFrom( - foregroundColor: Palette.coral, - side: BorderSide( - color: Palette.coral.withValues(alpha: 0.4), - ), - padding: EdgeInsets.symmetric( - horizontal: 1.w, - vertical: 0.6.h, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - ), - icon: const Icon(Icons.block_rounded, size: 16), - label: const Text('Revoke'), - ), - ], - ), - SizedBox(height: 0.8.h), - // Row 2: wallet address · client name - Row( - children: [ - Text( - walletLabel, - style: theme.textTheme.bodySmall?.copyWith( - color: Palette.ink, - fontFamily: 'monospace', - ), - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 0.8.w), - child: Text( - '·', - style: theme.textTheme.bodySmall - ?.copyWith(color: muted), - ), - ), - Expanded( - child: Text( - clientLabel, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.bodySmall - ?.copyWith(color: muted), - ), - ), - ], - ), - ], - ), - ), - ), - ], - ), - ), - ); - } -} -``` - -- [ ] **Step 2: Verify** - -```sh -cd operator && flutter analyze lib/screens/dashboard/evm/grants/widgets/grant_card.dart -``` - -Expected: no issues. - -- [ ] **Step 3: Commit** - -```sh -jj describe -m "feat(grants): add GrantCard widget with self-contained enrichment" -jj new -``` - ---- - -## Task 5: Create `EvmGrantsScreen` - -**Files:** -- Create: `operator/lib/screens/dashboard/evm/grants/grants.dart` - -The screen watches only `evmGrantsProvider` for top-level state (loading / error / no connection / empty / data). When there is data it renders a list of `GrantCard` widgets — each card manages its own enrichment subscriptions. - -- [ ] **Step 1: Write the screen** - -Create `operator/lib/screens/dashboard/evm/grants/grants.dart`: - -```dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/providers/evm/evm_grants.dart'; -import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; -import 'package:arbiter/router.gr.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/widgets/grant_card.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:arbiter/widgets/page_header.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -String _formatError(Object error) { - final message = error.toString(); - if (message.startsWith('Exception: ')) { - return message.substring('Exception: '.length); - } - return message; -} - -// ─── State panel ────────────────────────────────────────────────────────────── - -class _StatePanel extends StatelessWidget { - const _StatePanel({ - required this.icon, - required this.title, - required this.body, - this.actionLabel, - this.onAction, - this.busy = false, - }); - - final IconData icon; - final String title; - final String body; - final String? actionLabel; - final Future Function()? onAction; - final bool busy; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), - color: Palette.cream.withValues(alpha: 0.92), - border: Border.all(color: Palette.line), - ), - child: Padding( - padding: EdgeInsets.all(2.8.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (busy) - SizedBox( - width: 2.8.h, - height: 2.8.h, - child: const CircularProgressIndicator(strokeWidth: 2.5), - ) - else - Icon(icon, size: 34, color: Palette.coral), - SizedBox(height: 1.8.h), - Text( - title, - style: theme.textTheme.headlineSmall?.copyWith( - color: Palette.ink, - fontWeight: FontWeight.w800, - ), - ), - SizedBox(height: 1.h), - Text( - body, - style: theme.textTheme.bodyLarge?.copyWith( - color: Palette.ink.withValues(alpha: 0.72), - height: 1.5, - ), - ), - if (actionLabel != null && onAction != null) ...[ - SizedBox(height: 2.h), - OutlinedButton.icon( - onPressed: () => onAction!(), - icon: const Icon(Icons.refresh), - label: Text(actionLabel!), - ), - ], - ], - ), - ), - ); - } -} - -// ─── Grant list ─────────────────────────────────────────────────────────────── - -class _GrantList extends StatelessWidget { - const _GrantList({required this.grants}); - - final List grants; - - @override - Widget build(BuildContext context) { - return Column( - children: [ - for (var i = 0; i < grants.length; i++) - Padding( - padding: EdgeInsets.only( - bottom: i == grants.length - 1 ? 0 : 1.8.h, - ), - child: GrantCard(grant: grants[i]), - ), - ], - ); - } -} - -// ─── Screen ─────────────────────────────────────────────────────────────────── - -@RoutePage() -class EvmGrantsScreen extends ConsumerWidget { - const EvmGrantsScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - // Screen watches only the grant list for top-level state decisions - final grantsAsync = ref.watch(evmGrantsProvider); - - Future refresh() async { - await Future.wait([ - ref.read(evmGrantsProvider.notifier).refresh(), - ref.read(walletAccessListProvider.notifier).refresh(), - ]); - } - - void showMessage(String message) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), - ); - } - - Future safeRefresh() async { - try { - await refresh(); - } catch (e) { - showMessage(_formatError(e)); - } - } - - final grantsState = grantsAsync.asData?.value; - final grants = grantsState?.grants; - - final content = switch (grantsAsync) { - AsyncLoading() when grantsState == null => const _StatePanel( - icon: Icons.hourglass_top, - title: 'Loading grants', - body: 'Pulling grant registry from Arbiter.', - busy: true, - ), - AsyncError(:final error) => _StatePanel( - icon: Icons.sync_problem, - title: 'Grant registry unavailable', - body: _formatError(error), - actionLabel: 'Retry', - onAction: safeRefresh, - ), - AsyncData(:final value) when value == null => _StatePanel( - icon: Icons.portable_wifi_off, - title: 'No active server connection', - body: 'Reconnect to Arbiter to list EVM grants.', - actionLabel: 'Refresh', - onAction: safeRefresh, - ), - _ when grants != null && grants.isEmpty => _StatePanel( - icon: Icons.policy_outlined, - title: 'No grants yet', - body: 'Create a grant to allow SDK clients to sign transactions.', - actionLabel: 'Create grant', - onAction: () => context.router.push(const CreateEvmGrantRoute()), - ), - _ => _GrantList(grants: grants ?? const []), - }; - - return Scaffold( - body: SafeArea( - child: RefreshIndicator.adaptive( - color: Palette.ink, - backgroundColor: Colors.white, - onRefresh: safeRefresh, - child: ListView( - physics: const BouncingScrollPhysics( - parent: AlwaysScrollableScrollPhysics(), - ), - padding: EdgeInsets.fromLTRB(2.4.w, 2.4.h, 2.4.w, 3.2.h), - children: [ - PageHeader( - title: 'EVM Grants', - isBusy: grantsAsync.isLoading, - actions: [ - FilledButton.icon( - onPressed: () => - context.router.push(const CreateEvmGrantRoute()), - icon: const Icon(Icons.add_rounded), - label: const Text('Create grant'), - ), - SizedBox(width: 1.w), - OutlinedButton.icon( - onPressed: safeRefresh, - style: OutlinedButton.styleFrom( - foregroundColor: Palette.ink, - side: BorderSide(color: Palette.line), - padding: EdgeInsets.symmetric( - horizontal: 1.4.w, - vertical: 1.2.h, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(14), - ), - ), - icon: const Icon(Icons.refresh, size: 18), - label: const Text('Refresh'), - ), - ], - ), - SizedBox(height: 1.8.h), - content, - ], - ), - ), - ), - ); - } -} -``` - -- [ ] **Step 2: Verify** - -```sh -cd operator && flutter analyze lib/screens/dashboard/evm/grants/ -``` - -Expected: no issues. - -- [ ] **Step 3: Commit** - -```sh -jj describe -m "feat(grants): add EvmGrantsScreen" -jj new -``` - ---- - -## Task 6: Wire router and dashboard tab - -**Files:** -- Modify: `operator/lib/router.dart` -- Modify: `operator/lib/screens/dashboard.dart` -- Regenerated: `operator/lib/router.gr.dart` - -- [ ] **Step 1: Add route to `router.dart`** - -Replace the contents of `operator/lib/router.dart` with: - -```dart -import 'package:auto_route/auto_route.dart'; - -import 'router.gr.dart'; - -@AutoRouterConfig(generateForDir: ['lib/screens']) -class Router extends RootStackRouter { - @override - List get routes => [ - AutoRoute(page: Bootstrap.page, path: '/bootstrap', initial: true), - AutoRoute(page: ServerInfoSetupRoute.page, path: '/server-info'), - AutoRoute(page: ServerConnectionRoute.page, path: '/server-connection'), - AutoRoute(page: VaultSetupRoute.page, path: '/vault'), - AutoRoute(page: ClientDetailsRoute.page, path: '/clients/:clientId'), - AutoRoute(page: CreateEvmGrantRoute.page, path: '/evm-grants/create'), - - AutoRoute( - page: DashboardRouter.page, - path: '/dashboard', - children: [ - AutoRoute(page: EvmRoute.page, path: 'evm'), - AutoRoute(page: ClientsRoute.page, path: 'clients'), - AutoRoute(page: EvmGrantsRoute.page, path: 'grants'), - AutoRoute(page: AboutRoute.page, path: 'about'), - ], - ), - ]; -} -``` - -- [ ] **Step 2: Update `dashboard.dart`** - -In `operator/lib/screens/dashboard.dart`, replace the `routes` constant: - -```dart -final routes = [ - const EvmRoute(), - const ClientsRoute(), - const EvmGrantsRoute(), - const AboutRoute(), -]; -``` - -And replace the `destinations` list inside `AdaptiveScaffold`: - -```dart -destinations: const [ - NavigationDestination( - icon: Icon(Icons.account_balance_wallet_outlined), - selectedIcon: Icon(Icons.account_balance_wallet), - label: 'Wallets', - ), - NavigationDestination( - icon: Icon(Icons.devices_other_outlined), - selectedIcon: Icon(Icons.devices_other), - label: 'Clients', - ), - NavigationDestination( - icon: Icon(Icons.policy_outlined), - selectedIcon: Icon(Icons.policy), - label: 'Grants', - ), - NavigationDestination( - icon: Icon(Icons.info_outline), - selectedIcon: Icon(Icons.info), - label: 'About', - ), -], -``` - -- [ ] **Step 3: Regenerate router** - -```sh -cd operator && dart run build_runner build --delete-conflicting-outputs -``` - -Expected: `lib/router.gr.dart` updated, `EvmGrantsRoute` now available, no errors. - -- [ ] **Step 4: Full project verify** - -```sh -cd operator && flutter analyze -``` - -Expected: no issues. - -- [ ] **Step 5: Commit** - -```sh -jj describe -m "feat(nav): add Grants dashboard tab" -jj new -``` +# Grant Grid View Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add an "EVM Grants" dashboard tab that displays all grants as enriched cards (type, chain, wallet address, client name) with per-card revoke support. + +**Architecture:** A new `walletAccessListProvider` fetches wallet accesses with their DB row IDs. The screen (`grants.dart`) watches only `evmGrantsProvider` for top-level state. Each `GrantCard` widget (its own file) watches enrichment providers (`walletAccessListProvider`, `evmProvider`, `sdkClientsProvider`) and the revoke mutation directly — keeping rebuilds scoped to the card. The screen is registered as a dashboard tab in `AdaptiveScaffold`. + +**Tech Stack:** Flutter, Riverpod (`riverpod_annotation` + `build_runner` codegen), `sizer` (adaptive sizing), `auto_route`, Protocol Buffers (Dart), `Palette` design tokens. + +--- + +## File Map + +| File | Action | Responsibility | +|---|---|---| +| `operator/lib/theme/palette.dart` | Modify | Add `Palette.token` (indigo accent for token-transfer cards) | +| `operator/lib/features/connection/evm/wallet_access.dart` | Modify | Add `listAllWalletAccesses()` function | +| `operator/lib/providers/sdk_clients/wallet_access_list.dart` | Create | `WalletAccessListProvider` — fetches full wallet access list with IDs | +| `operator/lib/screens/dashboard/evm/grants/widgets/grant_card.dart` | Create | `GrantCard` widget — watches enrichment providers + revoke mutation; one card per grant | +| `operator/lib/screens/dashboard/evm/grants/grants.dart` | Create | `EvmGrantsScreen` — watches `evmGrantsProvider`; handles loading/error/empty/data states; renders `GrantCard` list | +| `operator/lib/router.dart` | Modify | Register `EvmGrantsRoute` in dashboard children | +| `operator/lib/screens/dashboard.dart` | Modify | Add Grants entry to `routes` list and `NavigationDestination` list | + +--- + +## Task 1: Add `Palette.token` + +**Files:** +- Modify: `operator/lib/theme/palette.dart` + +- [ ] **Step 1: Add the color** + +Replace the contents of `operator/lib/theme/palette.dart` with: + +```dart +import 'package:flutter/material.dart'; + +class Palette { + static const ink = Color(0xFF15263C); + static const coral = Color(0xFFE26254); + static const cream = Color(0xFFFFFAF4); + static const line = Color(0x1A15263C); + static const token = Color(0xFF5C6BC0); +} +``` + +- [ ] **Step 2: Verify** + +```sh +cd operator && flutter analyze lib/theme/palette.dart +``` + +Expected: no issues. + +- [ ] **Step 3: Commit** + +```sh +jj describe -m "feat(theme): add Palette.token for token-transfer grant cards" +jj new +``` + +--- + +## Task 2: Add `listAllWalletAccesses` feature function + +**Files:** +- Modify: `operator/lib/features/connection/evm/wallet_access.dart` + +`readClientWalletAccess` (existing) filters the list to one client's wallet IDs and returns `Set`. This new function returns the complete unfiltered list with row IDs so the grant cards can resolve wallet_access_id → wallet + client. + +- [ ] **Step 1: Append function** + +Add at the bottom of `operator/lib/features/connection/evm/wallet_access.dart`: + +```dart +Future> listAllWalletAccesses( + Connection connection, +) async { + final response = await connection.ask( + OperatorRequest(listWalletAccess: Empty()), + ); + if (!response.hasListWalletAccessResponse()) { + throw Exception( + 'Expected list wallet access response, got ${response.whichPayload()}', + ); + } + return response.listWalletAccessResponse.accesses.toList(growable: false); +} +``` + +Each returned `SdkClientWalletAccess` has: +- `.id` — the `evm_wallet_access` row ID (same value as `wallet_access_id` in a `GrantEntry`) +- `.access.walletId` — the EVM wallet DB ID +- `.access.sdkClientId` — the SDK client DB ID + +- [ ] **Step 2: Verify** + +```sh +cd operator && flutter analyze lib/features/connection/evm/wallet_access.dart +``` + +Expected: no issues. + +- [ ] **Step 3: Commit** + +```sh +jj describe -m "feat(evm): add listAllWalletAccesses feature function" +jj new +``` + +--- + +## Task 3: Create `WalletAccessListProvider` + +**Files:** +- Create: `operator/lib/providers/sdk_clients/wallet_access_list.dart` +- Generated: `operator/lib/providers/sdk_clients/wallet_access_list.g.dart` + +Mirrors the structure of `EvmGrants` in `providers/evm/evm_grants.dart` — class-based `@riverpod` with a `refresh()` method. + +- [ ] **Step 1: Write the provider** + +Create `operator/lib/providers/sdk_clients/wallet_access_list.dart`: + +```dart +import 'package:arbiter/features/connection/evm/wallet_access.dart'; +import 'package:arbiter/proto/operator.pb.dart'; +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:mtcore/markettakers.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'wallet_access_list.g.dart'; + +@riverpod +class WalletAccessList extends _$WalletAccessList { + @override + Future?> build() async { + final connection = await ref.watch(connectionManagerProvider.future); + if (connection == null) { + return null; + } + + try { + return await listAllWalletAccesses(connection); + } catch (e, st) { + talker.handle(e, st); + rethrow; + } + } + + Future refresh() async { + final connection = await ref.read(connectionManagerProvider.future); + if (connection == null) { + state = const AsyncData(null); + return; + } + + state = const AsyncLoading(); + state = await AsyncValue.guard(() => listAllWalletAccesses(connection)); + } +} +``` + +- [ ] **Step 2: Run code generation** + +```sh +cd operator && dart run build_runner build --delete-conflicting-outputs +``` + +Expected: `operator/lib/providers/sdk_clients/wallet_access_list.g.dart` created. No errors. + +- [ ] **Step 3: Verify** + +```sh +cd operator && flutter analyze lib/providers/sdk_clients/ +``` + +Expected: no issues. + +- [ ] **Step 4: Commit** + +```sh +jj describe -m "feat(providers): add WalletAccessListProvider" +jj new +``` + +--- + +## Task 4: Create `GrantCard` widget + +**Files:** +- Create: `operator/lib/screens/dashboard/evm/grants/widgets/grant_card.dart` + +This widget owns all per-card logic: enrichment lookups, revoke action, and rebuild scope. The screen only passes it a `GrantEntry` — the card fetches everything else itself. + +**Key types:** +- `GrantEntry` (from `proto/evm.pb.dart`): `.id`, `.shared.walletAccessId`, `.shared.chainId`, `.specific.whichGrant()` +- `SpecificGrant_Grant.etherTransfer` / `.tokenTransfer` — enum values for the oneof +- `SdkClientWalletAccess` (from `proto/operator.pb.dart`): `.id`, `.access.walletId`, `.access.sdkClientId` +- `WalletEntry` (from `proto/evm.pb.dart`): `.id`, `.address` (List) +- `SdkClientEntry` (from `proto/operator.pb.dart`): `.id`, `.info.name` +- `revokeEvmGrantMutation` — `Mutation` (global; all revoke buttons disable together while any revoke is in flight) +- `executeRevokeEvmGrant(ref, grantId: int)` — `Future` + +- [ ] **Step 1: Write the widget** + +Create `operator/lib/screens/dashboard/evm/grants/widgets/grant_card.dart`: + +```dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/proto/operator.pb.dart'; +import 'package:arbiter/providers/evm/evm.dart'; +import 'package:arbiter/providers/evm/evm_grants.dart'; +import 'package:arbiter/providers/sdk_clients/list.dart'; +import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +String _shortAddress(List bytes) { + final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); + return '0x${hex.substring(0, 6)}...${hex.substring(hex.length - 4)}'; +} + +String _formatError(Object error) { + final message = error.toString(); + if (message.startsWith('Exception: ')) { + return message.substring('Exception: '.length); + } + return message; +} + +class GrantCard extends ConsumerWidget { + const GrantCard({super.key, required this.grant}); + + final GrantEntry grant; + + @override + Widget build(BuildContext context, WidgetRef ref) { + // Enrichment lookups — each watch scopes rebuilds to this card only + final walletAccesses = + ref.watch(walletAccessListProvider).asData?.value ?? const []; + final wallets = ref.watch(evmProvider).asData?.value ?? const []; + final clients = ref.watch(sdkClientsProvider).asData?.value ?? const []; + final revoking = ref.watch(revokeEvmGrantMutation) is MutationPending; + + final isEther = + grant.specific.whichGrant() == SpecificGrant_Grant.etherTransfer; + final accent = isEther ? Palette.coral : Palette.token; + final typeLabel = isEther ? 'Ether' : 'Token'; + final theme = Theme.of(context); + final muted = Palette.ink.withValues(alpha: 0.62); + + // Resolve wallet_access_id → wallet address + client name + final accessById = { + for (final a in walletAccesses) a.id: a, + }; + final walletById = { + for (final w in wallets) w.id: w, + }; + final clientNameById = { + for (final c in clients) c.id: c.info.name, + }; + + final accessId = grant.shared.walletAccessId; + final access = accessById[accessId]; + final wallet = access != null ? walletById[access.access.walletId] : null; + + final walletLabel = wallet != null + ? _shortAddress(wallet.address) + : 'Access #$accessId'; + + final clientLabel = () { + if (access == null) return ''; + final name = clientNameById[access.access.sdkClientId] ?? ''; + return name.isEmpty ? 'Client #${access.access.sdkClientId}' : name; + }(); + + void showError(String message) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), + ); + } + + Future revoke() async { + try { + await executeRevokeEvmGrant(ref, grantId: grant.id); + } catch (e) { + showError(_formatError(e)); + } + } + + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + color: Palette.cream.withValues(alpha: 0.92), + border: Border.all(color: Palette.line), + ), + child: IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Accent strip + Container( + width: 0.8.w, + decoration: BoxDecoration( + color: accent, + borderRadius: const BorderRadius.horizontal( + left: Radius.circular(24), + ), + ), + ), + // Card body + Expanded( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: 1.6.w, + vertical: 1.4.h, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Row 1: type badge · chain · spacer · revoke button + Row( + children: [ + Container( + padding: EdgeInsets.symmetric( + horizontal: 1.w, + vertical: 0.4.h, + ), + decoration: BoxDecoration( + color: accent.withValues(alpha: 0.15), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + typeLabel, + style: theme.textTheme.labelSmall?.copyWith( + color: accent, + fontWeight: FontWeight.w800, + ), + ), + ), + SizedBox(width: 1.w), + Container( + padding: EdgeInsets.symmetric( + horizontal: 1.w, + vertical: 0.4.h, + ), + decoration: BoxDecoration( + color: Palette.ink.withValues(alpha: 0.06), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + 'Chain ${grant.shared.chainId}', + style: theme.textTheme.labelSmall?.copyWith( + color: muted, + fontWeight: FontWeight.w700, + ), + ), + ), + const Spacer(), + if (revoking) + SizedBox( + width: 1.8.h, + height: 1.8.h, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Palette.coral, + ), + ) + else + OutlinedButton.icon( + onPressed: revoke, + style: OutlinedButton.styleFrom( + foregroundColor: Palette.coral, + side: BorderSide( + color: Palette.coral.withValues(alpha: 0.4), + ), + padding: EdgeInsets.symmetric( + horizontal: 1.w, + vertical: 0.6.h, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + icon: const Icon(Icons.block_rounded, size: 16), + label: const Text('Revoke'), + ), + ], + ), + SizedBox(height: 0.8.h), + // Row 2: wallet address · client name + Row( + children: [ + Text( + walletLabel, + style: theme.textTheme.bodySmall?.copyWith( + color: Palette.ink, + fontFamily: 'monospace', + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 0.8.w), + child: Text( + '·', + style: theme.textTheme.bodySmall + ?.copyWith(color: muted), + ), + ), + Expanded( + child: Text( + clientLabel, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodySmall + ?.copyWith(color: muted), + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ), + ); + } +} +``` + +- [ ] **Step 2: Verify** + +```sh +cd operator && flutter analyze lib/screens/dashboard/evm/grants/widgets/grant_card.dart +``` + +Expected: no issues. + +- [ ] **Step 3: Commit** + +```sh +jj describe -m "feat(grants): add GrantCard widget with self-contained enrichment" +jj new +``` + +--- + +## Task 5: Create `EvmGrantsScreen` + +**Files:** +- Create: `operator/lib/screens/dashboard/evm/grants/grants.dart` + +The screen watches only `evmGrantsProvider` for top-level state (loading / error / no connection / empty / data). When there is data it renders a list of `GrantCard` widgets — each card manages its own enrichment subscriptions. + +- [ ] **Step 1: Write the screen** + +Create `operator/lib/screens/dashboard/evm/grants/grants.dart`: + +```dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/providers/evm/evm_grants.dart'; +import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; +import 'package:arbiter/router.gr.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/widgets/grant_card.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:arbiter/widgets/page_header.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +String _formatError(Object error) { + final message = error.toString(); + if (message.startsWith('Exception: ')) { + return message.substring('Exception: '.length); + } + return message; +} + +// ─── State panel ────────────────────────────────────────────────────────────── + +class _StatePanel extends StatelessWidget { + const _StatePanel({ + required this.icon, + required this.title, + required this.body, + this.actionLabel, + this.onAction, + this.busy = false, + }); + + final IconData icon; + final String title; + final String body; + final String? actionLabel; + final Future Function()? onAction; + final bool busy; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + color: Palette.cream.withValues(alpha: 0.92), + border: Border.all(color: Palette.line), + ), + child: Padding( + padding: EdgeInsets.all(2.8.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (busy) + SizedBox( + width: 2.8.h, + height: 2.8.h, + child: const CircularProgressIndicator(strokeWidth: 2.5), + ) + else + Icon(icon, size: 34, color: Palette.coral), + SizedBox(height: 1.8.h), + Text( + title, + style: theme.textTheme.headlineSmall?.copyWith( + color: Palette.ink, + fontWeight: FontWeight.w800, + ), + ), + SizedBox(height: 1.h), + Text( + body, + style: theme.textTheme.bodyLarge?.copyWith( + color: Palette.ink.withValues(alpha: 0.72), + height: 1.5, + ), + ), + if (actionLabel != null && onAction != null) ...[ + SizedBox(height: 2.h), + OutlinedButton.icon( + onPressed: () => onAction!(), + icon: const Icon(Icons.refresh), + label: Text(actionLabel!), + ), + ], + ], + ), + ), + ); + } +} + +// ─── Grant list ─────────────────────────────────────────────────────────────── + +class _GrantList extends StatelessWidget { + const _GrantList({required this.grants}); + + final List grants; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + for (var i = 0; i < grants.length; i++) + Padding( + padding: EdgeInsets.only( + bottom: i == grants.length - 1 ? 0 : 1.8.h, + ), + child: GrantCard(grant: grants[i]), + ), + ], + ); + } +} + +// ─── Screen ─────────────────────────────────────────────────────────────────── + +@RoutePage() +class EvmGrantsScreen extends ConsumerWidget { + const EvmGrantsScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + // Screen watches only the grant list for top-level state decisions + final grantsAsync = ref.watch(evmGrantsProvider); + + Future refresh() async { + await Future.wait([ + ref.read(evmGrantsProvider.notifier).refresh(), + ref.read(walletAccessListProvider.notifier).refresh(), + ]); + } + + void showMessage(String message) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), + ); + } + + Future safeRefresh() async { + try { + await refresh(); + } catch (e) { + showMessage(_formatError(e)); + } + } + + final grantsState = grantsAsync.asData?.value; + final grants = grantsState?.grants; + + final content = switch (grantsAsync) { + AsyncLoading() when grantsState == null => const _StatePanel( + icon: Icons.hourglass_top, + title: 'Loading grants', + body: 'Pulling grant registry from Arbiter.', + busy: true, + ), + AsyncError(:final error) => _StatePanel( + icon: Icons.sync_problem, + title: 'Grant registry unavailable', + body: _formatError(error), + actionLabel: 'Retry', + onAction: safeRefresh, + ), + AsyncData(:final value) when value == null => _StatePanel( + icon: Icons.portable_wifi_off, + title: 'No active server connection', + body: 'Reconnect to Arbiter to list EVM grants.', + actionLabel: 'Refresh', + onAction: safeRefresh, + ), + _ when grants != null && grants.isEmpty => _StatePanel( + icon: Icons.policy_outlined, + title: 'No grants yet', + body: 'Create a grant to allow SDK clients to sign transactions.', + actionLabel: 'Create grant', + onAction: () => context.router.push(const CreateEvmGrantRoute()), + ), + _ => _GrantList(grants: grants ?? const []), + }; + + return Scaffold( + body: SafeArea( + child: RefreshIndicator.adaptive( + color: Palette.ink, + backgroundColor: Colors.white, + onRefresh: safeRefresh, + child: ListView( + physics: const BouncingScrollPhysics( + parent: AlwaysScrollableScrollPhysics(), + ), + padding: EdgeInsets.fromLTRB(2.4.w, 2.4.h, 2.4.w, 3.2.h), + children: [ + PageHeader( + title: 'EVM Grants', + isBusy: grantsAsync.isLoading, + actions: [ + FilledButton.icon( + onPressed: () => + context.router.push(const CreateEvmGrantRoute()), + icon: const Icon(Icons.add_rounded), + label: const Text('Create grant'), + ), + SizedBox(width: 1.w), + OutlinedButton.icon( + onPressed: safeRefresh, + style: OutlinedButton.styleFrom( + foregroundColor: Palette.ink, + side: BorderSide(color: Palette.line), + padding: EdgeInsets.symmetric( + horizontal: 1.4.w, + vertical: 1.2.h, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(14), + ), + ), + icon: const Icon(Icons.refresh, size: 18), + label: const Text('Refresh'), + ), + ], + ), + SizedBox(height: 1.8.h), + content, + ], + ), + ), + ), + ); + } +} +``` + +- [ ] **Step 2: Verify** + +```sh +cd operator && flutter analyze lib/screens/dashboard/evm/grants/ +``` + +Expected: no issues. + +- [ ] **Step 3: Commit** + +```sh +jj describe -m "feat(grants): add EvmGrantsScreen" +jj new +``` + +--- + +## Task 6: Wire router and dashboard tab + +**Files:** +- Modify: `operator/lib/router.dart` +- Modify: `operator/lib/screens/dashboard.dart` +- Regenerated: `operator/lib/router.gr.dart` + +- [ ] **Step 1: Add route to `router.dart`** + +Replace the contents of `operator/lib/router.dart` with: + +```dart +import 'package:auto_route/auto_route.dart'; + +import 'router.gr.dart'; + +@AutoRouterConfig(generateForDir: ['lib/screens']) +class Router extends RootStackRouter { + @override + List get routes => [ + AutoRoute(page: Bootstrap.page, path: '/bootstrap', initial: true), + AutoRoute(page: ServerInfoSetupRoute.page, path: '/server-info'), + AutoRoute(page: ServerConnectionRoute.page, path: '/server-connection'), + AutoRoute(page: VaultSetupRoute.page, path: '/vault'), + AutoRoute(page: ClientDetailsRoute.page, path: '/clients/:clientId'), + AutoRoute(page: CreateEvmGrantRoute.page, path: '/evm-grants/create'), + + AutoRoute( + page: DashboardRouter.page, + path: '/dashboard', + children: [ + AutoRoute(page: EvmRoute.page, path: 'evm'), + AutoRoute(page: ClientsRoute.page, path: 'clients'), + AutoRoute(page: EvmGrantsRoute.page, path: 'grants'), + AutoRoute(page: AboutRoute.page, path: 'about'), + ], + ), + ]; +} +``` + +- [ ] **Step 2: Update `dashboard.dart`** + +In `operator/lib/screens/dashboard.dart`, replace the `routes` constant: + +```dart +final routes = [ + const EvmRoute(), + const ClientsRoute(), + const EvmGrantsRoute(), + const AboutRoute(), +]; +``` + +And replace the `destinations` list inside `AdaptiveScaffold`: + +```dart +destinations: const [ + NavigationDestination( + icon: Icon(Icons.account_balance_wallet_outlined), + selectedIcon: Icon(Icons.account_balance_wallet), + label: 'Wallets', + ), + NavigationDestination( + icon: Icon(Icons.devices_other_outlined), + selectedIcon: Icon(Icons.devices_other), + label: 'Clients', + ), + NavigationDestination( + icon: Icon(Icons.policy_outlined), + selectedIcon: Icon(Icons.policy), + label: 'Grants', + ), + NavigationDestination( + icon: Icon(Icons.info_outline), + selectedIcon: Icon(Icons.info), + label: 'About', + ), +], +``` + +- [ ] **Step 3: Regenerate router** + +```sh +cd operator && dart run build_runner build --delete-conflicting-outputs +``` + +Expected: `lib/router.gr.dart` updated, `EvmGrantsRoute` now available, no errors. + +- [ ] **Step 4: Full project verify** + +```sh +cd operator && flutter analyze +``` + +Expected: no issues. + +- [ ] **Step 5: Commit** + +```sh +jj describe -m "feat(nav): add Grants dashboard tab" +jj new +``` diff --git a/docs/superpowers/specs/2026-03-28-grant-grid-view-design.md b/docs/superpowers/specs/2026-03-28-grant-grid-view-design.md index 17c116d..335b8f3 100644 --- a/docs/superpowers/specs/2026-03-28-grant-grid-view-design.md +++ b/docs/superpowers/specs/2026-03-28-grant-grid-view-design.md @@ -1,170 +1,170 @@ -# Grant Grid View — Design Spec - -**Date:** 2026-03-28 - -## Overview - -Add a "Grants" dashboard tab to the Flutter operator app that displays all EVM grants as a card-based grid. Each card shows a compact summary (type, chain, wallet address, client name) with a revoke action. The tab integrates into the existing `AdaptiveScaffold` navigation alongside Wallets, Clients, and About. - -## Scope - -- New `walletAccessListProvider` for fetching wallet access entries with their DB row IDs -- New `EvmGrantsScreen` as a dashboard tab -- Grant card widget with enriched display (type, chain, wallet, client) -- Revoke action wired to existing `executeRevokeEvmGrant` mutation -- Dashboard tab bar and router updated -- New token-transfer accent color added to `Palette` - -**Out of scope:** Fixing grant creation (separate task). - ---- - -## Data Layer - -### `walletAccessListProvider` - -**File:** `operator/lib/providers/sdk_clients/wallet_access_list.dart` - -- `@riverpod` class, watches `connectionManagerProvider.future` -- Returns `List?` (null when not connected) -- Each entry: `.id` (wallet_access_id), `.access.walletId`, `.access.sdkClientId` -- Exposes a `refresh()` method following the same pattern as `EvmGrants.refresh()` - -### Enrichment at render time (Approach A) - -The `EvmGrantsScreen` watches four providers: -1. `evmGrantsProvider` — the grant list -2. `walletAccessListProvider` — to resolve wallet_access_id → (wallet_id, sdk_client_id) -3. `evmProvider` — to resolve wallet_id → wallet address -4. `sdkClientsProvider` — to resolve sdk_client_id → client name - -All lookups are in-memory Maps built inside the build method; no extra model class needed. - -Fallbacks: -- Wallet address not found → `"Access #N"` where N is the wallet_access_id -- Client name not found → `"Client #N"` where N is the sdk_client_id - ---- - -## Route Structure - -``` -/dashboard - /evm ← existing (Wallets tab) - /clients ← existing (Clients tab) - /grants ← NEW (Grants tab) - /about ← existing - -/evm-grants/create ← existing push route (unchanged) -``` - -### Changes to `router.dart` - -Add inside dashboard children: -```dart -AutoRoute(page: EvmGrantsRoute.page, path: 'grants'), -``` - -### Changes to `dashboard.dart` - -Add to `routes` list: -```dart -const EvmGrantsRoute() -``` - -Add `NavigationDestination`: -```dart -NavigationDestination( - icon: Icon(Icons.policy_outlined), - selectedIcon: Icon(Icons.policy), - label: 'Grants', -), -``` - ---- - -## Screen: `EvmGrantsScreen` - -**File:** `operator/lib/screens/dashboard/evm/grants/grants.dart` - -``` -Scaffold -└─ SafeArea - └─ RefreshIndicator.adaptive (refreshes evmGrantsProvider + walletAccessListProvider) - └─ ListView (BouncingScrollPhysics + AlwaysScrollableScrollPhysics) - ├─ PageHeader - │ title: 'EVM Grants' - │ isBusy: evmGrantsProvider.isLoading - │ actions: [CreateGrantButton, RefreshButton] - ├─ SizedBox(height: 1.8.h) - └─ -``` - -### State handling - -Matches the pattern from `EvmScreen` and `ClientsScreen`: - -| State | Display | -|---|---| -| Loading (no data yet) | `_StatePanel` with spinner, "Loading grants" | -| Error | `_StatePanel` with coral icon, error message, Retry button | -| No connection | `_StatePanel`, "No active server connection" | -| Empty list | `_StatePanel`, "No grants yet", with Create Grant shortcut | -| Data | Column of `_GrantCard` widgets | - -### Header actions - -**CreateGrantButton:** `FilledButton.icon` with `Icons.add_rounded`, pushes `CreateEvmGrantRoute()` via `context.router.push(...)`. - -**RefreshButton:** `OutlinedButton.icon` with `Icons.refresh`, calls `ref.read(evmGrantsProvider.notifier).refresh()`. - ---- - -## Grant Card: `_GrantCard` - -**Layout:** - -``` -Container (rounded 24, Palette.cream bg, Palette.line border) -└─ IntrinsicHeight > Row - ├─ Accent strip (0.8.w wide, full height, rounded left) - └─ Padding > Column - ├─ Row 1: TypeBadge + ChainChip + Spacer + RevokeButton - └─ Row 2: WalletText + "·" + ClientText -``` - -**Accent color by grant type:** -- Ether transfer → `Palette.coral` -- Token transfer → `Palette.token` (new entry in `Palette` — indigo, e.g. `Color(0xFF5C6BC0)`) - -**TypeBadge:** Small pill container with accent color background at 15% opacity, accent-colored text. Label: `'Ether'` or `'Token'`. - -**ChainChip:** Small container: `'Chain ${grant.shared.chainId}'`, muted ink color. - -**WalletText:** Short hex address (`0xabc...def`) from wallet lookup, `bodySmall`, monospace font family. - -**ClientText:** Client name from `sdkClientsProvider` lookup, or fallback string. `bodySmall`, muted ink. - -**RevokeButton:** -- `OutlinedButton` with `Icons.block_rounded` icon, label `'Revoke'` -- `foregroundColor: Palette.coral`, `side: BorderSide(color: Palette.coral.withValues(alpha: 0.4))` -- Disabled (replaced with `CircularProgressIndicator`) while `revokeEvmGrantMutation` is pending — note: this is a single global mutation, so all revoke buttons disable while any revoke is in flight -- On press: calls `executeRevokeEvmGrant(ref, grantId: grant.id)`; shows `SnackBar` on error - ---- - -## Adaptive Sizing - -All sizing uses `sizer` units (`1.h`, `1.w`, etc.). No hardcoded pixel values. - ---- - -## Files to Create / Modify - -| File | Action | -|---|---| -| `lib/theme/palette.dart` | Modify — add `Palette.token` color | -| `lib/providers/sdk_clients/wallet_access_list.dart` | Create | -| `lib/screens/dashboard/evm/grants/grants.dart` | Create | -| `lib/router.dart` | Modify — add grants route to dashboard children | -| `lib/screens/dashboard.dart` | Modify — add tab to routes list and NavigationDestinations | +# Grant Grid View — Design Spec + +**Date:** 2026-03-28 + +## Overview + +Add a "Grants" dashboard tab to the Flutter operator app that displays all EVM grants as a card-based grid. Each card shows a compact summary (type, chain, wallet address, client name) with a revoke action. The tab integrates into the existing `AdaptiveScaffold` navigation alongside Wallets, Clients, and About. + +## Scope + +- New `walletAccessListProvider` for fetching wallet access entries with their DB row IDs +- New `EvmGrantsScreen` as a dashboard tab +- Grant card widget with enriched display (type, chain, wallet, client) +- Revoke action wired to existing `executeRevokeEvmGrant` mutation +- Dashboard tab bar and router updated +- New token-transfer accent color added to `Palette` + +**Out of scope:** Fixing grant creation (separate task). + +--- + +## Data Layer + +### `walletAccessListProvider` + +**File:** `operator/lib/providers/sdk_clients/wallet_access_list.dart` + +- `@riverpod` class, watches `connectionManagerProvider.future` +- Returns `List?` (null when not connected) +- Each entry: `.id` (wallet_access_id), `.access.walletId`, `.access.sdkClientId` +- Exposes a `refresh()` method following the same pattern as `EvmGrants.refresh()` + +### Enrichment at render time (Approach A) + +The `EvmGrantsScreen` watches four providers: +1. `evmGrantsProvider` — the grant list +2. `walletAccessListProvider` — to resolve wallet_access_id → (wallet_id, sdk_client_id) +3. `evmProvider` — to resolve wallet_id → wallet address +4. `sdkClientsProvider` — to resolve sdk_client_id → client name + +All lookups are in-memory Maps built inside the build method; no extra model class needed. + +Fallbacks: +- Wallet address not found → `"Access #N"` where N is the wallet_access_id +- Client name not found → `"Client #N"` where N is the sdk_client_id + +--- + +## Route Structure + +``` +/dashboard + /evm ← existing (Wallets tab) + /clients ← existing (Clients tab) + /grants ← NEW (Grants tab) + /about ← existing + +/evm-grants/create ← existing push route (unchanged) +``` + +### Changes to `router.dart` + +Add inside dashboard children: +```dart +AutoRoute(page: EvmGrantsRoute.page, path: 'grants'), +``` + +### Changes to `dashboard.dart` + +Add to `routes` list: +```dart +const EvmGrantsRoute() +``` + +Add `NavigationDestination`: +```dart +NavigationDestination( + icon: Icon(Icons.policy_outlined), + selectedIcon: Icon(Icons.policy), + label: 'Grants', +), +``` + +--- + +## Screen: `EvmGrantsScreen` + +**File:** `operator/lib/screens/dashboard/evm/grants/grants.dart` + +``` +Scaffold +└─ SafeArea + └─ RefreshIndicator.adaptive (refreshes evmGrantsProvider + walletAccessListProvider) + └─ ListView (BouncingScrollPhysics + AlwaysScrollableScrollPhysics) + ├─ PageHeader + │ title: 'EVM Grants' + │ isBusy: evmGrantsProvider.isLoading + │ actions: [CreateGrantButton, RefreshButton] + ├─ SizedBox(height: 1.8.h) + └─ +``` + +### State handling + +Matches the pattern from `EvmScreen` and `ClientsScreen`: + +| State | Display | +|---|---| +| Loading (no data yet) | `_StatePanel` with spinner, "Loading grants" | +| Error | `_StatePanel` with coral icon, error message, Retry button | +| No connection | `_StatePanel`, "No active server connection" | +| Empty list | `_StatePanel`, "No grants yet", with Create Grant shortcut | +| Data | Column of `_GrantCard` widgets | + +### Header actions + +**CreateGrantButton:** `FilledButton.icon` with `Icons.add_rounded`, pushes `CreateEvmGrantRoute()` via `context.router.push(...)`. + +**RefreshButton:** `OutlinedButton.icon` with `Icons.refresh`, calls `ref.read(evmGrantsProvider.notifier).refresh()`. + +--- + +## Grant Card: `_GrantCard` + +**Layout:** + +``` +Container (rounded 24, Palette.cream bg, Palette.line border) +└─ IntrinsicHeight > Row + ├─ Accent strip (0.8.w wide, full height, rounded left) + └─ Padding > Column + ├─ Row 1: TypeBadge + ChainChip + Spacer + RevokeButton + └─ Row 2: WalletText + "·" + ClientText +``` + +**Accent color by grant type:** +- Ether transfer → `Palette.coral` +- Token transfer → `Palette.token` (new entry in `Palette` — indigo, e.g. `Color(0xFF5C6BC0)`) + +**TypeBadge:** Small pill container with accent color background at 15% opacity, accent-colored text. Label: `'Ether'` or `'Token'`. + +**ChainChip:** Small container: `'Chain ${grant.shared.chainId}'`, muted ink color. + +**WalletText:** Short hex address (`0xabc...def`) from wallet lookup, `bodySmall`, monospace font family. + +**ClientText:** Client name from `sdkClientsProvider` lookup, or fallback string. `bodySmall`, muted ink. + +**RevokeButton:** +- `OutlinedButton` with `Icons.block_rounded` icon, label `'Revoke'` +- `foregroundColor: Palette.coral`, `side: BorderSide(color: Palette.coral.withValues(alpha: 0.4))` +- Disabled (replaced with `CircularProgressIndicator`) while `revokeEvmGrantMutation` is pending — note: this is a single global mutation, so all revoke buttons disable while any revoke is in flight +- On press: calls `executeRevokeEvmGrant(ref, grantId: grant.id)`; shows `SnackBar` on error + +--- + +## Adaptive Sizing + +All sizing uses `sizer` units (`1.h`, `1.w`, etc.). No hardcoded pixel values. + +--- + +## Files to Create / Modify + +| File | Action | +|---|---| +| `lib/theme/palette.dart` | Modify — add `Palette.token` color | +| `lib/providers/sdk_clients/wallet_access_list.dart` | Create | +| `lib/screens/dashboard/evm/grants/grants.dart` | Create | +| `lib/router.dart` | Modify — add grants route to dashboard children | +| `lib/screens/dashboard.dart` | Modify — add tab to routes list and NavigationDestinations | diff --git a/mise.toml b/mise.toml index f0da5e6..723df87 100644 --- a/mise.toml +++ b/mise.toml @@ -1,24 +1,24 @@ -[tools] -"cargo:diesel_cli" = { version = "2.3.7", features = "sqlite,sqlite-bundled", default-features = "false" } -"cargo:cargo-audit" = "0.22.1" -"cargo:cargo-vet" = "0.10.2" -flutter = "3.41.7-stable" -protoc = "29.6" -rust = { version = "1.95.0", components = "clippy,rust-analyzer" } -"cargo:cargo-features-manager" = "0.12.0" -"cargo:cargo-nextest" = "0.9.133" -"cargo:cargo-shear" = "latest" -"cargo:cargo-insta" = "1.47.2" -python = "3.14.4" -ast-grep = "0.42.1" -"cargo:cargo-edit" = "0.13.10" -"cargo:cargo-mutants" = "27.0.0" -"cargo:flutter_rust_bridge_codegen" = "2.12.0" - -[tasks.codegen] -sources = ['protobufs/*.proto', 'protobufs/**/*.proto'] -outputs = ['useragent/lib/proto/**'] -run = ''' -dart pub global activate protoc_plugin && \ -protoc --dart_out=grpc:useragent/lib/proto --proto_path=protobufs/ $(find protobufs -name '*.proto' | sort) -''' +[tools] +"cargo:diesel_cli" = { version = "2.3.7", features = "sqlite,sqlite-bundled", default-features = "false" } +"cargo:cargo-audit" = "0.22.1" +"cargo:cargo-vet" = "0.10.2" +flutter = "3.41.7-stable" +protoc = "29.6" +rust = { version = "1.95.0", components = "clippy,rust-analyzer" } +"cargo:cargo-features-manager" = "0.12.0" +"cargo:cargo-nextest" = "0.9.133" +"cargo:cargo-shear" = "latest" +"cargo:cargo-insta" = "1.47.2" +python = "3.14.4" +ast-grep = "0.42.1" +"cargo:cargo-edit" = "0.13.10" +"cargo:cargo-mutants" = "27.0.0" +"cargo:flutter_rust_bridge_codegen" = "2.12.0" + +[tasks.codegen] +sources = ['protobufs/*.proto', 'protobufs/**/*.proto'] +outputs = ['useragent/lib/proto/**'] +run = ''' +dart pub global activate protoc_plugin && \ +protoc --dart_out=grpc:useragent/lib/proto --proto_path=protobufs/ $(find protobufs -name '*.proto' | sort) +''' diff --git a/protobufs/arbiter.proto b/protobufs/arbiter.proto index ba24941..4d5446a 100644 --- a/protobufs/arbiter.proto +++ b/protobufs/arbiter.proto @@ -1,16 +1,16 @@ -syntax = "proto3"; - -package arbiter; - -import "client.proto"; -import "operator.proto"; - -message ServerInfo { - string version = 1; - bytes cert_public_key = 2; -} - -service ArbiterService { - rpc Client(stream arbiter.client.ClientRequest) returns (stream arbiter.client.ClientResponse); - rpc Operator(stream arbiter.operator.OperatorRequest) returns (stream arbiter.operator.OperatorResponse); -} +syntax = "proto3"; + +package arbiter; + +import "client.proto"; +import "operator.proto"; + +message ServerInfo { + string version = 1; + bytes cert_public_key = 2; +} + +service ArbiterService { + rpc Client(stream arbiter.client.ClientRequest) returns (stream arbiter.client.ClientResponse); + rpc Operator(stream arbiter.operator.OperatorRequest) returns (stream arbiter.operator.OperatorResponse); +} diff --git a/protobufs/client.proto b/protobufs/client.proto index e1b346c..64b1f37 100644 --- a/protobufs/client.proto +++ b/protobufs/client.proto @@ -1,25 +1,25 @@ -syntax = "proto3"; - -package arbiter.client; - -import "client/auth.proto"; -import "client/evm.proto"; -import "client/vault.proto"; - -message ClientRequest { - int32 request_id = 4; - oneof payload { - auth.Request auth = 1; - vault.Request vault = 2; - evm.Request evm = 3; - } -} - -message ClientResponse { - optional int32 request_id = 7; - oneof payload { - auth.Response auth = 1; - vault.Response vault = 2; - evm.Response evm = 3; - } -} +syntax = "proto3"; + +package arbiter.client; + +import "client/auth.proto"; +import "client/evm.proto"; +import "client/vault.proto"; + +message ClientRequest { + int32 request_id = 4; + oneof payload { + auth.Request auth = 1; + vault.Request vault = 2; + evm.Request evm = 3; + } +} + +message ClientResponse { + optional int32 request_id = 7; + oneof payload { + auth.Response auth = 1; + vault.Response vault = 2; + evm.Response evm = 3; + } +} diff --git a/protobufs/client/auth.proto b/protobufs/client/auth.proto index 3a081d2..974e033 100644 --- a/protobufs/client/auth.proto +++ b/protobufs/client/auth.proto @@ -1,43 +1,43 @@ -syntax = "proto3"; - -package arbiter.client.auth; - -import "shared/client.proto"; - -message AuthChallengeRequest { - bytes pubkey = 1; - arbiter.shared.ClientInfo client_info = 2; -} - -message AuthChallenge { - uint64 timestamp_nanos = 1; - bytes random = 2; -} - -message AuthChallengeSolution { - bytes signature = 1; -} - -enum AuthResult { - AUTH_RESULT_UNSPECIFIED = 0; - AUTH_RESULT_SUCCESS = 1; - AUTH_RESULT_INVALID_KEY = 2; - AUTH_RESULT_INVALID_SIGNATURE = 3; - AUTH_RESULT_APPROVAL_DENIED = 4; - AUTH_RESULT_NO_OPERATORS_ONLINE = 5; - AUTH_RESULT_INTERNAL = 6; -} - -message Request { - oneof payload { - AuthChallengeRequest challenge_request = 1; - AuthChallengeSolution challenge_solution = 2; - } -} - -message Response { - oneof payload { - AuthChallenge challenge = 1; - AuthResult result = 2; - } -} +syntax = "proto3"; + +package arbiter.client.auth; + +import "shared/client.proto"; + +message AuthChallengeRequest { + bytes pubkey = 1; + arbiter.shared.ClientInfo client_info = 2; +} + +message AuthChallenge { + uint64 timestamp_nanos = 1; + bytes random = 2; +} + +message AuthChallengeSolution { + bytes signature = 1; +} + +enum AuthResult { + AUTH_RESULT_UNSPECIFIED = 0; + AUTH_RESULT_SUCCESS = 1; + AUTH_RESULT_INVALID_KEY = 2; + AUTH_RESULT_INVALID_SIGNATURE = 3; + AUTH_RESULT_APPROVAL_DENIED = 4; + AUTH_RESULT_NO_OPERATORS_ONLINE = 5; + AUTH_RESULT_INTERNAL = 6; +} + +message Request { + oneof payload { + AuthChallengeRequest challenge_request = 1; + AuthChallengeSolution challenge_solution = 2; + } +} + +message Response { + oneof payload { + AuthChallenge challenge = 1; + AuthResult result = 2; + } +} diff --git a/protobufs/client/evm.proto b/protobufs/client/evm.proto index ded097a..d9613af 100644 --- a/protobufs/client/evm.proto +++ b/protobufs/client/evm.proto @@ -1,19 +1,19 @@ -syntax = "proto3"; - -package arbiter.client.evm; - -import "evm.proto"; - -message Request { - oneof payload { - arbiter.evm.EvmSignTransactionRequest sign_transaction = 1; - arbiter.evm.EvmAnalyzeTransactionRequest analyze_transaction = 2; - } -} - -message Response { - oneof payload { - arbiter.evm.EvmSignTransactionResponse sign_transaction = 1; - arbiter.evm.EvmAnalyzeTransactionResponse analyze_transaction = 2; - } -} +syntax = "proto3"; + +package arbiter.client.evm; + +import "evm.proto"; + +message Request { + oneof payload { + arbiter.evm.EvmSignTransactionRequest sign_transaction = 1; + arbiter.evm.EvmAnalyzeTransactionRequest analyze_transaction = 2; + } +} + +message Response { + oneof payload { + arbiter.evm.EvmSignTransactionResponse sign_transaction = 1; + arbiter.evm.EvmAnalyzeTransactionResponse analyze_transaction = 2; + } +} diff --git a/protobufs/client/vault.proto b/protobufs/client/vault.proto index d9165b1..0f841d8 100644 --- a/protobufs/client/vault.proto +++ b/protobufs/client/vault.proto @@ -1,18 +1,18 @@ -syntax = "proto3"; - -package arbiter.client.vault; - -import "google/protobuf/empty.proto"; -import "shared/vault.proto"; - -message Request { - oneof payload { - google.protobuf.Empty query_state = 1; - } -} - -message Response { - oneof payload { - arbiter.shared.VaultState state = 1; - } -} +syntax = "proto3"; + +package arbiter.client.vault; + +import "google/protobuf/empty.proto"; +import "shared/vault.proto"; + +message Request { + oneof payload { + google.protobuf.Empty query_state = 1; + } +} + +message Response { + oneof payload { + arbiter.shared.VaultState state = 1; + } +} diff --git a/protobufs/evm.proto b/protobufs/evm.proto index 316217d..95cb182 100644 --- a/protobufs/evm.proto +++ b/protobufs/evm.proto @@ -1,153 +1,153 @@ -syntax = "proto3"; - -package arbiter.evm; - -import "google/protobuf/empty.proto"; -import "google/protobuf/timestamp.proto"; -import "shared/evm.proto"; - -enum EvmError { - EVM_ERROR_UNSPECIFIED = 0; - EVM_ERROR_VAULT_SEALED = 1; - EVM_ERROR_INTERNAL = 2; -} - -message WalletEntry { - int32 id = 1; - bytes address = 2; // 20-byte Ethereum address -} - -message WalletList { - repeated WalletEntry wallets = 1; -} - -message WalletCreateResponse { - oneof result { - WalletEntry wallet = 1; - EvmError error = 2; - } -} - -message WalletListResponse { - oneof result { - WalletList wallets = 1; - EvmError error = 2; - } -} - -// --- Grant types --- - -message TransactionRateLimit { - uint32 count = 1; - int64 window_secs = 2; -} - -message VolumeRateLimit { - bytes max_volume = 1; // U256 as big-endian bytes - int64 window_secs = 2; -} - -message SharedSettings { - int32 wallet_access_id = 1; - uint64 chain_id = 2; - optional google.protobuf.Timestamp valid_from = 3; - optional google.protobuf.Timestamp valid_until = 4; - optional bytes max_gas_fee_per_gas = 5; // U256 as big-endian bytes - optional bytes max_priority_fee_per_gas = 6; // U256 as big-endian bytes - optional TransactionRateLimit rate_limit = 7; -} - -message EtherTransferSettings { - repeated bytes targets = 1; // list of 20-byte Ethereum addresses - VolumeRateLimit limit = 2; -} - -message TokenTransferSettings { - bytes token_contract = 1; // 20-byte Ethereum address - optional bytes target = 2; // 20-byte Ethereum address; absent means any recipient allowed - repeated VolumeRateLimit volume_limits = 3; -} - -message SpecificGrant { - oneof grant { - EtherTransferSettings ether_transfer = 1; - TokenTransferSettings token_transfer = 2; - } -} - -// --- Operator grant management --- -message EvmGrantCreateRequest { - SharedSettings shared = 1; - SpecificGrant specific = 2; -} - -message EvmGrantCreateResponse { - oneof result { - int32 grant_id = 1; - EvmError error = 2; - } -} - -message EvmGrantDeleteRequest { - int32 grant_id = 1; -} - -message EvmGrantDeleteResponse { - oneof result { - google.protobuf.Empty ok = 1; - EvmError error = 2; - } -} - -// Basic grant info returned in grant listings -message GrantEntry { - int32 id = 1; - int32 wallet_access_id = 2; - SharedSettings shared = 3; - SpecificGrant specific = 4; -} - -message EvmGrantListRequest { - optional int32 wallet_access_id = 1; -} - -message EvmGrantListResponse { - oneof result { - EvmGrantList grants = 1; - EvmError error = 2; - } -} - -message EvmGrantList { - repeated GrantEntry grants = 1; -} - -// --- Client transaction operations --- - -message EvmSignTransactionRequest { - bytes wallet_address = 1; // 20-byte Ethereum address - bytes rlp_transaction = 2; // RLP-encoded EIP-1559 transaction (unsigned) -} - -// oneof because signing and evaluation happen atomically — a signing failure -// is always either an eval error or an internal error, never a partial success -message EvmSignTransactionResponse { - oneof result { - bytes signature = 1; // 65-byte signature: r[32] || s[32] || v[1] - arbiter.shared.evm.TransactionEvalError eval_error = 2; - EvmError error = 3; - } -} - -message EvmAnalyzeTransactionRequest { - bytes wallet_address = 1; // 20-byte Ethereum address - bytes rlp_transaction = 2; // RLP-encoded EIP-1559 transaction -} - -message EvmAnalyzeTransactionResponse { - oneof result { - arbiter.shared.evm.SpecificMeaning meaning = 1; - arbiter.shared.evm.TransactionEvalError eval_error = 2; - EvmError error = 3; - } -} +syntax = "proto3"; + +package arbiter.evm; + +import "google/protobuf/empty.proto"; +import "google/protobuf/timestamp.proto"; +import "shared/evm.proto"; + +enum EvmError { + EVM_ERROR_UNSPECIFIED = 0; + EVM_ERROR_VAULT_SEALED = 1; + EVM_ERROR_INTERNAL = 2; +} + +message WalletEntry { + int32 id = 1; + bytes address = 2; // 20-byte Ethereum address +} + +message WalletList { + repeated WalletEntry wallets = 1; +} + +message WalletCreateResponse { + oneof result { + WalletEntry wallet = 1; + EvmError error = 2; + } +} + +message WalletListResponse { + oneof result { + WalletList wallets = 1; + EvmError error = 2; + } +} + +// --- Grant types --- + +message TransactionRateLimit { + uint32 count = 1; + int64 window_secs = 2; +} + +message VolumeRateLimit { + bytes max_volume = 1; // U256 as big-endian bytes + int64 window_secs = 2; +} + +message SharedSettings { + int32 wallet_access_id = 1; + uint64 chain_id = 2; + optional google.protobuf.Timestamp valid_from = 3; + optional google.protobuf.Timestamp valid_until = 4; + optional bytes max_gas_fee_per_gas = 5; // U256 as big-endian bytes + optional bytes max_priority_fee_per_gas = 6; // U256 as big-endian bytes + optional TransactionRateLimit rate_limit = 7; +} + +message EtherTransferSettings { + repeated bytes targets = 1; // list of 20-byte Ethereum addresses + VolumeRateLimit limit = 2; +} + +message TokenTransferSettings { + bytes token_contract = 1; // 20-byte Ethereum address + optional bytes target = 2; // 20-byte Ethereum address; absent means any recipient allowed + repeated VolumeRateLimit volume_limits = 3; +} + +message SpecificGrant { + oneof grant { + EtherTransferSettings ether_transfer = 1; + TokenTransferSettings token_transfer = 2; + } +} + +// --- Operator grant management --- +message EvmGrantCreateRequest { + SharedSettings shared = 1; + SpecificGrant specific = 2; +} + +message EvmGrantCreateResponse { + oneof result { + int32 grant_id = 1; + EvmError error = 2; + } +} + +message EvmGrantDeleteRequest { + int32 grant_id = 1; +} + +message EvmGrantDeleteResponse { + oneof result { + google.protobuf.Empty ok = 1; + EvmError error = 2; + } +} + +// Basic grant info returned in grant listings +message GrantEntry { + int32 id = 1; + int32 wallet_access_id = 2; + SharedSettings shared = 3; + SpecificGrant specific = 4; +} + +message EvmGrantListRequest { + optional int32 wallet_access_id = 1; +} + +message EvmGrantListResponse { + oneof result { + EvmGrantList grants = 1; + EvmError error = 2; + } +} + +message EvmGrantList { + repeated GrantEntry grants = 1; +} + +// --- Client transaction operations --- + +message EvmSignTransactionRequest { + bytes wallet_address = 1; // 20-byte Ethereum address + bytes rlp_transaction = 2; // RLP-encoded EIP-1559 transaction (unsigned) +} + +// oneof because signing and evaluation happen atomically — a signing failure +// is always either an eval error or an internal error, never a partial success +message EvmSignTransactionResponse { + oneof result { + bytes signature = 1; // 65-byte signature: r[32] || s[32] || v[1] + arbiter.shared.evm.TransactionEvalError eval_error = 2; + EvmError error = 3; + } +} + +message EvmAnalyzeTransactionRequest { + bytes wallet_address = 1; // 20-byte Ethereum address + bytes rlp_transaction = 2; // RLP-encoded EIP-1559 transaction +} + +message EvmAnalyzeTransactionResponse { + oneof result { + arbiter.shared.evm.SpecificMeaning meaning = 1; + arbiter.shared.evm.TransactionEvalError eval_error = 2; + EvmError error = 3; + } +} diff --git a/protobufs/operator.proto b/protobufs/operator.proto index f780ae3..b911fae 100644 --- a/protobufs/operator.proto +++ b/protobufs/operator.proto @@ -1,28 +1,28 @@ -syntax = "proto3"; - -package arbiter.operator; - -import "operator/auth.proto"; -import "operator/evm.proto"; -import "operator/sdk_client.proto"; -import "operator/vault/vault.proto"; - -message OperatorRequest { - int32 id = 16; - oneof payload { - auth.Request auth = 1; - vault.Request vault = 2; - evm.Request evm = 3; - sdk_client.Request sdk_client = 4; - } -} - -message OperatorResponse { - optional int32 id = 16; - oneof payload { - auth.Response auth = 1; - vault.Response vault = 2; - evm.Response evm = 3; - sdk_client.Response sdk_client = 4; - } -} +syntax = "proto3"; + +package arbiter.operator; + +import "operator/auth.proto"; +import "operator/evm.proto"; +import "operator/sdk_client.proto"; +import "operator/vault/vault.proto"; + +message OperatorRequest { + int32 id = 16; + oneof payload { + auth.Request auth = 1; + vault.Request vault = 2; + evm.Request evm = 3; + sdk_client.Request sdk_client = 4; + } +} + +message OperatorResponse { + optional int32 id = 16; + oneof payload { + auth.Response auth = 1; + vault.Response vault = 2; + evm.Response evm = 3; + sdk_client.Response sdk_client = 4; + } +} diff --git a/protobufs/operator/auth.proto b/protobufs/operator/auth.proto index 61a8085..0f34f6a 100644 --- a/protobufs/operator/auth.proto +++ b/protobufs/operator/auth.proto @@ -1,41 +1,41 @@ -syntax = "proto3"; - -package arbiter.operator.auth; - -message AuthChallengeRequest { - bytes pubkey = 1; - optional string bootstrap_token = 2; -} - -message AuthChallenge { - uint64 timestamp_nanos = 1; - bytes random = 2; -} - -message AuthChallengeSolution { - bytes signature = 1; -} - -enum AuthResult { - AUTH_RESULT_UNSPECIFIED = 0; - AUTH_RESULT_SUCCESS = 1; - AUTH_RESULT_INVALID_KEY = 2; - AUTH_RESULT_INVALID_SIGNATURE = 3; - AUTH_RESULT_BOOTSTRAP_REQUIRED = 4; - AUTH_RESULT_TOKEN_INVALID = 5; - AUTH_RESULT_INTERNAL = 6; -} - -message Request { - oneof payload { - AuthChallengeRequest challenge_request = 1; - AuthChallengeSolution challenge_solution = 2; - } -} - -message Response { - oneof payload { - AuthChallenge challenge = 1; - AuthResult result = 2; - } -} +syntax = "proto3"; + +package arbiter.operator.auth; + +message AuthChallengeRequest { + bytes pubkey = 1; + optional string bootstrap_token = 2; +} + +message AuthChallenge { + uint64 timestamp_nanos = 1; + bytes random = 2; +} + +message AuthChallengeSolution { + bytes signature = 1; +} + +enum AuthResult { + AUTH_RESULT_UNSPECIFIED = 0; + AUTH_RESULT_SUCCESS = 1; + AUTH_RESULT_INVALID_KEY = 2; + AUTH_RESULT_INVALID_SIGNATURE = 3; + AUTH_RESULT_BOOTSTRAP_REQUIRED = 4; + AUTH_RESULT_TOKEN_INVALID = 5; + AUTH_RESULT_INTERNAL = 6; +} + +message Request { + oneof payload { + AuthChallengeRequest challenge_request = 1; + AuthChallengeSolution challenge_solution = 2; + } +} + +message Response { + oneof payload { + AuthChallenge challenge = 1; + AuthResult result = 2; + } +} diff --git a/protobufs/operator/evm.proto b/protobufs/operator/evm.proto index b92c119..3afc12e 100644 --- a/protobufs/operator/evm.proto +++ b/protobufs/operator/evm.proto @@ -1,33 +1,33 @@ -syntax = "proto3"; - -package arbiter.operator.evm; - -import "evm.proto"; -import "google/protobuf/empty.proto"; - -message SignTransactionRequest { - int32 client_id = 1; - arbiter.evm.EvmSignTransactionRequest request = 2; -} - -message Request { - oneof payload { - google.protobuf.Empty wallet_create = 1; - google.protobuf.Empty wallet_list = 2; - arbiter.evm.EvmGrantCreateRequest grant_create = 3; - arbiter.evm.EvmGrantDeleteRequest grant_delete = 4; - arbiter.evm.EvmGrantListRequest grant_list = 5; - SignTransactionRequest sign_transaction = 6; - } -} - -message Response { - oneof payload { - arbiter.evm.WalletCreateResponse wallet_create = 1; - arbiter.evm.WalletListResponse wallet_list = 2; - arbiter.evm.EvmGrantCreateResponse grant_create = 3; - arbiter.evm.EvmGrantDeleteResponse grant_delete = 4; - arbiter.evm.EvmGrantListResponse grant_list = 5; - arbiter.evm.EvmSignTransactionResponse sign_transaction = 6; - } -} +syntax = "proto3"; + +package arbiter.operator.evm; + +import "evm.proto"; +import "google/protobuf/empty.proto"; + +message SignTransactionRequest { + int32 client_id = 1; + arbiter.evm.EvmSignTransactionRequest request = 2; +} + +message Request { + oneof payload { + google.protobuf.Empty wallet_create = 1; + google.protobuf.Empty wallet_list = 2; + arbiter.evm.EvmGrantCreateRequest grant_create = 3; + arbiter.evm.EvmGrantDeleteRequest grant_delete = 4; + arbiter.evm.EvmGrantListRequest grant_list = 5; + SignTransactionRequest sign_transaction = 6; + } +} + +message Response { + oneof payload { + arbiter.evm.WalletCreateResponse wallet_create = 1; + arbiter.evm.WalletListResponse wallet_list = 2; + arbiter.evm.EvmGrantCreateResponse grant_create = 3; + arbiter.evm.EvmGrantDeleteResponse grant_delete = 4; + arbiter.evm.EvmGrantListResponse grant_list = 5; + arbiter.evm.EvmSignTransactionResponse sign_transaction = 6; + } +} diff --git a/protobufs/operator/sdk_client.proto b/protobufs/operator/sdk_client.proto index f59721f..f7b68d6 100644 --- a/protobufs/operator/sdk_client.proto +++ b/protobufs/operator/sdk_client.proto @@ -1,100 +1,100 @@ -syntax = "proto3"; - -package arbiter.operator.sdk_client; - -import "shared/client.proto"; -import "google/protobuf/empty.proto"; - -enum Error { - ERROR_UNSPECIFIED = 0; - ERROR_ALREADY_EXISTS = 1; - ERROR_NOT_FOUND = 2; - ERROR_HAS_RELATED_DATA = 3; // hard-delete blocked by FK (client has grants or transaction logs) - ERROR_INTERNAL = 4; -} - -message RevokeRequest { - int32 client_id = 1; -} - -message Entry { - int32 id = 1; - bytes pubkey = 2; - arbiter.shared.ClientInfo info = 3; - int32 created_at = 4; -} - -message List { - repeated Entry clients = 1; -} - -message RevokeResponse { - oneof result { - google.protobuf.Empty ok = 1; - Error error = 2; - } -} - -message ListResponse { - oneof result { - List clients = 1; - Error error = 2; - } -} - -message ConnectionRequest { - bytes pubkey = 1; - arbiter.shared.ClientInfo info = 2; -} - -message ConnectionResponse { - bool approved = 1; - bytes pubkey = 2; -} - -message ConnectionCancel { - bytes pubkey = 1; -} - -message WalletAccess { - int32 wallet_id = 1; - int32 sdk_client_id = 2; -} - -message WalletAccessEntry { - int32 id = 1; - WalletAccess access = 2; -} - -message GrantWalletAccess { - repeated WalletAccess accesses = 1; -} - -message RevokeWalletAccess { - repeated int32 accesses = 1; -} - -message ListWalletAccessResponse { - repeated WalletAccessEntry accesses = 1; -} - -message Request { - oneof payload { - ConnectionResponse connection_response = 1; - RevokeRequest revoke = 2; - google.protobuf.Empty list = 3; - GrantWalletAccess grant_wallet_access = 4; - RevokeWalletAccess revoke_wallet_access = 5; - google.protobuf.Empty list_wallet_access = 6; - } -} - -message Response { - oneof payload { - ConnectionRequest connection_request = 1; - ConnectionCancel connection_cancel = 2; - RevokeResponse revoke = 3; - ListResponse list = 4; - ListWalletAccessResponse list_wallet_access = 5; - } -} +syntax = "proto3"; + +package arbiter.operator.sdk_client; + +import "shared/client.proto"; +import "google/protobuf/empty.proto"; + +enum Error { + ERROR_UNSPECIFIED = 0; + ERROR_ALREADY_EXISTS = 1; + ERROR_NOT_FOUND = 2; + ERROR_HAS_RELATED_DATA = 3; // hard-delete blocked by FK (client has grants or transaction logs) + ERROR_INTERNAL = 4; +} + +message RevokeRequest { + int32 client_id = 1; +} + +message Entry { + int32 id = 1; + bytes pubkey = 2; + arbiter.shared.ClientInfo info = 3; + int32 created_at = 4; +} + +message List { + repeated Entry clients = 1; +} + +message RevokeResponse { + oneof result { + google.protobuf.Empty ok = 1; + Error error = 2; + } +} + +message ListResponse { + oneof result { + List clients = 1; + Error error = 2; + } +} + +message ConnectionRequest { + bytes pubkey = 1; + arbiter.shared.ClientInfo info = 2; +} + +message ConnectionResponse { + bool approved = 1; + bytes pubkey = 2; +} + +message ConnectionCancel { + bytes pubkey = 1; +} + +message WalletAccess { + int32 wallet_id = 1; + int32 sdk_client_id = 2; +} + +message WalletAccessEntry { + int32 id = 1; + WalletAccess access = 2; +} + +message GrantWalletAccess { + repeated WalletAccess accesses = 1; +} + +message RevokeWalletAccess { + repeated int32 accesses = 1; +} + +message ListWalletAccessResponse { + repeated WalletAccessEntry accesses = 1; +} + +message Request { + oneof payload { + ConnectionResponse connection_response = 1; + RevokeRequest revoke = 2; + google.protobuf.Empty list = 3; + GrantWalletAccess grant_wallet_access = 4; + RevokeWalletAccess revoke_wallet_access = 5; + google.protobuf.Empty list_wallet_access = 6; + } +} + +message Response { + oneof payload { + ConnectionRequest connection_request = 1; + ConnectionCancel connection_cancel = 2; + RevokeResponse revoke = 3; + ListResponse list = 4; + ListWalletAccessResponse list_wallet_access = 5; + } +} diff --git a/protobufs/operator/vault/bootstrap.proto b/protobufs/operator/vault/bootstrap.proto index 97e376d..5689a64 100644 --- a/protobufs/operator/vault/bootstrap.proto +++ b/protobufs/operator/vault/bootstrap.proto @@ -1,24 +1,24 @@ -syntax = "proto3"; - -package arbiter.operator.vault.bootstrap; - -message BootstrapEncryptedKey { - bytes nonce = 1; - bytes ciphertext = 2; - bytes associated_data = 3; -} - -enum BootstrapResult { - BOOTSTRAP_RESULT_UNSPECIFIED = 0; - BOOTSTRAP_RESULT_SUCCESS = 1; - BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED = 2; - BOOTSTRAP_RESULT_INVALID_KEY = 3; -} - -message Request { - BootstrapEncryptedKey encrypted_key = 2; -} - -message Response { - BootstrapResult result = 1; -} +syntax = "proto3"; + +package arbiter.operator.vault.bootstrap; + +message BootstrapEncryptedKey { + bytes nonce = 1; + bytes ciphertext = 2; + bytes associated_data = 3; +} + +enum BootstrapResult { + BOOTSTRAP_RESULT_UNSPECIFIED = 0; + BOOTSTRAP_RESULT_SUCCESS = 1; + BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED = 2; + BOOTSTRAP_RESULT_INVALID_KEY = 3; +} + +message Request { + BootstrapEncryptedKey encrypted_key = 2; +} + +message Response { + BootstrapResult result = 1; +} diff --git a/protobufs/operator/vault/unseal.proto b/protobufs/operator/vault/unseal.proto index 9378d5d..1164f77 100644 --- a/protobufs/operator/vault/unseal.proto +++ b/protobufs/operator/vault/unseal.proto @@ -1,37 +1,37 @@ -syntax = "proto3"; - -package arbiter.operator.vault.unseal; - -message UnsealStart { - bytes client_pubkey = 1; -} - -message UnsealStartResponse { - bytes server_pubkey = 1; -} -message UnsealEncryptedKey { - bytes nonce = 1; - bytes ciphertext = 2; - bytes associated_data = 3; -} - -enum UnsealResult { - UNSEAL_RESULT_UNSPECIFIED = 0; - UNSEAL_RESULT_SUCCESS = 1; - UNSEAL_RESULT_INVALID_KEY = 2; - UNSEAL_RESULT_UNBOOTSTRAPPED = 3; -} - -message Request { - oneof payload { - UnsealStart start = 1; - UnsealEncryptedKey encrypted_key = 2; - } -} - -message Response { - oneof payload { - UnsealStartResponse start = 1; - UnsealResult result = 2; - } -} +syntax = "proto3"; + +package arbiter.operator.vault.unseal; + +message UnsealStart { + bytes client_pubkey = 1; +} + +message UnsealStartResponse { + bytes server_pubkey = 1; +} +message UnsealEncryptedKey { + bytes nonce = 1; + bytes ciphertext = 2; + bytes associated_data = 3; +} + +enum UnsealResult { + UNSEAL_RESULT_UNSPECIFIED = 0; + UNSEAL_RESULT_SUCCESS = 1; + UNSEAL_RESULT_INVALID_KEY = 2; + UNSEAL_RESULT_UNBOOTSTRAPPED = 3; +} + +message Request { + oneof payload { + UnsealStart start = 1; + UnsealEncryptedKey encrypted_key = 2; + } +} + +message Response { + oneof payload { + UnsealStartResponse start = 1; + UnsealResult result = 2; + } +} diff --git a/protobufs/operator/vault/vault.proto b/protobufs/operator/vault/vault.proto index 72bd940..ada6793 100644 --- a/protobufs/operator/vault/vault.proto +++ b/protobufs/operator/vault/vault.proto @@ -1,24 +1,24 @@ -syntax = "proto3"; - -package arbiter.operator.vault; - -import "google/protobuf/empty.proto"; -import "shared/vault.proto"; -import "operator/vault/bootstrap.proto"; -import "operator/vault/unseal.proto"; - -message Request { - oneof payload { - google.protobuf.Empty query_state = 1; - unseal.Request unseal = 2; - bootstrap.Request bootstrap = 3; - } -} - -message Response { - oneof payload { - arbiter.shared.VaultState state = 1; - unseal.Response unseal = 2; - bootstrap.Response bootstrap = 3; - } -} +syntax = "proto3"; + +package arbiter.operator.vault; + +import "google/protobuf/empty.proto"; +import "shared/vault.proto"; +import "operator/vault/bootstrap.proto"; +import "operator/vault/unseal.proto"; + +message Request { + oneof payload { + google.protobuf.Empty query_state = 1; + unseal.Request unseal = 2; + bootstrap.Request bootstrap = 3; + } +} + +message Response { + oneof payload { + arbiter.shared.VaultState state = 1; + unseal.Response unseal = 2; + bootstrap.Response bootstrap = 3; + } +} diff --git a/protobufs/shared/client.proto b/protobufs/shared/client.proto index b36c840..db6a43b 100644 --- a/protobufs/shared/client.proto +++ b/protobufs/shared/client.proto @@ -1,9 +1,9 @@ -syntax = "proto3"; - -package arbiter.shared; - -message ClientInfo { - string name = 1; - optional string description = 2; - optional string version = 3; -} +syntax = "proto3"; + +package arbiter.shared; + +message ClientInfo { + string name = 1; + optional string description = 2; + optional string version = 3; +} diff --git a/protobufs/shared/evm.proto b/protobufs/shared/evm.proto index 5ddd6f2..934f804 100644 --- a/protobufs/shared/evm.proto +++ b/protobufs/shared/evm.proto @@ -1,74 +1,74 @@ -syntax = "proto3"; - -package arbiter.shared.evm; - -import "google/protobuf/empty.proto"; - -message EtherTransferMeaning { - bytes to = 1; // 20-byte Ethereum address - bytes value = 2; // U256 as big-endian bytes -} - -message TokenInfo { - string symbol = 1; - bytes address = 2; // 20-byte Ethereum address - uint64 chain_id = 3; -} - -// Mirror of token_transfers::Meaning -message TokenTransferMeaning { - TokenInfo token = 1; - bytes to = 2; // 20-byte Ethereum address - bytes value = 3; // U256 as big-endian bytes -} - -// Mirror of policies::SpecificMeaning -message SpecificMeaning { - oneof meaning { - EtherTransferMeaning ether_transfer = 1; - TokenTransferMeaning token_transfer = 2; - } -} - -message GasLimitExceededViolation { - optional bytes max_gas_fee_per_gas = 1; // U256 as big-endian bytes - optional bytes max_priority_fee_per_gas = 2; // U256 as big-endian bytes -} - -message EvalViolation { - message ChainIdMismatch { - uint64 expected = 1; - uint64 actual = 2; - } - oneof kind { - bytes invalid_target = 1; // 20-byte Ethereum address - GasLimitExceededViolation gas_limit_exceeded = 2; - google.protobuf.Empty rate_limit_exceeded = 3; - google.protobuf.Empty volumetric_limit_exceeded = 4; - google.protobuf.Empty invalid_time = 5; - google.protobuf.Empty invalid_transaction_type = 6; - - ChainIdMismatch chain_id_mismatch = 7; - } -} - -// Transaction was classified but no grant covers it -message NoMatchingGrantError { - SpecificMeaning meaning = 1; -} - -// Transaction was classified and a grant was found, but constraints were violated -message PolicyViolationsError { - SpecificMeaning meaning = 1; - repeated EvalViolation violations = 2; -} - -// top-level error returned when transaction evaluation fails -message TransactionEvalError { - oneof kind { - google.protobuf.Empty contract_creation_not_supported = 1; - google.protobuf.Empty unsupported_transaction_type = 2; - NoMatchingGrantError no_matching_grant = 3; - PolicyViolationsError policy_violations = 4; - } -} +syntax = "proto3"; + +package arbiter.shared.evm; + +import "google/protobuf/empty.proto"; + +message EtherTransferMeaning { + bytes to = 1; // 20-byte Ethereum address + bytes value = 2; // U256 as big-endian bytes +} + +message TokenInfo { + string symbol = 1; + bytes address = 2; // 20-byte Ethereum address + uint64 chain_id = 3; +} + +// Mirror of token_transfers::Meaning +message TokenTransferMeaning { + TokenInfo token = 1; + bytes to = 2; // 20-byte Ethereum address + bytes value = 3; // U256 as big-endian bytes +} + +// Mirror of policies::SpecificMeaning +message SpecificMeaning { + oneof meaning { + EtherTransferMeaning ether_transfer = 1; + TokenTransferMeaning token_transfer = 2; + } +} + +message GasLimitExceededViolation { + optional bytes max_gas_fee_per_gas = 1; // U256 as big-endian bytes + optional bytes max_priority_fee_per_gas = 2; // U256 as big-endian bytes +} + +message EvalViolation { + message ChainIdMismatch { + uint64 expected = 1; + uint64 actual = 2; + } + oneof kind { + bytes invalid_target = 1; // 20-byte Ethereum address + GasLimitExceededViolation gas_limit_exceeded = 2; + google.protobuf.Empty rate_limit_exceeded = 3; + google.protobuf.Empty volumetric_limit_exceeded = 4; + google.protobuf.Empty invalid_time = 5; + google.protobuf.Empty invalid_transaction_type = 6; + + ChainIdMismatch chain_id_mismatch = 7; + } +} + +// Transaction was classified but no grant covers it +message NoMatchingGrantError { + SpecificMeaning meaning = 1; +} + +// Transaction was classified and a grant was found, but constraints were violated +message PolicyViolationsError { + SpecificMeaning meaning = 1; + repeated EvalViolation violations = 2; +} + +// top-level error returned when transaction evaluation fails +message TransactionEvalError { + oneof kind { + google.protobuf.Empty contract_creation_not_supported = 1; + google.protobuf.Empty unsupported_transaction_type = 2; + NoMatchingGrantError no_matching_grant = 3; + PolicyViolationsError policy_violations = 4; + } +} diff --git a/protobufs/shared/vault.proto b/protobufs/shared/vault.proto index 795539f..179b822 100644 --- a/protobufs/shared/vault.proto +++ b/protobufs/shared/vault.proto @@ -1,11 +1,11 @@ -syntax = "proto3"; - -package arbiter.shared; - -enum VaultState { - VAULT_STATE_UNSPECIFIED = 0; - VAULT_STATE_UNBOOTSTRAPPED = 1; - VAULT_STATE_SEALED = 2; - VAULT_STATE_UNSEALED = 3; - VAULT_STATE_ERROR = 4; -} +syntax = "proto3"; + +package arbiter.shared; + +enum VaultState { + VAULT_STATE_UNSPECIFIED = 0; + VAULT_STATE_UNBOOTSTRAPPED = 1; + VAULT_STATE_SEALED = 2; + VAULT_STATE_UNSEALED = 3; + VAULT_STATE_ERROR = 4; +} diff --git a/scripts/gen_erc20_registry.py b/scripts/gen_erc20_registry.py index 97c814e..315d097 100644 --- a/scripts/gen_erc20_registry.py +++ b/scripts/gen_erc20_registry.py @@ -1,150 +1,150 @@ -#!/usr/bin/env python3 -""" -Fetch the Uniswap default token list and emit Rust `TokenInfo` statics. - -Usage: - python3 gen_erc20_registry.py # fetch from IPFS - python3 gen_erc20_registry.py tokens.json # local file - python3 gen_erc20_registry.py tokens.json out.rs # custom output file -""" - -import json -import re -import sys -import unicodedata -import urllib.request - -UNISWAP_URL = "https://ipfs.io/ipns/tokens.uniswap.org" - -SOLANA_CHAIN_ID = 501000101 -IDENTIFIER_RE = re.compile(r"[^A-Za-z0-9]+") - - -def load_tokens(source=None): - if source: - with open(source) as f: - return json.load(f) - req = urllib.request.Request( - UNISWAP_URL, - headers={"Accept": "application/json", "User-Agent": "gen_tokens/1.0"}, - ) - with urllib.request.urlopen(req, timeout=60) as resp: - return json.loads(resp.read()) - - -def escape(s: str) -> str: - return s.replace("\\", "\\\\").replace('"', '\\"') - - -def to_screaming_case(name: str) -> str: - normalized = unicodedata.normalize("NFKD", name or "") - ascii_name = normalized.encode("ascii", "ignore").decode("ascii") - snake = IDENTIFIER_RE.sub("_", ascii_name).strip("_").upper() - if not snake: - snake = "TOKEN" - if snake[0].isdigit(): - snake = f"TOKEN_{snake}" - return snake - - -def static_name_for_token(token: dict, used_names: set[str]) -> str: - base = to_screaming_case(token.get("name", "")) - if base not in used_names: - used_names.add(base) - return base - - address = token["address"] - suffix = f"{token['chainId']}_{address[2:].upper()[-8:]}" - candidate = f"{base}_{suffix}" - - i = 2 - while candidate in used_names: - candidate = f"{base}_{suffix}_{i}" - i += 1 - - used_names.add(candidate) - return candidate - - -def main(): - source = sys.argv[1] if len(sys.argv) > 1 else None - output = sys.argv[2] if len(sys.argv) > 2 else "generated_tokens.rs" - data = load_tokens(source) - tokens = data["tokens"] - - # Deduplicate by (chainId, address) - seen = set() - unique = [] - for t in tokens: - key = (t["chainId"], t["address"].lower()) - if key not in seen: - seen.add(key) - unique.append(t) - - unique.sort(key=lambda t: (t["chainId"], t.get("symbol", "").upper())) - evm_tokens = [t for t in unique if t["chainId"] != SOLANA_CHAIN_ID] - - ver = data["version"] - lines = [] - w = lines.append - - w( - f"// Auto-generated from Uniswap token list v{ver['major']}.{ver['minor']}.{ver['patch']}" - ) - w(f"// {len(evm_tokens)} tokens") - w("// DO NOT EDIT - regenerate with gen_erc20_registry.py") - w("") - - used_static_names = set() - token_statics = [] - for t in evm_tokens: - static_name = static_name_for_token(t, used_static_names) - token_statics.append((static_name, t)) - - for static_name, t in token_statics: - addr = t["address"] - name = escape(t.get("name", "")) - symbol = escape(t.get("symbol", "")) - decimals = t.get("decimals", 18) - logo = t.get("logoURI") - chain = t["chainId"] - - logo_val = f'Some("{escape(logo)}")' if logo else "None" - - w(f"pub static {static_name}: TokenInfo = TokenInfo {{") - w(f' name: "{name}",') - w(f' symbol: "{symbol}",') - w(f" decimals: {decimals},") - w(f' contract: address!("{addr}"),') - w(f" chain: {chain},") - w(f" logo_uri: {logo_val},") - w("};") - w("") - - w("pub static TOKENS: &[&TokenInfo] = &[") - for static_name, _ in token_statics: - w(f" &{static_name},") - w("];") - w("") - w("pub fn get_token(") - w(" chain_id: alloy::primitives::ChainId,") - w(" address: alloy::primitives::Address,") - w(") -> Option<&'static TokenInfo> {") - w(" match (chain_id, address) {") - for static_name, t in token_statics: - w( - f' ({t["chainId"]}, addr) if addr == address!("{t["address"]}") => Some(&{static_name}),' - ) - w(" _ => None,") - w(" }") - w("}") - w("") - - with open(output, "w") as f: - f.write("\n".join(lines)) - - print(f"Wrote {len(token_statics)} tokens to {output}") - - -if __name__ == "__main__": - main() +#!/usr/bin/env python3 +""" +Fetch the Uniswap default token list and emit Rust `TokenInfo` statics. + +Usage: + python3 gen_erc20_registry.py # fetch from IPFS + python3 gen_erc20_registry.py tokens.json # local file + python3 gen_erc20_registry.py tokens.json out.rs # custom output file +""" + +import json +import re +import sys +import unicodedata +import urllib.request + +UNISWAP_URL = "https://ipfs.io/ipns/tokens.uniswap.org" + +SOLANA_CHAIN_ID = 501000101 +IDENTIFIER_RE = re.compile(r"[^A-Za-z0-9]+") + + +def load_tokens(source=None): + if source: + with open(source) as f: + return json.load(f) + req = urllib.request.Request( + UNISWAP_URL, + headers={"Accept": "application/json", "User-Agent": "gen_tokens/1.0"}, + ) + with urllib.request.urlopen(req, timeout=60) as resp: + return json.loads(resp.read()) + + +def escape(s: str) -> str: + return s.replace("\\", "\\\\").replace('"', '\\"') + + +def to_screaming_case(name: str) -> str: + normalized = unicodedata.normalize("NFKD", name or "") + ascii_name = normalized.encode("ascii", "ignore").decode("ascii") + snake = IDENTIFIER_RE.sub("_", ascii_name).strip("_").upper() + if not snake: + snake = "TOKEN" + if snake[0].isdigit(): + snake = f"TOKEN_{snake}" + return snake + + +def static_name_for_token(token: dict, used_names: set[str]) -> str: + base = to_screaming_case(token.get("name", "")) + if base not in used_names: + used_names.add(base) + return base + + address = token["address"] + suffix = f"{token['chainId']}_{address[2:].upper()[-8:]}" + candidate = f"{base}_{suffix}" + + i = 2 + while candidate in used_names: + candidate = f"{base}_{suffix}_{i}" + i += 1 + + used_names.add(candidate) + return candidate + + +def main(): + source = sys.argv[1] if len(sys.argv) > 1 else None + output = sys.argv[2] if len(sys.argv) > 2 else "generated_tokens.rs" + data = load_tokens(source) + tokens = data["tokens"] + + # Deduplicate by (chainId, address) + seen = set() + unique = [] + for t in tokens: + key = (t["chainId"], t["address"].lower()) + if key not in seen: + seen.add(key) + unique.append(t) + + unique.sort(key=lambda t: (t["chainId"], t.get("symbol", "").upper())) + evm_tokens = [t for t in unique if t["chainId"] != SOLANA_CHAIN_ID] + + ver = data["version"] + lines = [] + w = lines.append + + w( + f"// Auto-generated from Uniswap token list v{ver['major']}.{ver['minor']}.{ver['patch']}" + ) + w(f"// {len(evm_tokens)} tokens") + w("// DO NOT EDIT - regenerate with gen_erc20_registry.py") + w("") + + used_static_names = set() + token_statics = [] + for t in evm_tokens: + static_name = static_name_for_token(t, used_static_names) + token_statics.append((static_name, t)) + + for static_name, t in token_statics: + addr = t["address"] + name = escape(t.get("name", "")) + symbol = escape(t.get("symbol", "")) + decimals = t.get("decimals", 18) + logo = t.get("logoURI") + chain = t["chainId"] + + logo_val = f'Some("{escape(logo)}")' if logo else "None" + + w(f"pub static {static_name}: TokenInfo = TokenInfo {{") + w(f' name: "{name}",') + w(f' symbol: "{symbol}",') + w(f" decimals: {decimals},") + w(f' contract: address!("{addr}"),') + w(f" chain: {chain},") + w(f" logo_uri: {logo_val},") + w("};") + w("") + + w("pub static TOKENS: &[&TokenInfo] = &[") + for static_name, _ in token_statics: + w(f" &{static_name},") + w("];") + w("") + w("pub fn get_token(") + w(" chain_id: alloy::primitives::ChainId,") + w(" address: alloy::primitives::Address,") + w(") -> Option<&'static TokenInfo> {") + w(" match (chain_id, address) {") + for static_name, t in token_statics: + w( + f' ({t["chainId"]}, addr) if addr == address!("{t["address"]}") => Some(&{static_name}),' + ) + w(" _ => None,") + w(" }") + w("}") + w("") + + with open(output, "w") as f: + f.write("\n".join(lines)) + + print(f"Wrote {len(token_statics)} tokens to {output}") + + +if __name__ == "__main__": + main() diff --git a/server/.cargo/audit.toml b/server/.cargo/audit.toml index a615271..3ef8fe2 100644 --- a/server/.cargo/audit.toml +++ b/server/.cargo/audit.toml @@ -1,13 +1,13 @@ -[advisories] -# RUSTSEC-2023-0071: Marvin Attack timing side-channel in rsa crate. -# No fixed version is available upstream. -# RSA support is required for Windows Hello / KeyCredentialManager -# (https://learn.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredentialmanager.requestcreateasync), -# which only issues RSA-2048 keys. -# Mitigations in place: -# - Signing uses BlindedSigningKey (PSS+SHA-256), which applies blinding to -# protect the private key from timing recovery during signing. -# - RSA decryption is never performed; we only verify public-key signatures. -# - The attack requires local, high-resolution timing access against the -# signing process, which is not exposed in our threat model. -ignore = ["RUSTSEC-2023-0071"] +[advisories] +# RUSTSEC-2023-0071: Marvin Attack timing side-channel in rsa crate. +# No fixed version is available upstream. +# RSA support is required for Windows Hello / KeyCredentialManager +# (https://learn.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredentialmanager.requestcreateasync), +# which only issues RSA-2048 keys. +# Mitigations in place: +# - Signing uses BlindedSigningKey (PSS+SHA-256), which applies blinding to +# protect the private key from timing recovery during signing. +# - RSA decryption is never performed; we only verify public-key signatures. +# - The attack requires local, high-resolution timing access against the +# signing process, which is not exposed in our threat model. +ignore = ["RUSTSEC-2023-0071"] diff --git a/server/.cargo/config.toml b/server/.cargo/config.toml index 1cde5bc..a711c80 100644 --- a/server/.cargo/config.toml +++ b/server/.cargo/config.toml @@ -1,2 +1,2 @@ -[env] -MACOSX_DEPLOYMENT_TARGET = "26.3" +[env] +MACOSX_DEPLOYMENT_TARGET = "26.3" diff --git a/server/.cargo/mutants.toml b/server/.cargo/mutants.toml index efa7ea6..8049333 100644 --- a/server/.cargo/mutants.toml +++ b/server/.cargo/mutants.toml @@ -1 +1 @@ -test_tool = "nextest" +test_tool = "nextest" diff --git a/server/.gitignore b/server/.gitignore index 121a315..b1a2a6c 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -1,2 +1,2 @@ -mutants.out/ +mutants.out/ mutants.out.old/ \ No newline at end of file diff --git a/server/Cargo.lock b/server/Cargo.lock index e36c264..2f15cf5 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1,6347 +1,6347 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common 0.1.7", - "generic-array", -] - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "alloy" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8010fc7e9e8643ef4e758cdccf3eef26734594aedf88a9d5ed35e51837d42ef" -dependencies = [ - "alloy-consensus", - "alloy-contract", - "alloy-core", - "alloy-eips", - "alloy-genesis", - "alloy-network", - "alloy-provider", - "alloy-rpc-client", - "alloy-rpc-types", - "alloy-serde", - "alloy-signer", - "alloy-signer-local", - "alloy-transport", - "alloy-transport-http", - "alloy-trie", -] - -[[package]] -name = "alloy-chains" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84e0378e959aa6a885897522080a990e80eb317f1e9a222a604492ea50e13096" -dependencies = [ - "alloy-primitives", - "num_enum", - "strum 0.27.2", -] - -[[package]] -name = "alloy-consensus" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d64da86c616b5092ea64eea648f311bbd58630a0b384c42d699175d6f9122b" -dependencies = [ - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "alloy-trie", - "alloy-tx-macros", - "auto_impl", - "borsh", - "c-kzg", - "derive_more", - "either", - "k256", - "once_cell", - "rand 0.8.6", - "secp256k1", - "serde", - "serde_json", - "serde_with", - "thiserror", -] - -[[package]] -name = "alloy-consensus-any" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd98696ca3617d3a9ba1a6f2011880cbfd5618228dab6400c9f8bca457859a8" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-contract" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3df0aadc569a8b277808a7d0ad0e421180654ea36a3c59e9ed2bb968c9a1cd" -dependencies = [ - "alloy-consensus", - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-network", - "alloy-network-primitives", - "alloy-primitives", - "alloy-provider", - "alloy-rpc-types-eth", - "alloy-sol-types", - "alloy-transport", - "futures", - "futures-util", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "alloy-core" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e8604b0c092fabc80d075ede181c9b9e596249c70b99253082d7e689836529" -dependencies = [ - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-primitives", - "alloy-rlp", - "alloy-sol-types", -] - -[[package]] -name = "alloy-dyn-abi" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2db5c583aaef0255aa63a4fe827f826090142528bba48d1bf4119b62780cad" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-type-parser", - "alloy-sol-types", - "itoa", - "serde", - "serde_json", - "winnow 0.7.15", -] - -[[package]] -name = "alloy-eip2124" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "crc", - "serde", - "thiserror", -] - -[[package]] -name = "alloy-eip2930" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9441120fa82df73e8959ae0e4ab8ade03de2aaae61be313fbf5746277847ce25" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "borsh", - "serde", -] - -[[package]] -name = "alloy-eip7702" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2919c5a56a1007492da313e7a3b6d45ef5edc5d33416fdec63c0d7a2702a0d20" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "borsh", - "serde", - "thiserror", -] - -[[package]] -name = "alloy-eip7928" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec6ae911a2fc304a7cb80a79fb7bed6d1474aed4e7c203df1f8ff538f64fc78d" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "borsh", - "once_cell", - "serde", -] - -[[package]] -name = "alloy-eips" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c0456f5f7a4497e9342d20f528e30f5288ddfa0d6a012bd5044afee46cd8a0" -dependencies = [ - "alloy-eip2124", - "alloy-eip2930", - "alloy-eip7702", - "alloy-eip7928", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "auto_impl", - "borsh", - "c-kzg", - "derive_more", - "either", - "serde", - "serde_with", - "sha2 0.10.9", -] - -[[package]] -name = "alloy-genesis" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a71ff8b55d2b8aa05259f474cae7dea0e4991724dc18936b81cb23ec492a0c2a" -dependencies = [ - "alloy-eips", - "alloy-primitives", - "alloy-serde", - "alloy-trie", - "borsh", - "serde", - "serde_with", -] - -[[package]] -name = "alloy-json-abi" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dbe713da0c737d9e5e387b0ba790eb98b14dd207fe53eef50e19a5a8ec3dac" -dependencies = [ - "alloy-primitives", - "alloy-sol-type-parser", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-json-rpc" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e352478b756bad5d7203148e4b461861282ea2ded3da406ba24868b52cd098" -dependencies = [ - "alloy-primitives", - "alloy-sol-types", - "http", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "alloy-network" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed08ae169869e08370ed121612e0d3dadac33d1a256e9f2465926b23f0bd7d95" -dependencies = [ - "alloy-consensus", - "alloy-consensus-any", - "alloy-eips", - "alloy-json-rpc", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rpc-types-any", - "alloy-rpc-types-eth", - "alloy-serde", - "alloy-signer", - "alloy-sol-types", - "async-trait", - "auto_impl", - "derive_more", - "futures-utils-wasm", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-network-primitives" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e6c7ad28afe348a9a9c5624b67ee5b3607b8de98d5816b3056ecdfa6fa2697" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-primitives" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" -dependencies = [ - "alloy-rlp", - "bytes", - "cfg-if", - "const-hex", - "derive_more", - "foldhash 0.2.0", - "hashbrown 0.16.1", - "indexmap 2.14.0", - "itoa", - "k256", - "keccak-asm", - "paste", - "proptest", - "rand 0.9.4", - "rapidhash", - "ruint", - "rustc-hash", - "serde", - "sha3 0.10.9", -] - -[[package]] -name = "alloy-provider" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93a7c17472b55482d4734154c2f5ed13f72e03f6752cebb927f6a2d8b52e646c" -dependencies = [ - "alloy-chains", - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-network", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rpc-client", - "alloy-rpc-types-eth", - "alloy-signer", - "alloy-sol-types", - "alloy-transport", - "alloy-transport-http", - "async-stream", - "async-trait", - "auto_impl", - "dashmap", - "either", - "futures", - "futures-utils-wasm", - "lru", - "parking_lot", - "pin-project", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "url", - "wasmtimer", -] - -[[package]] -name = "alloy-rlp" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" -dependencies = [ - "alloy-rlp-derive", - "arrayvec", - "bytes", -] - -[[package]] -name = "alloy-rlp-derive" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36834a5c0a2fa56e171bf256c34d70fca07d0c0031583edea1c4946b7889c9e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "alloy-rpc-client" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5beb5c2fe6b960c8e8b038e69fd502a90a2e930afa4770efb748b163b0767729" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "alloy-transport", - "alloy-transport-http", - "futures", - "pin-project", - "reqwest", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", - "url", - "wasmtimer", -] - -[[package]] -name = "alloy-rpc-types" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee1257a278f6d293e05c5162c5940a1561b1aa85ded0028b464c81de37ebfa5" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-rpc-types-any" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a234bfbdf7a76c3d13808f729af5321852de3dedcaa6fc6d5f54787aaf54c6a" -dependencies = [ - "alloy-consensus-any", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-rpc-types-eth" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56a282daf869eeb7383d3d5c2deb35b0b3fb45ecb329513af4090fc61245ee18" -dependencies = [ - "alloy-consensus", - "alloy-consensus-any", - "alloy-eips", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "alloy-sol-types", - "itertools 0.14.0", - "serde", - "serde_json", - "serde_with", - "thiserror", -] - -[[package]] -name = "alloy-serde" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0eada2558e921b39dfcead33c487364df9b31374f5733c1c9d2c891c4529933" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", -] - -[[package]] -name = "alloy-signer" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41eb29f7a8adcd8941fbb8e134022a133e6f8dfd345f2e3b7109599f8a7dca08" -dependencies = [ - "alloy-primitives", - "async-trait", - "auto_impl", - "either", - "elliptic-curve", - "k256", - "thiserror", -] - -[[package]] -name = "alloy-signer-local" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef839e7ce9b59aa60fa9a175e97986c6145c888d643b0f1fb0a3e7b8e56a2e2" -dependencies = [ - "alloy-consensus", - "alloy-network", - "alloy-primitives", - "alloy-signer", - "async-trait", - "k256", - "rand 0.8.6", - "thiserror", -] - -[[package]] -name = "alloy-sol-macro" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" -dependencies = [ - "alloy-sol-macro-expander", - "alloy-sol-macro-input", - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "alloy-sol-macro-expander" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" -dependencies = [ - "alloy-json-abi", - "alloy-sol-macro-input", - "const-hex", - "heck", - "indexmap 2.14.0", - "proc-macro-error2", - "proc-macro2", - "quote", - "sha3 0.10.9", - "syn 2.0.117", - "syn-solidity", -] - -[[package]] -name = "alloy-sol-macro-input" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" -dependencies = [ - "alloy-json-abi", - "const-hex", - "dunce", - "heck", - "macro-string", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.117", - "syn-solidity", -] - -[[package]] -name = "alloy-sol-type-parser" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6df77fea9d6a2a75c0ef8d2acbdfd92286cc599983d3175ccdc170d3433d249" -dependencies = [ - "serde", - "winnow 0.7.15", -] - -[[package]] -name = "alloy-sol-types" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-macro", - "serde", -] - -[[package]] -name = "alloy-transport" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ac7a80c0bac3e44559d53d002e34c461dc2f23262b42cafec019bc70551abbe" -dependencies = [ - "alloy-json-rpc", - "auto_impl", - "base64", - "derive_more", - "futures", - "futures-utils-wasm", - "parking_lot", - "serde", - "serde_json", - "thiserror", - "tokio", - "tower", - "tracing", - "url", - "wasmtimer", -] - -[[package]] -name = "alloy-transport-http" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed3ed3300a998f88639ed619fdbbd88bd82865e00c6a8ecb796c99eb12358f6" -dependencies = [ - "alloy-json-rpc", - "alloy-transport", - "itertools 0.14.0", - "reqwest", - "serde_json", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-trie" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f14b5d9b2c2173980202c6ff470d96e7c5e202c65a9f67884ad565226df7fbb" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "derive_more", - "nybbles", - "serde", - "smallvec", - "thiserror", - "tracing", -] - -[[package]] -name = "alloy-tx-macros" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0350197dcd4ba4e9a7dd43915d908c0eb0e7352755791709a705e1c76b6" -dependencies = [ - "darling 0.23.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[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.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" - -[[package]] -name = "arbiter-client" -version = "0.1.0" -dependencies = [ - "alloy", - "arbiter-crypto", - "arbiter-proto", - "async-trait", - "chrono", - "http", - "rustls-webpki", - "thiserror", - "tokio", - "tokio-stream", - "tonic", -] - -[[package]] -name = "arbiter-crypto" -version = "0.1.0" -dependencies = [ - "alloy", - "chrono", - "hmac 0.13.0", - "memsafe", - "ml-dsa", - "rand 0.10.1", - "thiserror", - "x-wing", -] - -[[package]] -name = "arbiter-macros" -version = "0.1.0" -dependencies = [ - "arbiter-crypto", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "arbiter-proto" -version = "0.1.0" -dependencies = [ - "async-trait", - "base64", - "futures", - "kameo", - "miette", - "prost", - "prost-types", - "rcgen", - "rstest", - "rustls-pki-types", - "thiserror", - "tokio", - "tokio-stream", - "tonic", - "tonic-prost", - "tonic-prost-build", - "url", -] - -[[package]] -name = "arbiter-server" -version = "0.1.0" -dependencies = [ - "alloy", - "anyhow", - "arbiter-crypto", - "arbiter-macros", - "arbiter-proto", - "arbiter-tokens-registry", - "argon2", - "async-trait", - "chacha20poly1305", - "chrono", - "diesel", - "diesel-async", - "diesel_migrations", - "hmac 0.13.0", - "k256", - "kameo", - "kameo_actors", - "ml-dsa", - "mutants", - "pem", - "proptest", - "prost-types", - "rand 0.10.1", - "rcgen", - "restructed", - "rstest", - "rustls", - "sha2 0.11.0", - "smlang", - "strum 0.28.0", - "subtle", - "test-log", - "thiserror", - "tokio", - "tokio-stream", - "tonic", - "tracing", - "tracing-subscriber", - "x25519-dalek 2.0.1", -] - -[[package]] -name = "arbiter-tokens-registry" -version = "0.1.0" -dependencies = [ - "alloy", -] - -[[package]] -name = "argon2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" -dependencies = [ - "base64ct", - "blake2", - "cpufeatures 0.2.17", - "password-hash", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "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 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.4.1", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" -dependencies = [ - "ark-ff-asm 0.5.0", - "ark-ff-macros 0.5.0", - "ark-serialize 0.5.0", - "ark-std 0.5.0", - "arrayvec", - "digest 0.10.7", - "educe", - "itertools 0.13.0", - "num-bigint", - "num-traits", - "paste", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[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-asm" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" -dependencies = [ - "quote", - "syn 2.0.117", -] - -[[package]] -name = "ark-ff-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" -dependencies = [ - "num-bigint", - "num-traits", - "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-ff-macros" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" -dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "ark-serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" -dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-std 0.4.0", - "digest 0.10.7", - "num-bigint", -] - -[[package]] -name = "ark-serialize" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" -dependencies = [ - "ark-std 0.5.0", - "arrayvec", - "digest 0.10.7", - "num-bigint", -] - -[[package]] -name = "ark-std" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "num-traits", - "rand 0.8.6", -] - -[[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.6", -] - -[[package]] -name = "ark-std" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" -dependencies = [ - "num-traits", - "rand 0.8.6", -] - -[[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.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" -dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror", - "time", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "async-trait" -version = "0.1.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "auto_impl" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "aws-lc-rs" -version = "1.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" -dependencies = [ - "aws-lc-sys", - "untrusted 0.7.1", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "axum" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" -dependencies = [ - "axum-core", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "serde_core", - "sync_wrapper", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "sync_wrapper", - "tower-layer", - "tower-service", -] - -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link", -] - -[[package]] -name = "backtrace-ext" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" -dependencies = [ - "backtrace", -] - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" - -[[package]] -name = "bb8" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457d7ed3f888dfd2c7af56d4975cade43c622f74bdcddfed6d4352f57acc6310" -dependencies = [ - "futures-util", - "parking_lot", - "portable-atomic", - "tokio", -] - -[[package]] -name = "bit-set" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" - -[[package]] -name = "bitcoin-io" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" - -[[package]] -name = "bitcoin_hashes" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" -dependencies = [ - "bitcoin-io", - "hex-conservative", -] - -[[package]] -name = "bitflags" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest 0.10.7", -] - -[[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-buffer" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "blst" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" -dependencies = [ - "cc", - "glob", - "threadpool", - "zeroize", -] - -[[package]] -name = "borsh" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" -dependencies = [ - "borsh-derive", - "bytes", - "cfg_aliases", -] - -[[package]] -name = "borsh-derive" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" -dependencies = [ - "once_cell", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "bumpalo" -version = "3.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" - -[[package]] -name = "byte-slice-cast" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" -dependencies = [ - "serde", -] - -[[package]] -name = "c-kzg" -version = "2.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6648ed1e4ea8e8a1a4a2c78e1cda29a3fd500bc622899c340d8525ea9a76b24a" -dependencies = [ - "blst", - "cc", - "glob", - "hex", - "libc", - "once_cell", - "serde", -] - -[[package]] -name = "cc" -version = "1.2.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" -dependencies = [ - "find-msvc-tools", - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures 0.2.17", -] - -[[package]] -name = "chacha20" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "rand_core 0.10.1", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20 0.9.1", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "chrono" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common 0.1.7", - "inout", - "zeroize", -] - -[[package]] -name = "cmake" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" -dependencies = [ - "cc", -] - -[[package]] -name = "cmov" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "const-hex" -version = "1.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531185e432bb31db1ecda541e9e7ab21468d4d844ad7505e0546a49b4945d49b" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "proptest", - "serde_core", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "const-oid" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" - -[[package]] -name = "const_format" -version = "0.2.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" -dependencies = [ - "const_format_proc_macros", - "konst", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "convert_case" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -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 = "cpufeatures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" - -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - -[[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.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "typenum", -] - -[[package]] -name = "crypto-common" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" -dependencies = [ - "hybrid-array", - "rand_core 0.10.1", -] - -[[package]] -name = "ctutils" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" -dependencies = [ - "cmov", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "curve25519-dalek-derive", - "fiat-crypto 0.2.9", - "rustc_version 0.4.1", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek" -version = "5.0.0-pre.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335f1947f241137a14106b6f5acc5918a5ede29c9d71d3f2cb1678d5075d9fc3" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "curve25519-dalek-derive", - "fiat-crypto 0.3.0", - "rustc_version 0.4.1", - "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.117", -] - -[[package]] -name = "darling" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" -dependencies = [ - "darling_core 0.21.3", - "darling_macro 0.21.3", -] - -[[package]] -name = "darling" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" -dependencies = [ - "darling_core 0.23.0", - "darling_macro 0.23.0", -] - -[[package]] -name = "darling_core" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_core" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" -dependencies = [ - "ident_case", - "proc-macro2", - "quote", - "serde", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" -dependencies = [ - "darling_core 0.21.3", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" -dependencies = [ - "darling_core 0.23.0", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "data-encoding" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" - -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid 0.9.6", - "zeroize", -] - -[[package]] -name = "der" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b" -dependencies = [ - "const-oid 0.10.2", - "zeroize", -] - -[[package]] -name = "der-parser" -version = "10.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - -[[package]] -name = "deranged" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", - "serde_core", -] - -[[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 = "derive_more" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version 0.4.1", - "syn 2.0.117", - "unicode-xid", -] - -[[package]] -name = "diesel" -version = "2.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9940fb8467a0a06312218ed384185cb8536aa10d8ec017d0ce7fad2c1bd882d5" -dependencies = [ - "chrono", - "diesel_derives", - "downcast-rs", - "libsqlite3-sys", - "serde_json", - "sqlite-wasm-rs", - "time", - "uuid", -] - -[[package]] -name = "diesel-async" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c20ddcc6737cecdaef3dfecb2796bdfe3002456521189d30be8e4c5a1bc821d" -dependencies = [ - "bb8", - "diesel", - "diesel_migrations", - "futures-core", - "futures-util", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "diesel_derives" -version = "2.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1817b7f4279b947fc4cafddec12b0e5f8727141706561ce3ac94a60bddd1cf5" -dependencies = [ - "diesel_table_macro_syntax", - "dsl_auto_type", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "diesel_migrations" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d0f4a98124ba6d4ca75da535f65984badec16a003b6e2f94a01e31a79490b8" -dependencies = [ - "diesel", - "migrations_internals", - "migrations_macros", -] - -[[package]] -name = "diesel_table_macro_syntax" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe2444076b48641147115697648dc743c2c00b61adade0f01ce67133c7babe8c" -dependencies = [ - "syn 2.0.117", -] - -[[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 0.9.6", - "crypto-common 0.1.7", - "subtle", -] - -[[package]] -name = "digest" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" -dependencies = [ - "block-buffer 0.12.0", - "const-oid 0.10.2", - "crypto-common 0.2.1", - "ctutils", -] - -[[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.117", -] - -[[package]] -name = "downcast-rs" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" - -[[package]] -name = "dsl_auto_type" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd122633e4bef06db27737f21d3738fb89c8f6d5360d6d9d7635dda142a7757e" -dependencies = [ - "darling 0.21.3", - "either", - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "dyn-clone" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der 0.7.10", - "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "serdect", - "signature 2.2.0", - "spki 0.7.3", -] - -[[package]] -name = "educe" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" -dependencies = [ - "enum-ordinalize", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -dependencies = [ - "serde", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pkcs8 0.10.2", - "rand_core 0.6.4", - "sec1", - "serdect", - "subtle", - "zeroize", -] - -[[package]] -name = "enum-ordinalize" -version = "4.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" -dependencies = [ - "enum-ordinalize-derive", -] - -[[package]] -name = "enum-ordinalize-derive" -version = "4.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "fastrand" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "fastrlp" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - -[[package]] -name = "fiat-crypto" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" - -[[package]] -name = "find-msvc-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand 0.8.6", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - -[[package]] -name = "flate2" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" -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 = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foldhash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-executor" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" - -[[package]] -name = "futures-macro" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "futures-sink" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" - -[[package]] -name = "futures-task" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" - -[[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.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "slab", -] - -[[package]] -name = "futures-utils-wasm" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi 5.3.0", - "wasip2", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" -dependencies = [ - "cfg-if", - "libc", - "r-efi 6.0.0", - "rand_core 0.10.1", - "wasip2", - "wasip3", -] - -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - -[[package]] -name = "glob" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "h2" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap 2.14.0", - "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.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", - "serde", - "serde_core", -] - -[[package]] -name = "hashbrown" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" - -[[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.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[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.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" -dependencies = [ - "arrayvec", -] - -[[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" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" -dependencies = [ - "digest 0.11.2", -] - -[[package]] -name = "http" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" -dependencies = [ - "bytes", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hybrid-array" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" -dependencies = [ - "ctutils", - "typenum", - "zeroize", -] - -[[package]] -name = "hyper" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" -dependencies = [ - "http", - "hyper", - "hyper-util", - "rustls", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-timeout" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" -dependencies = [ - "hyper", - "hyper-util", - "pin-project-lite", - "tokio", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" -dependencies = [ - "base64", - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "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 = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" -dependencies = [ - "displaydoc", - "potential_utf", - "utf8_iter", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" - -[[package]] -name = "icu_properties" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" - -[[package]] -name = "icu_provider" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - -[[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.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[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.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" -dependencies = [ - "equivalent", - "hashbrown 0.17.0", - "serde", - "serde_core", -] - -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", -] - -[[package]] -name = "ipnet" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" - -[[package]] -name = "iri-string" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "is_ci" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" - -[[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.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "jni" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" -dependencies = [ - "cfg-if", - "combine", - "jni-macros", - "jni-sys", - "log", - "simd_cesu8", - "thiserror", - "walkdir", - "windows-link", -] - -[[package]] -name = "jni-macros" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version 0.4.1", - "simd_cesu8", - "syn 2.0.117", -] - -[[package]] -name = "jni-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" -dependencies = [ - "jni-sys-macros", -] - -[[package]] -name = "jni-sys-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" -dependencies = [ - "quote", - "syn 2.0.117", -] - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" -dependencies = [ - "cfg-if", - "futures-util", - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "k256" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "once_cell", - "serdect", - "sha2 0.10.9", - "signature 2.2.0", -] - -[[package]] -name = "kameo" -version = "0.20.0" -source = "git+https://github.com/hdbg/kameo.git?rev=805b417#805b41783fe90b54827ecad142b422c7a9b69b9a" -dependencies = [ - "downcast-rs", - "dyn-clone", - "futures", - "kameo_macros", - "serde", - "tokio", - "tracing", -] - -[[package]] -name = "kameo_actors" -version = "0.5.0" -source = "git+https://github.com/hdbg/kameo.git?rev=805b417#805b41783fe90b54827ecad142b422c7a9b69b9a" -dependencies = [ - "futures", - "glob", - "kameo", - "thiserror", - "tokio", -] - -[[package]] -name = "kameo_macros" -version = "0.20.0" -source = "git+https://github.com/hdbg/kameo.git?rev=805b417#805b41783fe90b54827ecad142b422c7a9b69b9a" -dependencies = [ - "darling 0.23.0", - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "keccak" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" -dependencies = [ - "cpufeatures 0.2.17", -] - -[[package]] -name = "keccak" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", -] - -[[package]] -name = "keccak-asm" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa468878266ad91431012b3e5ef1bf9b170eab22883503a318d46857afa4579a" -dependencies = [ - "digest 0.10.7", - "sha3-asm", -] - -[[package]] -name = "kem" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01737161ba802849cfd486b5bd209d38ba4943494c249a8126005170c7621edd" -dependencies = [ - "crypto-common 0.2.1", - "rand_core 0.10.1", -] - -[[package]] -name = "konst" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" -dependencies = [ - "konst_macro_rules", -] - -[[package]] -name = "konst_macro_rules" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - -[[package]] -name = "libc" -version = "0.2.186" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" - -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - -[[package]] -name = "libsqlite3-sys" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" -dependencies = [ - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - -[[package]] -name = "litemap" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "lru" -version = "0.16.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" -dependencies = [ - "hashbrown 0.16.1", -] - -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - -[[package]] -name = "macro-string" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "matchit" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" - -[[package]] -name = "memchr" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" - -[[package]] -name = "memsafe" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f3e199d5e8adf073900f95b635f1192c394a442ed406c16dc7991b74501645" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "miette" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" -dependencies = [ - "backtrace", - "backtrace-ext", - "cfg-if", - "miette-derive", - "owo-colors", - "serde", - "supports-color", - "supports-hyperlinks", - "supports-unicode", - "terminal_size", - "textwrap", - "unicode-width 0.1.14", -] - -[[package]] -name = "miette-derive" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "migrations_internals" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c791ecdf977c99f45f23280405d7723727470f6689a5e6dbf513ac547ae10d" -dependencies = [ - "serde", - "toml", -] - -[[package]] -name = "migrations_macros" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36fc5ac76be324cfd2d3f2cf0fdf5d5d3c4f14ed8aaebadb09e304ba42282703" -dependencies = [ - "migrations_internals", - "proc-macro2", - "quote", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[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.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "ml-dsa" -version = "0.1.0-rc.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a596bd65985e2b343c3fd6cc4ade15cdd76da66b15936cfbce72ea661cdbb2" -dependencies = [ - "const-oid 0.10.2", - "ctutils", - "hybrid-array", - "module-lattice", - "pkcs8 0.11.0", - "rand_core 0.10.1", - "sha3 0.11.0", - "signature 3.0.0-rc.10", - "zeroize", -] - -[[package]] -name = "ml-kem" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c77d5ff6d755d09a0ef4d4d28c2b7e83658fe83e8c736d55e93d43e380d1cd" -dependencies = [ - "hybrid-array", - "kem", - "module-lattice", - "rand_core 0.10.1", - "sha3 0.11.0", - "zeroize", -] - -[[package]] -name = "module-lattice" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc7c90d33a0dac244570c26461d761ffaeadb3bfc2b17cc625ae2185cafdffae" -dependencies = [ - "ctutils", - "hybrid-array", - "num-traits", - "zeroize", -] - -[[package]] -name = "multimap" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" - -[[package]] -name = "mutants" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ac067452ff1aca8c5002111bd6b1c895baee6e45fcbc44e0193aea17be56" - -[[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 = "nu-ansi-term" -version = "0.50.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" -dependencies = [ - "windows-sys 0.61.2", -] - -[[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-conv" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" - -[[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", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" -dependencies = [ - "num_enum_derive", - "rustversion", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "nybbles" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210" -dependencies = [ - "alloy-rlp", - "cfg-if", - "proptest", - "ruint", - "serde", - "smallvec", -] - -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - -[[package]] -name = "oid-registry" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" -dependencies = [ - "asn1-rs", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "openssl-probe" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" - -[[package]] -name = "owo-colors" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" - -[[package]] -name = "parity-scale-codec" -version = "3.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "const_format", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "rustversion", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[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 = "pem" -version = "3.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" -dependencies = [ - "base64", - "serde_core", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pest" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" -dependencies = [ - "memchr", - "ucd-trie", -] - -[[package]] -name = "petgraph" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" -dependencies = [ - "fixedbitset", - "hashbrown 0.15.5", - "indexmap 2.14.0", -] - -[[package]] -name = "pin-project" -version = "1.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der 0.7.10", - "spki 0.7.3", -] - -[[package]] -name = "pkcs8" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" -dependencies = [ - "der 0.8.0", - "spki 0.8.0", -] - -[[package]] -name = "pkg-config" -version = "0.3.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures 0.2.17", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - -[[package]] -name = "potential_utf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" -dependencies = [ - "zerovec", -] - -[[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.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.117", -] - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" -dependencies = [ - "bit-set", - "bit-vec", - "bitflags", - "num-traits", - "rand 0.9.4", - "rand_chacha 0.9.0", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", - "unarray", -] - -[[package]] -name = "prost" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-build" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" -dependencies = [ - "heck", - "itertools 0.14.0", - "log", - "multimap", - "petgraph", - "prettyplease", - "prost", - "prost-types", - "pulldown-cmark", - "pulldown-cmark-to-cmark", - "regex", - "syn 2.0.117", - "tempfile", -] - -[[package]] -name = "prost-derive" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" -dependencies = [ - "anyhow", - "itertools 0.14.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "prost-types" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" -dependencies = [ - "chrono", - "prost", -] - -[[package]] -name = "pulldown-cmark" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" -dependencies = [ - "bitflags", - "memchr", - "unicase", -] - -[[package]] -name = "pulldown-cmark-to-cmark" -version = "22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" -dependencies = [ - "pulldown-cmark", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quinn" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" -dependencies = [ - "aws-lc-rs", - "bytes", - "getrandom 0.3.4", - "lru-slab", - "rand 0.9.4", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.60.2", -] - -[[package]] -name = "quote" -version = "1.0.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "r-efi" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", - "serde", -] - -[[package]] -name = "rand" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.5", - "serde", -] - -[[package]] -name = "rand" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" -dependencies = [ - "chacha20 0.10.0", - "getrandom 0.4.2", - "rand_core 0.10.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_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.5", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", - "serde", -] - -[[package]] -name = "rand_core" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" - -[[package]] -name = "rand_xorshift" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" -dependencies = [ - "rand_core 0.9.5", -] - -[[package]] -name = "rapidhash" -version = "4.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" -dependencies = [ - "rustversion", -] - -[[package]] -name = "rcgen" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b99e0098aa4082912d4c649628623db6aba77335e4f4569ff5083a6448b32e" -dependencies = [ - "aws-lc-rs", - "pem", - "rustls-pki-types", - "time", - "x509-parser", - "yasna", - "zeroize", -] - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags", -] - -[[package]] -name = "ref-cast" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "regex" -version = "1.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" - -[[package]] -name = "relative-path" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" - -[[package]] -name = "reqwest" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" -dependencies = [ - "base64", - "bytes", - "futures-core", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pki-types", - "rustls-platform-verifier", - "serde", - "serde_json", - "sync_wrapper", - "tokio", - "tokio-rustls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "restructed" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6f6e863d7d9d318699737c043d560dce1ea3cb6f5c78e0a3f0d1f257c73dfc" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac 0.12.1", - "subtle", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.17", - "libc", - "untrusted 0.9.0", - "windows-sys 0.52.0", -] - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "rustc-hex", -] - -[[package]] -name = "rsqlite-vfs" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a1f2315036ef6b1fbacd1972e8ee7688030b0a2121edfc2a6550febd41574d" -dependencies = [ - "hashbrown 0.16.1", - "thiserror", -] - -[[package]] -name = "rstest" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49" -dependencies = [ - "futures-timer", - "futures-util", - "rstest_macros", -] - -[[package]] -name = "rstest_macros" -version = "0.26.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0" -dependencies = [ - "cfg-if", - "glob", - "proc-macro-crate", - "proc-macro2", - "quote", - "regex", - "relative-path", - "rustc_version 0.4.1", - "syn 2.0.117", - "unicode-ident", -] - -[[package]] -name = "ruint" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0298da754d1395046b0afdc2f20ee76d29a8ae310cd30ffa84ed42acba9cb12a" -dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "ark-ff 0.5.0", - "bytes", - "fastrlp 0.3.1", - "fastrlp 0.4.0", - "num-bigint", - "num-integer", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "rand 0.8.6", - "rand 0.9.4", - "rlp", - "ruint-macro", - "serde_core", - "valuable", - "zeroize", -] - -[[package]] -name = "ruint-macro" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" - -[[package]] -name = "rustc-demangle" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" - -[[package]] -name = "rustc-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver 1.0.28", -] - -[[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 = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustls" -version = "0.23.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pki-types" -version = "1.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" -dependencies = [ - "web-time", - "zeroize", -] - -[[package]] -name = "rustls-platform-verifier" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs", - "windows-sys 0.61.2", -] - -[[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.103.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted 0.9.0", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "rusty-fork" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[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.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "schemars" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - -[[package]] -name = "schemars" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der 0.7.10", - "generic-array", - "pkcs8 0.10.2", - "serdect", - "subtle", - "zeroize", -] - -[[package]] -name = "secp256k1" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" -dependencies = [ - "bitcoin_hashes", - "rand 0.8.6", - "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 = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" - -[[package]] -name = "semver-parser" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" -dependencies = [ - "pest", -] - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "serde_json" -version = "1.0.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "serde_spanned" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" -dependencies = [ - "serde_core", -] - -[[package]] -name = "serde_with" -version = "3.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" -dependencies = [ - "base64", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.14.0", - "schemars 0.9.0", - "schemars 1.2.1", - "serde_core", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" -dependencies = [ - "darling 0.23.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "serdect" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" -dependencies = [ - "base16ct", - "serde", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "digest 0.11.2", -] - -[[package]] -name = "sha3" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" -dependencies = [ - "digest 0.10.7", - "keccak 0.1.6", -] - -[[package]] -name = "sha3" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" -dependencies = [ - "digest 0.11.2", - "keccak 0.2.0", -] - -[[package]] -name = "sha3-asm" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59cbb88c189d6352cc8ae96a39d19c7ecad8f7330b29461187f2587fdc2988d5" -dependencies = [ - "cc", - "cfg-if", -] - -[[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.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - -[[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 = "signature" -version = "3.0.0-rc.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f1880df446116126965eeec169136b2e0251dba37c6223bcc819569550edea3" -dependencies = [ - "digest 0.11.2", - "rand_core 0.10.1", -] - -[[package]] -name = "simd-adler32" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" - -[[package]] -name = "simd_cesu8" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" -dependencies = [ - "rustc_version 0.4.1", - "simdutf8", -] - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - -[[package]] -name = "slab" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -dependencies = [ - "serde", -] - -[[package]] -name = "smlang" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de84f9f80bbe6272174e2bfdb8cf7ce4815b218038a42161c2f21c1d872c215" -dependencies = [ - "smlang-macros", -] - -[[package]] -name = "smlang-macros" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "231b4425dcc43afc7e18c34e7c6738cd252d42d91d909c948df14107c9ae79f1" -dependencies = [ - "proc-macro2", - "quote", - "string_morph", - "syn 1.0.109", -] - -[[package]] -name = "socket2" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der 0.7.10", -] - -[[package]] -name = "spki" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f" -dependencies = [ - "base64ct", - "der 0.8.0", -] - -[[package]] -name = "sqlite-wasm-rs" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b2c760607300407ddeaee518acf28c795661b7108c75421303dbefb237d3a36" -dependencies = [ - "cc", - "js-sys", - "rsqlite-vfs", - "wasm-bindgen", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "string_morph" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "183aaf7fa637cc7b5f54c45b8f7cb6e8d73831f9f75a56b6defa5bf8c51d1699" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros 0.27.2", -] - -[[package]] -name = "strum" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" -dependencies = [ - "strum_macros 0.28.0", -] - -[[package]] -name = "strum_macros" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "strum_macros" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "supports-color" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" -dependencies = [ - "is_ci", -] - -[[package]] -name = "supports-hyperlinks" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91" - -[[package]] -name = "supports-unicode" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" - -[[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.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn-solidity" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" -dependencies = [ - "paste", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" -dependencies = [ - "fastrand", - "getrandom 0.4.2", - "once_cell", - "rustix", - "windows-sys 0.61.2", -] - -[[package]] -name = "terminal_size" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" -dependencies = [ - "rustix", - "windows-sys 0.61.2", -] - -[[package]] -name = "test-log" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f46bf474f0a4afebf92f076d54fd5e63423d9438b8c278a3d2ccb0f47f7cdb3" -dependencies = [ - "test-log-macros", - "tracing-subscriber", -] - -[[package]] -name = "test-log-core" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d4d41320b48bc4a211a9021678fcc0c99569b594ea31c93735b8e517102b4c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "test-log-macros" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9beb9249a81e430dffd42400a49019bcf548444f1968ff23080a625de0d4d320" -dependencies = [ - "syn 2.0.117", - "test-log-core", -] - -[[package]] -name = "textwrap" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" -dependencies = [ - "unicode-linebreak", - "unicode-width 0.2.2", -] - -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "time" -version = "0.3.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde_core", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" - -[[package]] -name = "time-macros" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinystr" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinyvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" -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.52.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" -dependencies = [ - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "tracing", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", - "tokio-util", -] - -[[package]] -name = "tokio-util" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.9.12+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" -dependencies = [ - "serde_core", - "serde_spanned", - "toml_datetime 0.7.5+spec-1.1.0", - "toml_parser", - "winnow 0.7.15", -] - -[[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_datetime" -version = "1.1.1+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_edit" -version = "0.25.11+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" -dependencies = [ - "indexmap 2.14.0", - "toml_datetime 1.1.1+spec-1.1.0", - "toml_parser", - "winnow 1.0.2", -] - -[[package]] -name = "toml_parser" -version = "1.1.2+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" -dependencies = [ - "winnow 1.0.2", -] - -[[package]] -name = "tonic" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" -dependencies = [ - "async-trait", - "axum", - "base64", - "bytes", - "flate2", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-timeout", - "hyper-util", - "percent-encoding", - "pin-project", - "socket2", - "sync_wrapper", - "tokio", - "tokio-rustls", - "tokio-stream", - "tower", - "tower-layer", - "tower-service", - "tracing", - "zstd", -] - -[[package]] -name = "tonic-build" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734" -dependencies = [ - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "tonic-prost" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" -dependencies = [ - "bytes", - "prost", - "tonic", -] - -[[package]] -name = "tonic-prost-build" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" -dependencies = [ - "prettyplease", - "proc-macro2", - "prost-build", - "prost-types", - "quote", - "syn 2.0.117", - "tempfile", - "tonic-build", -] - -[[package]] -name = "tower" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" -dependencies = [ - "futures-core", - "futures-util", - "indexmap 2.14.0", - "pin-project-lite", - "slab", - "sync_wrapper", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-http" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" -dependencies = [ - "bitflags", - "bytes", - "futures-util", - "http", - "http-body", - "iri-string", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -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.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -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.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", - "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 = "typenum" -version = "1.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" - -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - -[[package]] -name = "unicase" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "unicode-linebreak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" - -[[package]] -name = "unicode-segmentation" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - -[[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 0.1.7", - "subtle", -] - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", - "serde_derive", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid" -version = "1.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[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 = "wait-timeout" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" -dependencies = [ - "libc", -] - -[[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.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen 0.51.0", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn 2.0.117", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap 2.14.0", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags", - "hashbrown 0.15.5", - "indexmap 2.14.0", - "semver 1.0.28", -] - -[[package]] -name = "wasmtimer" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b" -dependencies = [ - "futures", - "js-sys", - "parking_lot", - "pin-utils", - "slab", - "wasm-bindgen", -] - -[[package]] -name = "web-sys" -version = "0.3.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" -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 = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" -dependencies = [ - "rustls-pki-types", -] - -[[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.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - -[[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.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[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.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[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 0.52.6", - "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-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[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_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[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_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - -[[package]] -name = "winnow" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" -dependencies = [ - "memchr", -] - -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap 2.14.0", - "prettyplease", - "syn 2.0.117", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags", - "indexmap 2.14.0", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap 2.14.0", - "log", - "semver 1.0.28", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - -[[package]] -name = "writeable" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "x-wing" -version = "0.1.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d0d5f4d1f26b9b9e7477af1d3bef960e1d1fb64edab7912fde472a8a8432e" -dependencies = [ - "kem", - "ml-kem", - "rand_core 0.10.1", - "sha3 0.11.0", - "x25519-dalek 3.0.0-pre.6", - "zeroize", -] - -[[package]] -name = "x25519-dalek" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" -dependencies = [ - "curve25519-dalek 4.1.3", - "rand_core 0.6.4", - "serde", - "zeroize", -] - -[[package]] -name = "x25519-dalek" -version = "3.0.0-pre.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d5d6ff67acd3945b933e592bfa7143db4fcbb2f871754b6b9fbd7847fc5aea" -dependencies = [ - "curve25519-dalek 5.0.0-pre.6", - "rand_core 0.10.1", - "zeroize", -] - -[[package]] -name = "x509-parser" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" -dependencies = [ - "asn1-rs", - "aws-lc-rs", - "data-encoding", - "der-parser", - "lazy_static", - "nom", - "oid-registry", - "rusticata-macros", - "thiserror", - "time", -] - -[[package]] -name = "yasna" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" -dependencies = [ - "time", -] - -[[package]] -name = "yoke" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "zerofrom" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "zerotrie" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" - -[[package]] -name = "zstd" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" -dependencies = [ - "cc", - "pkg-config", -] +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common 0.1.7", + "generic-array", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "alloy" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8010fc7e9e8643ef4e758cdccf3eef26734594aedf88a9d5ed35e51837d42ef" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-network", + "alloy-provider", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", + "alloy-trie", +] + +[[package]] +name = "alloy-chains" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84e0378e959aa6a885897522080a990e80eb317f1e9a222a604492ea50e13096" +dependencies = [ + "alloy-primitives", + "num_enum", + "strum 0.27.2", +] + +[[package]] +name = "alloy-consensus" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d64da86c616b5092ea64eea648f311bbd58630a0b384c42d699175d6f9122b" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-trie", + "alloy-tx-macros", + "auto_impl", + "borsh", + "c-kzg", + "derive_more", + "either", + "k256", + "once_cell", + "rand 0.8.6", + "secp256k1", + "serde", + "serde_json", + "serde_with", + "thiserror", +] + +[[package]] +name = "alloy-consensus-any" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd98696ca3617d3a9ba1a6f2011880cbfd5618228dab6400c9f8bca457859a8" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-contract" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3df0aadc569a8b277808a7d0ad0e421180654ea36a3c59e9ed2bb968c9a1cd" +dependencies = [ + "alloy-consensus", + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "alloy-core" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23e8604b0c092fabc80d075ede181c9b9e596249c70b99253082d7e689836529" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", +] + +[[package]] +name = "alloy-dyn-abi" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2db5c583aaef0255aa63a4fe827f826090142528bba48d1bf4119b62780cad" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "itoa", + "serde", + "serde_json", + "winnow 0.7.15", +] + +[[package]] +name = "alloy-eip2124" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "crc", + "serde", + "thiserror", +] + +[[package]] +name = "alloy-eip2930" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9441120fa82df73e8959ae0e4ab8ade03de2aaae61be313fbf5746277847ce25" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2919c5a56a1007492da313e7a3b6d45ef5edc5d33416fdec63c0d7a2702a0d20" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "serde", + "thiserror", +] + +[[package]] +name = "alloy-eip7928" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec6ae911a2fc304a7cb80a79fb7bed6d1474aed4e7c203df1f8ff538f64fc78d" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "once_cell", + "serde", +] + +[[package]] +name = "alloy-eips" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c0456f5f7a4497e9342d20f528e30f5288ddfa0d6a012bd5044afee46cd8a0" +dependencies = [ + "alloy-eip2124", + "alloy-eip2930", + "alloy-eip7702", + "alloy-eip7928", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "auto_impl", + "borsh", + "c-kzg", + "derive_more", + "either", + "serde", + "serde_with", + "sha2 0.10.9", +] + +[[package]] +name = "alloy-genesis" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a71ff8b55d2b8aa05259f474cae7dea0e4991724dc18936b81cb23ec492a0c2a" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "alloy-trie", + "borsh", + "serde", + "serde_with", +] + +[[package]] +name = "alloy-json-abi" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9dbe713da0c737d9e5e387b0ba790eb98b14dd207fe53eef50e19a5a8ec3dac" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-rpc" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e352478b756bad5d7203148e4b461861282ea2ded3da406ba24868b52cd098" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "http", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "alloy-network" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed08ae169869e08370ed121612e0d3dadac33d1a256e9f2465926b23f0bd7d95" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-json-rpc", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-any", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "auto_impl", + "derive_more", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-network-primitives" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e6c7ad28afe348a9a9c5624b67ee5b3607b8de98d5816b3056ecdfa6fa2697" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-primitives" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "foldhash 0.2.0", + "hashbrown 0.16.1", + "indexmap 2.14.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.9.4", + "rapidhash", + "ruint", + "rustc-hash", + "serde", + "sha3 0.10.9", +] + +[[package]] +name = "alloy-provider" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93a7c17472b55482d4734154c2f5ed13f72e03f6752cebb927f6a2d8b52e646c" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-types-eth", + "alloy-signer", + "alloy-sol-types", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "either", + "futures", + "futures-utils-wasm", + "lru", + "parking_lot", + "pin-project", + "reqwest", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc90b1e703d3c03f4ff7f48e82dd0bc1c8211ab7d079cd836a06fcfeb06651cb" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36834a5c0a2fa56e171bf256c34d70fca07d0c0031583edea1c4946b7889c9e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "alloy-rpc-client" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5beb5c2fe6b960c8e8b038e69fd502a90a2e930afa4770efb748b163b0767729" +dependencies = [ + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-rpc-types" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee1257a278f6d293e05c5162c5940a1561b1aa85ded0028b464c81de37ebfa5" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] + +[[package]] +name = "alloy-rpc-types-any" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a234bfbdf7a76c3d13808f729af5321852de3dedcaa6fc6d5f54787aaf54c6a" +dependencies = [ + "alloy-consensus-any", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-rpc-types-eth" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56a282daf869eeb7383d3d5c2deb35b0b3fb45ecb329513af4090fc61245ee18" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "itertools 0.14.0", + "serde", + "serde_json", + "serde_with", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eada2558e921b39dfcead33c487364df9b31374f5733c1c9d2c891c4529933" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41eb29f7a8adcd8941fbb8e134022a133e6f8dfd345f2e3b7109599f8a7dca08" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "either", + "elliptic-curve", + "k256", + "thiserror", +] + +[[package]] +name = "alloy-signer-local" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef839e7ce9b59aa60fa9a175e97986c6145c888d643b0f1fb0a3e7b8e56a2e2" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "k256", + "rand 0.8.6", + "thiserror", +] + +[[package]] +name = "alloy-sol-macro" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" +dependencies = [ + "alloy-json-abi", + "alloy-sol-macro-input", + "const-hex", + "heck", + "indexmap 2.14.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "sha3 0.10.9", + "syn 2.0.117", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" +dependencies = [ + "alloy-json-abi", + "const-hex", + "dunce", + "heck", + "macro-string", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.117", + "syn-solidity", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6df77fea9d6a2a75c0ef8d2acbdfd92286cc599983d3175ccdc170d3433d249" +dependencies = [ + "serde", + "winnow 0.7.15", +] + +[[package]] +name = "alloy-sol-types" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" +dependencies = [ + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "serde", +] + +[[package]] +name = "alloy-transport" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ac7a80c0bac3e44559d53d002e34c461dc2f23262b42cafec019bc70551abbe" +dependencies = [ + "alloy-json-rpc", + "auto_impl", + "base64", + "derive_more", + "futures", + "futures-utils-wasm", + "parking_lot", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", + "wasmtimer", +] + +[[package]] +name = "alloy-transport-http" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed3ed3300a998f88639ed619fdbbd88bd82865e00c6a8ecb796c99eb12358f6" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "itertools 0.14.0", + "reqwest", + "serde_json", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-trie" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f14b5d9b2c2173980202c6ff470d96e7c5e202c65a9f67884ad565226df7fbb" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "derive_more", + "nybbles", + "serde", + "smallvec", + "thiserror", + "tracing", +] + +[[package]] +name = "alloy-tx-macros" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99fce0350197dcd4ba4e9a7dd43915d908c0eb0e7352755791709a705e1c76b6" +dependencies = [ + "darling 0.23.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arbiter-client" +version = "0.1.0" +dependencies = [ + "alloy", + "arbiter-crypto", + "arbiter-proto", + "async-trait", + "chrono", + "http", + "rustls-webpki", + "thiserror", + "tokio", + "tokio-stream", + "tonic", +] + +[[package]] +name = "arbiter-crypto" +version = "0.1.0" +dependencies = [ + "alloy", + "chrono", + "hmac 0.13.0", + "memsafe", + "ml-dsa", + "rand 0.10.1", + "thiserror", + "x-wing", +] + +[[package]] +name = "arbiter-macros" +version = "0.1.0" +dependencies = [ + "arbiter-crypto", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "arbiter-proto" +version = "0.1.0" +dependencies = [ + "async-trait", + "base64", + "futures", + "kameo", + "miette", + "prost", + "prost-types", + "rcgen", + "rstest", + "rustls-pki-types", + "thiserror", + "tokio", + "tokio-stream", + "tonic", + "tonic-prost", + "tonic-prost-build", + "url", +] + +[[package]] +name = "arbiter-server" +version = "0.1.0" +dependencies = [ + "alloy", + "anyhow", + "arbiter-crypto", + "arbiter-macros", + "arbiter-proto", + "arbiter-tokens-registry", + "argon2", + "async-trait", + "chacha20poly1305", + "chrono", + "diesel", + "diesel-async", + "diesel_migrations", + "hmac 0.13.0", + "k256", + "kameo", + "kameo_actors", + "ml-dsa", + "mutants", + "pem", + "proptest", + "prost-types", + "rand 0.10.1", + "rcgen", + "restructed", + "rstest", + "rustls", + "sha2 0.11.0", + "smlang", + "strum 0.28.0", + "subtle", + "test-log", + "thiserror", + "tokio", + "tokio-stream", + "tonic", + "tracing", + "tracing-subscriber", + "x25519-dalek 2.0.1", +] + +[[package]] +name = "arbiter-tokens-registry" +version = "0.1.0" +dependencies = [ + "alloy", +] + +[[package]] +name = "argon2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" +dependencies = [ + "base64ct", + "blake2", + "cpufeatures 0.2.17", + "password-hash", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "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 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[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-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "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-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.6", +] + +[[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.6", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.6", +] + +[[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.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "auto_impl" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "aws-lc-rs" +version = "1.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" +dependencies = [ + "aws-lc-sys", + "untrusted 0.7.1", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "axum" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" +dependencies = [ + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "backtrace-ext" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" +dependencies = [ + "backtrace", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "bb8" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457d7ed3f888dfd2c7af56d4975cade43c622f74bdcddfed6d4352f57acc6310" +dependencies = [ + "futures-util", + "parking_lot", + "portable-atomic", + "tokio", +] + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitcoin-io" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[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-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "blst" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "serde", +] + +[[package]] +name = "c-kzg" +version = "2.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6648ed1e4ea8e8a1a4a2c78e1cda29a3fd500bc622899c340d8525ea9a76b24a" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] + +[[package]] +name = "cc" +version = "1.2.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures 0.2.17", +] + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20 0.9.1", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common 0.1.7", + "inout", + "zeroize", +] + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "const-hex" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531185e432bb31db1ecda541e9e7ab21468d4d844ad7505e0546a49b4945d49b" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "proptest", + "serde_core", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + +[[package]] +name = "const_format" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" +dependencies = [ + "const_format_proc_macros", + "konst", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +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 = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "crypto-common" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +dependencies = [ + "hybrid-array", + "rand_core 0.10.1", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "curve25519-dalek-derive", + "fiat-crypto 0.2.9", + "rustc_version 0.4.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "5.0.0-pre.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335f1947f241137a14106b6f5acc5918a5ede29c9d71d3f2cb1678d5075d9fc3" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "curve25519-dalek-derive", + "fiat-crypto 0.3.0", + "rustc_version 0.4.1", + "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.117", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "serde", + "strsim", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid 0.9.6", + "zeroize", +] + +[[package]] +name = "der" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b" +dependencies = [ + "const-oid 0.10.2", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", + "serde_core", +] + +[[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 = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.1", + "syn 2.0.117", + "unicode-xid", +] + +[[package]] +name = "diesel" +version = "2.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9940fb8467a0a06312218ed384185cb8536aa10d8ec017d0ce7fad2c1bd882d5" +dependencies = [ + "chrono", + "diesel_derives", + "downcast-rs", + "libsqlite3-sys", + "serde_json", + "sqlite-wasm-rs", + "time", + "uuid", +] + +[[package]] +name = "diesel-async" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c20ddcc6737cecdaef3dfecb2796bdfe3002456521189d30be8e4c5a1bc821d" +dependencies = [ + "bb8", + "diesel", + "diesel_migrations", + "futures-core", + "futures-util", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "diesel_derives" +version = "2.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1817b7f4279b947fc4cafddec12b0e5f8727141706561ce3ac94a60bddd1cf5" +dependencies = [ + "diesel_table_macro_syntax", + "dsl_auto_type", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "diesel_migrations" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d0f4a98124ba6d4ca75da535f65984badec16a003b6e2f94a01e31a79490b8" +dependencies = [ + "diesel", + "migrations_internals", + "migrations_macros", +] + +[[package]] +name = "diesel_table_macro_syntax" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe2444076b48641147115697648dc743c2c00b61adade0f01ce67133c7babe8c" +dependencies = [ + "syn 2.0.117", +] + +[[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 0.9.6", + "crypto-common 0.1.7", + "subtle", +] + +[[package]] +name = "digest" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" +dependencies = [ + "block-buffer 0.12.0", + "const-oid 0.10.2", + "crypto-common 0.2.1", + "ctutils", +] + +[[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.117", +] + +[[package]] +name = "downcast-rs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" + +[[package]] +name = "dsl_auto_type" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd122633e4bef06db27737f21d3738fb89c8f6d5360d6d9d7635dda142a7757e" +dependencies = [ + "darling 0.21.3", + "either", + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der 0.7.10", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "serdect", + "signature 2.2.0", + "spki 0.7.3", +] + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "sec1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "enum-ordinalize" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "fastrlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "fiat-crypto" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.6", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +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 = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[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.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasip2", + "wasip3", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "h2" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.14.0", + "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.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", + "serde", + "serde_core", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" + +[[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.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[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.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + +[[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" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" +dependencies = [ + "digest 0.11.2", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hybrid-array" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" +dependencies = [ + "ctutils", + "typenum", + "zeroize", +] + +[[package]] +name = "hyper" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "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 = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[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.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[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.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.0", + "serde", + "serde_core", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "iri-string" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + +[[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.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys", + "log", + "simd_cesu8", + "thiserror", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version 0.4.1", + "simd_cesu8", + "syn 2.0.117", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2 0.10.9", + "signature 2.2.0", +] + +[[package]] +name = "kameo" +version = "0.20.0" +source = "git+https://github.com/hdbg/kameo.git?rev=805b417#805b41783fe90b54827ecad142b422c7a9b69b9a" +dependencies = [ + "downcast-rs", + "dyn-clone", + "futures", + "kameo_macros", + "serde", + "tokio", + "tracing", +] + +[[package]] +name = "kameo_actors" +version = "0.5.0" +source = "git+https://github.com/hdbg/kameo.git?rev=805b417#805b41783fe90b54827ecad142b422c7a9b69b9a" +dependencies = [ + "futures", + "glob", + "kameo", + "thiserror", + "tokio", +] + +[[package]] +name = "kameo_macros" +version = "0.20.0" +source = "git+https://github.com/hdbg/kameo.git?rev=805b417#805b41783fe90b54827ecad142b422c7a9b69b9a" +dependencies = [ + "darling 0.23.0", + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures 0.2.17", +] + +[[package]] +name = "keccak" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", +] + +[[package]] +name = "keccak-asm" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa468878266ad91431012b3e5ef1bf9b170eab22883503a318d46857afa4579a" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "kem" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01737161ba802849cfd486b5bd209d38ba4943494c249a8126005170c7621edd" +dependencies = [ + "crypto-common 0.2.1", + "rand_core 0.10.1", +] + +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libsqlite3-sys" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" +dependencies = [ + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "lru" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" +dependencies = [ + "hashbrown 0.16.1", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memsafe" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f3e199d5e8adf073900f95b635f1192c394a442ed406c16dc7991b74501645" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "backtrace", + "backtrace-ext", + "cfg-if", + "miette-derive", + "owo-colors", + "serde", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "unicode-width 0.1.14", +] + +[[package]] +name = "miette-derive" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "migrations_internals" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c791ecdf977c99f45f23280405d7723727470f6689a5e6dbf513ac547ae10d" +dependencies = [ + "serde", + "toml", +] + +[[package]] +name = "migrations_macros" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36fc5ac76be324cfd2d3f2cf0fdf5d5d3c4f14ed8aaebadb09e304ba42282703" +dependencies = [ + "migrations_internals", + "proc-macro2", + "quote", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "ml-dsa" +version = "0.1.0-rc.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a596bd65985e2b343c3fd6cc4ade15cdd76da66b15936cfbce72ea661cdbb2" +dependencies = [ + "const-oid 0.10.2", + "ctutils", + "hybrid-array", + "module-lattice", + "pkcs8 0.11.0", + "rand_core 0.10.1", + "sha3 0.11.0", + "signature 3.0.0-rc.10", + "zeroize", +] + +[[package]] +name = "ml-kem" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c77d5ff6d755d09a0ef4d4d28c2b7e83658fe83e8c736d55e93d43e380d1cd" +dependencies = [ + "hybrid-array", + "kem", + "module-lattice", + "rand_core 0.10.1", + "sha3 0.11.0", + "zeroize", +] + +[[package]] +name = "module-lattice" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc7c90d33a0dac244570c26461d761ffaeadb3bfc2b17cc625ae2185cafdffae" +dependencies = [ + "ctutils", + "hybrid-array", + "num-traits", + "zeroize", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "mutants" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ac067452ff1aca8c5002111bd6b1c895baee6e45fcbc44e0193aea17be56" + +[[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 = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[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-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + +[[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", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "nybbles" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210" +dependencies = [ + "alloy-rlp", + "cfg-if", + "proptest", + "ruint", + "serde", + "smallvec", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" +dependencies = [ + "asn1-rs", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "owo-colors" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" + +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[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 = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64", + "serde_core", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pest" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap 2.14.0", +] + +[[package]] +name = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.10", + "spki 0.7.3", +] + +[[package]] +name = "pkcs8" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" +dependencies = [ + "der 0.8.0", + "spki 0.8.0", +] + +[[package]] +name = "pkg-config" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures 0.2.17", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[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.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "num-traits", + "rand 0.9.4", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343d3bd7056eda839b03204e68deff7d1b13aba7af2b2fd16890697274262ee7" +dependencies = [ + "heck", + "itertools 0.14.0", + "log", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "pulldown-cmark", + "pulldown-cmark-to-cmark", + "regex", + "syn 2.0.117", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost-types" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" +dependencies = [ + "chrono", + "prost", +] + +[[package]] +name = "pulldown-cmark" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" +dependencies = [ + "bitflags", + "memchr", + "unicase", +] + +[[package]] +name = "pulldown-cmark-to-cmark" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" +dependencies = [ + "pulldown-cmark", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", + "serde", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", + "serde", +] + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20 0.10.0", + "getrandom 0.4.2", + "rand_core 0.10.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_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", + "serde", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.5", +] + +[[package]] +name = "rapidhash" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" +dependencies = [ + "rustversion", +] + +[[package]] +name = "rcgen" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10b99e0098aa4082912d4c649628623db6aba77335e4f4569ff5083a6448b32e" +dependencies = [ + "aws-lc-rs", + "pem", + "rustls-pki-types", + "time", + "x509-parser", + "yasna", + "zeroize", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "reqwest" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" +dependencies = [ + "base64", + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "restructed" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6f6e863d7d9d318699737c043d560dce1ea3cb6f5c78e0a3f0d1f257c73dfc" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "rsqlite-vfs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a1f2315036ef6b1fbacd1972e8ee7688030b0a2121edfc2a6550febd41574d" +dependencies = [ + "hashbrown 0.16.1", + "thiserror", +] + +[[package]] +name = "rstest" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49" +dependencies = [ + "futures-timer", + "futures-util", + "rstest_macros", +] + +[[package]] +name = "rstest_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version 0.4.1", + "syn 2.0.117", + "unicode-ident", +] + +[[package]] +name = "ruint" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0298da754d1395046b0afdc2f20ee76d29a8ae310cd30ffa84ed42acba9cb12a" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "ark-ff 0.5.0", + "bytes", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand 0.8.6", + "rand 0.9.4", + "rlp", + "ruint-macro", + "serde_core", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.28", +] + +[[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 = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[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.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted 0.9.0", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[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.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der 0.7.10", + "generic-array", + "pkcs8 0.10.2", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +dependencies = [ + "bitcoin_hashes", + "rand 0.8.6", + "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 = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "semver-parser" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_with" +version = "3.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.14.0", + "schemars 0.9.0", + "schemars 1.2.1", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" +dependencies = [ + "darling 0.23.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "digest 0.11.2", +] + +[[package]] +name = "sha3" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" +dependencies = [ + "digest 0.10.7", + "keccak 0.1.6", +] + +[[package]] +name = "sha3" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" +dependencies = [ + "digest 0.11.2", + "keccak 0.2.0", +] + +[[package]] +name = "sha3-asm" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cbb88c189d6352cc8ae96a39d19c7ecad8f7330b29461187f2587fdc2988d5" +dependencies = [ + "cc", + "cfg-if", +] + +[[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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[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 = "signature" +version = "3.0.0-rc.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f1880df446116126965eeec169136b2e0251dba37c6223bcc819569550edea3" +dependencies = [ + "digest 0.11.2", + "rand_core 0.10.1", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version 0.4.1", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "smlang" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de84f9f80bbe6272174e2bfdb8cf7ce4815b218038a42161c2f21c1d872c215" +dependencies = [ + "smlang-macros", +] + +[[package]] +name = "smlang-macros" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "231b4425dcc43afc7e18c34e7c6738cd252d42d91d909c948df14107c9ae79f1" +dependencies = [ + "proc-macro2", + "quote", + "string_morph", + "syn 1.0.109", +] + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der 0.7.10", +] + +[[package]] +name = "spki" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f" +dependencies = [ + "base64ct", + "der 0.8.0", +] + +[[package]] +name = "sqlite-wasm-rs" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b2c760607300407ddeaee518acf28c795661b7108c75421303dbefb237d3a36" +dependencies = [ + "cc", + "js-sys", + "rsqlite-vfs", + "wasm-bindgen", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_morph" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183aaf7fa637cc7b5f54c45b8f7cb6e8d73831f9f75a56b6defa5bf8c51d1699" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros 0.27.2", +] + +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros 0.28.0", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "supports-color" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" +dependencies = [ + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91" + +[[package]] +name = "supports-unicode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" + +[[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.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-solidity" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "terminal_size" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" +dependencies = [ + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "test-log" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f46bf474f0a4afebf92f076d54fd5e63423d9438b8c278a3d2ccb0f47f7cdb3" +dependencies = [ + "test-log-macros", + "tracing-subscriber", +] + +[[package]] +name = "test-log-core" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d4d41320b48bc4a211a9021678fcc0c99569b594ea31c93735b8e517102b4c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "test-log-macros" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9beb9249a81e430dffd42400a49019bcf548444f1968ff23080a625de0d4d320" +dependencies = [ + "syn 2.0.117", + "test-log-core", +] + +[[package]] +name = "textwrap" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057" +dependencies = [ + "unicode-linebreak", + "unicode-width 0.2.2", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +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.52.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "tracing", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.9.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +dependencies = [ + "serde_core", + "serde_spanned", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "winnow 0.7.15", +] + +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap 2.14.0", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.2", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.2", +] + +[[package]] +name = "tonic" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fec7c61a0695dc1887c1b53952990f3ad2e3a31453e1f49f10e75424943a93ec" +dependencies = [ + "async-trait", + "axum", + "base64", + "bytes", + "flate2", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "socket2", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", + "zstd", +] + +[[package]] +name = "tonic-build" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1882ac3bf5ef12877d7ed57aad87e75154c11931c2ba7e6cde5e22d63522c734" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tonic-prost" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55376a0bbaa4975a3f10d009ad763d8f4108f067c7c2e74f3001fb49778d309" +dependencies = [ + "bytes", + "prost", + "tonic", +] + +[[package]] +name = "tonic-prost-build" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3144df636917574672e93d0f56d7edec49f90305749c668df5101751bb8f95a" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn 2.0.117", + "tempfile", + "tonic-build", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 2.14.0", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +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.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +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.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "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 = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[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 0.1.7", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", + "serde_derive", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[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 = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[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.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver 1.0.28", +] + +[[package]] +name = "wasmtimer" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b" +dependencies = [ + "futures", + "js-sys", + "parking_lot", + "pin-utils", + "slab", + "wasm-bindgen", +] + +[[package]] +name = "web-sys" +version = "0.3.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" +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 = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +dependencies = [ + "rustls-pki-types", +] + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[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.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[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.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[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 0.52.6", + "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-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[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_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[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_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[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_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[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_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[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_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver 1.0.28", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x-wing" +version = "0.1.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d0d5f4d1f26b9b9e7477af1d3bef960e1d1fb64edab7912fde472a8a8432e" +dependencies = [ + "kem", + "ml-kem", + "rand_core 0.10.1", + "sha3 0.11.0", + "x25519-dalek 3.0.0-pre.6", + "zeroize", +] + +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek 4.1.3", + "rand_core 0.6.4", + "serde", + "zeroize", +] + +[[package]] +name = "x25519-dalek" +version = "3.0.0-pre.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d5d6ff67acd3945b933e592bfa7143db4fcbb2f871754b6b9fbd7847fc5aea" +dependencies = [ + "curve25519-dalek 5.0.0-pre.6", + "rand_core 0.10.1", + "zeroize", +] + +[[package]] +name = "x509-parser" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" +dependencies = [ + "asn1-rs", + "aws-lc-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/server/Cargo.toml b/server/Cargo.toml index cd588a8..f59dcfb 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,171 +1,171 @@ -[workspace] -members = [ - "crates/*", -] -resolver = "3" - - -[workspace.dependencies] -alloy = "2.0.4" -async-trait = "0.1.89" -base64 = "0.22.1" -chrono = { version = "0.4.44", features = ["serde"] } -futures = "0.3.32" -k256 = { version = "0.13.4", features = ["ecdsa", "pkcs8"] } -kameo = {git = "https://github.com/hdbg/kameo.git", rev = "805b417"} -kameo_actors = {git = "https://github.com/hdbg/kameo.git", rev = "805b417"} -hmac = "0.13.0" -miette = { version = "7.6.0", features = ["fancy", "serde"] } -ml-dsa = { version = "0.1.0-rc.9", features = ["zeroize"] } -mutants = "0.0.4" -prost = "0.14.3" -prost-types = { version = "0.14.3", features = ["chrono"] } -rand = "0.10.1" -rcgen = { version = "0.14.7", features = [ "aws_lc_rs", "pem", "x509-parser", "zeroize" ], default-features = false } -rstest = "0.26.1" -rustls = { version = "0.23.40", features = ["aws-lc-rs", "logging", "prefer-post-quantum", "std"], default-features = false } -rustls-pki-types = "1.14.1" -sha2 = "0.11" -smlang = "0.8.0" -thiserror = "2.0.18" -tokio = { version = "1.52.1", features = ["full"] } -tokio-stream = { version = "0.1.18", features = ["full"] } -tonic = { version = "0.14.5", features = [ "deflate", "gzip", "tls-connect-info", "zstd" ] } -tracing = "0.1.44" -x25519-dalek = { version = "2.0.1", features = ["getrandom"] } - -[workspace.lints.rust] -missing_unsafe_on_extern = "deny" -unsafe_attr_outside_unsafe = "deny" -unsafe_op_in_unsafe_fn = "deny" -unstable_features = "deny" - -deprecated_safe_2024 = "warn" -ffi_unwind_calls = "warn" -linker_messages = "warn" - -elided_lifetimes_in_paths = "warn" -explicit_outlives_requirements = "warn" -impl-trait-overcaptures = "warn" -impl-trait-redundant-captures = "warn" -redundant_lifetimes = "warn" -single_use_lifetimes = "warn" -unused_lifetimes = "warn" - -macro_use_extern_crate = "warn" -redundant_imports = "warn" -unused_import_braces = "warn" -unused_macro_rules = "warn" -unused_qualifications = "warn" - -unit_bindings = "warn" - -# missing_docs = "warn" # ENABLE BY THE FIRST MAJOR VERSION!! -unnameable_types = "warn" - -[workspace.lints.clippy] -derive_partial_eq_without_eq = "allow" -future_not_send = "allow" -inconsistent_struct_constructor = "allow" -inline_always = "allow" -missing_errors_doc = "allow" -missing_fields_in_debug = "allow" -missing_panics_doc = "allow" -must_use_candidate = "allow" -needless_pass_by_ref_mut = "allow" -pub_underscore_fields = "allow" -redundant_pub_crate = "allow" -uninhabited_references = "allow" # safe with unsafe_code = "forbid" and standard uninhabited pattern (match *self {}) -too-many-lines = "allow" # this is a very common pattern in server code, and it's not always possible to break it down into smaller modules without hurting readability - -# restriction lints -alloc_instead_of_core = "warn" -allow_attributes_without_reason = "warn" -as_conversions = "warn" -assertions_on_result_states = "warn" -cfg_not_test = "warn" -clone_on_ref_ptr = "warn" -cognitive_complexity = "warn" -create_dir = "warn" -dbg_macro = "warn" -decimal_literal_representation = "warn" -default_union_representation = "warn" -deref_by_slicing = "warn" -disallowed_script_idents = "warn" -doc_include_without_cfg = "warn" -empty_drop = "warn" -empty_enum_variants_with_brackets = "warn" -empty_structs_with_brackets = "warn" -exit = "warn" -filetype_is_file = "warn" -float_arithmetic = "warn" -float_cmp_const = "warn" -fn_to_numeric_cast_any = "warn" -get_unwrap = "warn" -if_then_some_else_none = "warn" -indexing_slicing = "warn" -infinite_loop = "warn" -inline_asm_x86_att_syntax = "warn" -inline_asm_x86_intel_syntax = "warn" -integer_division = "warn" -large_include_file = "warn" -lossy_float_literal = "warn" -map_with_unused_argument_over_ranges = "warn" -mem_forget = "warn" -missing_assert_message = "warn" -mixed_read_write_in_expression = "warn" -modulo_arithmetic = "warn" -multiple_unsafe_ops_per_block = "warn" -mutex_atomic = "warn" -mutex_integer = "warn" -needless_raw_strings = "warn" -non_ascii_literal = "warn" -non_zero_suggestions = "warn" -pathbuf_init_then_push = "warn" -pointer_format = "warn" -precedence_bits = "warn" -pub_without_shorthand = "warn" -rc_buffer = "warn" -rc_mutex = "warn" -redundant_test_prefix = "warn" -redundant_type_annotations = "warn" -ref_patterns = "warn" -renamed_function_params = "warn" -rest_pat_in_fully_bound_structs = "warn" -return_and_then = "warn" -semicolon_inside_block = "warn" -str_to_string = "warn" -string_add = "warn" -string_lit_chars_any = "warn" -string_slice = "warn" -suspicious_xor_used_as_pow = "warn" -try_err = "warn" -undocumented_unsafe_blocks = "warn" -uninlined_format_args = "warn" -unnecessary_safety_comment = "warn" -unnecessary_safety_doc = "warn" -unnecessary_self_imports = "warn" -unneeded_field_pattern = "warn" -unused_result_ok = "warn" -verbose_file_reads = "warn" - -# cargo lints -negative_feature_names = "warn" -redundant_feature_names = "warn" -wildcard_dependencies = "warn" - -# ENABLE BY THE FIRST MAJOR VERSION!! -# todo = "warn" -# unimplemented = "warn" -# panic = "warn" -# panic_in_result_fn = "warn" -# -# cargo_common_metadata = "warn" -# multiple_crate_versions = "warn" # a controversial option since it's really difficult to maintain - -disallowed_methods = "deny" - -nursery = { level = "warn", priority = -1 } -pedantic = { level = "warn", priority = -1 } - -type_repetition_in_bounds = "allow" # sometimes, it's better for readability this way +[workspace] +members = [ + "crates/*", +] +resolver = "3" + + +[workspace.dependencies] +alloy = "2.0.4" +async-trait = "0.1.89" +base64 = "0.22.1" +chrono = { version = "0.4.44", features = ["serde"] } +futures = "0.3.32" +k256 = { version = "0.13.4", features = ["ecdsa", "pkcs8"] } +kameo = {git = "https://github.com/hdbg/kameo.git", rev = "805b417"} +kameo_actors = {git = "https://github.com/hdbg/kameo.git", rev = "805b417"} +hmac = "0.13.0" +miette = { version = "7.6.0", features = ["fancy", "serde"] } +ml-dsa = { version = "0.1.0-rc.9", features = ["zeroize"] } +mutants = "0.0.4" +prost = "0.14.3" +prost-types = { version = "0.14.3", features = ["chrono"] } +rand = "0.10.1" +rcgen = { version = "0.14.7", features = [ "aws_lc_rs", "pem", "x509-parser", "zeroize" ], default-features = false } +rstest = "0.26.1" +rustls = { version = "0.23.40", features = ["aws-lc-rs", "logging", "prefer-post-quantum", "std"], default-features = false } +rustls-pki-types = "1.14.1" +sha2 = "0.11" +smlang = "0.8.0" +thiserror = "2.0.18" +tokio = { version = "1.52.1", features = ["full"] } +tokio-stream = { version = "0.1.18", features = ["full"] } +tonic = { version = "0.14.5", features = [ "deflate", "gzip", "tls-connect-info", "zstd" ] } +tracing = "0.1.44" +x25519-dalek = { version = "2.0.1", features = ["getrandom"] } + +[workspace.lints.rust] +missing_unsafe_on_extern = "deny" +unsafe_attr_outside_unsafe = "deny" +unsafe_op_in_unsafe_fn = "deny" +unstable_features = "deny" + +deprecated_safe_2024 = "warn" +ffi_unwind_calls = "warn" +linker_messages = "warn" + +elided_lifetimes_in_paths = "warn" +explicit_outlives_requirements = "warn" +impl-trait-overcaptures = "warn" +impl-trait-redundant-captures = "warn" +redundant_lifetimes = "warn" +single_use_lifetimes = "warn" +unused_lifetimes = "warn" + +macro_use_extern_crate = "warn" +redundant_imports = "warn" +unused_import_braces = "warn" +unused_macro_rules = "warn" +unused_qualifications = "warn" + +unit_bindings = "warn" + +# missing_docs = "warn" # ENABLE BY THE FIRST MAJOR VERSION!! +unnameable_types = "warn" + +[workspace.lints.clippy] +derive_partial_eq_without_eq = "allow" +future_not_send = "allow" +inconsistent_struct_constructor = "allow" +inline_always = "allow" +missing_errors_doc = "allow" +missing_fields_in_debug = "allow" +missing_panics_doc = "allow" +must_use_candidate = "allow" +needless_pass_by_ref_mut = "allow" +pub_underscore_fields = "allow" +redundant_pub_crate = "allow" +uninhabited_references = "allow" # safe with unsafe_code = "forbid" and standard uninhabited pattern (match *self {}) +too-many-lines = "allow" # this is a very common pattern in server code, and it's not always possible to break it down into smaller modules without hurting readability + +# restriction lints +alloc_instead_of_core = "warn" +allow_attributes_without_reason = "warn" +as_conversions = "warn" +assertions_on_result_states = "warn" +cfg_not_test = "warn" +clone_on_ref_ptr = "warn" +cognitive_complexity = "warn" +create_dir = "warn" +dbg_macro = "warn" +decimal_literal_representation = "warn" +default_union_representation = "warn" +deref_by_slicing = "warn" +disallowed_script_idents = "warn" +doc_include_without_cfg = "warn" +empty_drop = "warn" +empty_enum_variants_with_brackets = "warn" +empty_structs_with_brackets = "warn" +exit = "warn" +filetype_is_file = "warn" +float_arithmetic = "warn" +float_cmp_const = "warn" +fn_to_numeric_cast_any = "warn" +get_unwrap = "warn" +if_then_some_else_none = "warn" +indexing_slicing = "warn" +infinite_loop = "warn" +inline_asm_x86_att_syntax = "warn" +inline_asm_x86_intel_syntax = "warn" +integer_division = "warn" +large_include_file = "warn" +lossy_float_literal = "warn" +map_with_unused_argument_over_ranges = "warn" +mem_forget = "warn" +missing_assert_message = "warn" +mixed_read_write_in_expression = "warn" +modulo_arithmetic = "warn" +multiple_unsafe_ops_per_block = "warn" +mutex_atomic = "warn" +mutex_integer = "warn" +needless_raw_strings = "warn" +non_ascii_literal = "warn" +non_zero_suggestions = "warn" +pathbuf_init_then_push = "warn" +pointer_format = "warn" +precedence_bits = "warn" +pub_without_shorthand = "warn" +rc_buffer = "warn" +rc_mutex = "warn" +redundant_test_prefix = "warn" +redundant_type_annotations = "warn" +ref_patterns = "warn" +renamed_function_params = "warn" +rest_pat_in_fully_bound_structs = "warn" +return_and_then = "warn" +semicolon_inside_block = "warn" +str_to_string = "warn" +string_add = "warn" +string_lit_chars_any = "warn" +string_slice = "warn" +suspicious_xor_used_as_pow = "warn" +try_err = "warn" +undocumented_unsafe_blocks = "warn" +uninlined_format_args = "warn" +unnecessary_safety_comment = "warn" +unnecessary_safety_doc = "warn" +unnecessary_self_imports = "warn" +unneeded_field_pattern = "warn" +unused_result_ok = "warn" +verbose_file_reads = "warn" + +# cargo lints +negative_feature_names = "warn" +redundant_feature_names = "warn" +wildcard_dependencies = "warn" + +# ENABLE BY THE FIRST MAJOR VERSION!! +# todo = "warn" +# unimplemented = "warn" +# panic = "warn" +# panic_in_result_fn = "warn" +# +# cargo_common_metadata = "warn" +# multiple_crate_versions = "warn" # a controversial option since it's really difficult to maintain + +disallowed_methods = "deny" + +nursery = { level = "warn", priority = -1 } +pedantic = { level = "warn", priority = -1 } + +type_repetition_in_bounds = "allow" # sometimes, it's better for readability this way diff --git a/server/clippy.toml b/server/clippy.toml index bed3c74..9f0a02e 100644 --- a/server/clippy.toml +++ b/server/clippy.toml @@ -1,28 +1,28 @@ -disallowed-methods = [ - # RSA decryption is forbidden: the rsa crate has RUSTSEC-2023-0071 (Marvin Attack). - # We only use RSA for Windows Hello (KeyCredentialManager) public-key verification — decryption - # is never required and must not be introduced. - { path = "rsa::RsaPrivateKey::decrypt", reason = "RSA decryption is forbidden (RUSTSEC-2023-0071 Marvin Attack). Only PSS signing/verification is permitted." }, - { path = "rsa::RsaPrivateKey::decrypt_blinded", reason = "RSA decryption is forbidden (RUSTSEC-2023-0071 Marvin Attack). Only PSS signing/verification is permitted." }, - { path = "rsa::traits::Decryptor::decrypt", reason = "RSA decryption is forbidden (RUSTSEC-2023-0071 Marvin Attack). This blocks decrypt() on rsa::{pkcs1v15,oaep}::DecryptingKey." }, - { path = "rsa::traits::RandomizedDecryptor::decrypt_with_rng", reason = "RSA decryption is forbidden (RUSTSEC-2023-0071 Marvin Attack). This blocks decrypt_with_rng() on rsa::{pkcs1v15,oaep}::DecryptingKey." }, -] - -allow-indexing-slicing-in-tests = true -allow-panic-in-tests = true -check-inconsistent-struct-field-initializers = true -suppress-restriction-lint-in-const = true -allow-renamed-params-for = [ - "core::convert::From", - "core::convert::TryFrom", - "core::str::FromStr", - "kameo::actor::Actor", -] - -module-items-ordered-within-groupings = ["UPPER_SNAKE_CASE"] -source-item-ordering = ["enum"] -trait-assoc-item-kinds-order = [ - "const", - "type", - "fn", -] # community tested standard +disallowed-methods = [ + # RSA decryption is forbidden: the rsa crate has RUSTSEC-2023-0071 (Marvin Attack). + # We only use RSA for Windows Hello (KeyCredentialManager) public-key verification — decryption + # is never required and must not be introduced. + { path = "rsa::RsaPrivateKey::decrypt", reason = "RSA decryption is forbidden (RUSTSEC-2023-0071 Marvin Attack). Only PSS signing/verification is permitted." }, + { path = "rsa::RsaPrivateKey::decrypt_blinded", reason = "RSA decryption is forbidden (RUSTSEC-2023-0071 Marvin Attack). Only PSS signing/verification is permitted." }, + { path = "rsa::traits::Decryptor::decrypt", reason = "RSA decryption is forbidden (RUSTSEC-2023-0071 Marvin Attack). This blocks decrypt() on rsa::{pkcs1v15,oaep}::DecryptingKey." }, + { path = "rsa::traits::RandomizedDecryptor::decrypt_with_rng", reason = "RSA decryption is forbidden (RUSTSEC-2023-0071 Marvin Attack). This blocks decrypt_with_rng() on rsa::{pkcs1v15,oaep}::DecryptingKey." }, +] + +allow-indexing-slicing-in-tests = true +allow-panic-in-tests = true +check-inconsistent-struct-field-initializers = true +suppress-restriction-lint-in-const = true +allow-renamed-params-for = [ + "core::convert::From", + "core::convert::TryFrom", + "core::str::FromStr", + "kameo::actor::Actor", +] + +module-items-ordered-within-groupings = ["UPPER_SNAKE_CASE"] +source-item-ordering = ["enum"] +trait-assoc-item-kinds-order = [ + "const", + "type", + "fn", +] # community tested standard diff --git a/server/crates/arbiter-client/Cargo.toml b/server/crates/arbiter-client/Cargo.toml index 9b0e229..5600f2d 100644 --- a/server/crates/arbiter-client/Cargo.toml +++ b/server/crates/arbiter-client/Cargo.toml @@ -1,29 +1,29 @@ -[package] -name = "arbiter-client" -version = "0.1.0" -edition = "2024" -repository = "https://git.markettakers.org/MarketTakers/arbiter" -license = "Apache-2.0" - -[lints] -workspace = true - -[features] -evm = ["dep:alloy"] - -[dependencies] -arbiter-proto.path = "../arbiter-proto" -arbiter-crypto.path = "../arbiter-crypto" -alloy = { workspace = true, optional = true } -tonic.workspace = true -tonic.features = ["tls-aws-lc"] -tokio.workspace = true -tokio-stream.workspace = true -thiserror.workspace = true -http = "1.4.0" -rustls-webpki = { version = "0.103.13", features = ["aws-lc-rs"] } -async-trait.workspace = true -chrono.workspace = true - -[lib] -doctest = false +[package] +name = "arbiter-client" +version = "0.1.0" +edition = "2024" +repository = "https://git.markettakers.org/MarketTakers/arbiter" +license = "Apache-2.0" + +[lints] +workspace = true + +[features] +evm = ["dep:alloy"] + +[dependencies] +arbiter-proto.path = "../arbiter-proto" +arbiter-crypto.path = "../arbiter-crypto" +alloy = { workspace = true, optional = true } +tonic.workspace = true +tonic.features = ["tls-aws-lc"] +tokio.workspace = true +tokio-stream.workspace = true +thiserror.workspace = true +http = "1.4.0" +rustls-webpki = { version = "0.103.13", features = ["aws-lc-rs"] } +async-trait.workspace = true +chrono.workspace = true + +[lib] +doctest = false diff --git a/server/crates/arbiter-client/src/auth.rs b/server/crates/arbiter-client/src/auth.rs index 176cd13..44b0693 100644 --- a/server/crates/arbiter-client/src/auth.rs +++ b/server/crates/arbiter-client/src/auth.rs @@ -1,160 +1,160 @@ -use crate::{ - storage::StorageError, - transport::{ClientTransport, next_request_id}, -}; -use arbiter_crypto::authn::{self, CLIENT_CONTEXT, SigningKey}; -use arbiter_proto::{ - ClientMetadata, - proto::{ - client::{ - ClientRequest, - auth::{ - self as proto_auth, AuthChallenge, AuthChallengeRequest, AuthChallengeSolution, - AuthResult, request::Payload as AuthRequestPayload, - response::Payload as AuthResponsePayload, - }, - client_request::Payload as ClientRequestPayload, - client_response::Payload as ClientResponsePayload, - }, - shared::ClientInfo as ProtoClientInfo, - }, -}; - -use chrono::DateTime; - -#[derive(Debug, thiserror::Error)] -pub enum AuthError { - #[error("Server sent invalid auth challenge")] - InvalidChallenge, - #[error("Client approval denied by Operator")] - ApprovalDenied, - #[error("Auth challenge was not returned by server")] - MissingAuthChallenge, - - #[error("No Operators online to approve client")] - NoOperatorsOnline, - - #[error("Signing key storage error")] - Storage(#[from] StorageError), - - #[error("Unexpected auth response payload")] - UnexpectedAuthResponse, -} - -fn map_auth_result(code: i32) -> AuthError { - match AuthResult::try_from(code).unwrap_or(AuthResult::Unspecified) { - AuthResult::ApprovalDenied => AuthError::ApprovalDenied, - AuthResult::NoOperatorsOnline => AuthError::NoOperatorsOnline, - AuthResult::Unspecified - | AuthResult::Success - | AuthResult::InvalidKey - | AuthResult::InvalidSignature - | AuthResult::Internal => AuthError::UnexpectedAuthResponse, - } -} - -async fn send_auth_challenge_request( - transport: &mut ClientTransport, - metadata: ClientMetadata, - key: &SigningKey, -) -> Result<(), AuthError> { - transport - .send(ClientRequest { - request_id: next_request_id(), - payload: Some(ClientRequestPayload::Auth(proto_auth::Request { - payload: Some(AuthRequestPayload::ChallengeRequest(AuthChallengeRequest { - pubkey: key.public_key().to_bytes(), - client_info: Some(ProtoClientInfo { - name: metadata.name, - description: metadata.description, - version: metadata.version, - }), - })), - })), - }) - .await - .map_err(|_| AuthError::UnexpectedAuthResponse) -} - -async fn receive_auth_challenge( - transport: &mut ClientTransport, -) -> Result { - let response = transport - .recv() - .await - .map_err(|_| AuthError::MissingAuthChallenge)?; - - let payload = response.payload.ok_or(AuthError::MissingAuthChallenge)?; - match payload { - ClientResponsePayload::Auth(response) => match response.payload { - Some(AuthResponsePayload::Challenge(challenge)) => Ok(challenge), - Some(AuthResponsePayload::Result(result)) => Err(map_auth_result(result)), - None => Err(AuthError::MissingAuthChallenge), - }, - _ => Err(AuthError::UnexpectedAuthResponse), - } -} - -async fn send_auth_challenge_solution( - transport: &mut ClientTransport, - key: &SigningKey, - challenge: AuthChallenge, -) -> Result<(), AuthError> { - let timestamp = DateTime::from_timestamp_nanos(challenge.timestamp_nanos.cast_signed()); - let challenge = authn::AuthChallenge { - nonce: *challenge - .random - .as_array() - .ok_or(AuthError::InvalidChallenge)?, - timestamp, - }; - let challenge_payload: Vec = challenge.format(); - let signature = key - .sign_message(&challenge_payload, CLIENT_CONTEXT) - .map_err(|_| AuthError::UnexpectedAuthResponse)? - .to_bytes(); - - transport - .send(ClientRequest { - request_id: next_request_id(), - payload: Some(ClientRequestPayload::Auth(proto_auth::Request { - payload: Some(AuthRequestPayload::ChallengeSolution( - AuthChallengeSolution { signature }, - )), - })), - }) - .await - .map_err(|_| AuthError::UnexpectedAuthResponse) -} - -async fn receive_auth_confirmation(transport: &mut ClientTransport) -> Result<(), AuthError> { - let response = transport - .recv() - .await - .map_err(|_| AuthError::UnexpectedAuthResponse)?; - - let payload = response.payload.ok_or(AuthError::UnexpectedAuthResponse)?; - match payload { - ClientResponsePayload::Auth(response) => match response.payload { - Some(AuthResponsePayload::Result(result)) - if AuthResult::try_from(result).ok() == Some(AuthResult::Success) => - { - Ok(()) - } - Some(AuthResponsePayload::Result(result)) => Err(map_auth_result(result)), - _ => Err(AuthError::UnexpectedAuthResponse), - }, - _ => Err(AuthError::UnexpectedAuthResponse), - } -} - -pub async fn authenticate( - transport: &mut ClientTransport, - metadata: ClientMetadata, - key: &SigningKey, -) -> Result<(), AuthError> { - send_auth_challenge_request(transport, metadata, key).await?; - let challenge = receive_auth_challenge(transport).await?; - send_auth_challenge_solution(transport, key, challenge).await?; - receive_auth_confirmation(transport).await -} +use crate::{ + storage::StorageError, + transport::{ClientTransport, next_request_id}, +}; +use arbiter_crypto::authn::{self, CLIENT_CONTEXT, SigningKey}; +use arbiter_proto::{ + ClientMetadata, + proto::{ + client::{ + ClientRequest, + auth::{ + self as proto_auth, AuthChallenge, AuthChallengeRequest, AuthChallengeSolution, + AuthResult, request::Payload as AuthRequestPayload, + response::Payload as AuthResponsePayload, + }, + client_request::Payload as ClientRequestPayload, + client_response::Payload as ClientResponsePayload, + }, + shared::ClientInfo as ProtoClientInfo, + }, +}; + +use chrono::DateTime; + +#[derive(Debug, thiserror::Error)] +pub enum AuthError { + #[error("Server sent invalid auth challenge")] + InvalidChallenge, + #[error("Client approval denied by Operator")] + ApprovalDenied, + #[error("Auth challenge was not returned by server")] + MissingAuthChallenge, + + #[error("No Operators online to approve client")] + NoOperatorsOnline, + + #[error("Signing key storage error")] + Storage(#[from] StorageError), + + #[error("Unexpected auth response payload")] + UnexpectedAuthResponse, +} + +fn map_auth_result(code: i32) -> AuthError { + match AuthResult::try_from(code).unwrap_or(AuthResult::Unspecified) { + AuthResult::ApprovalDenied => AuthError::ApprovalDenied, + AuthResult::NoOperatorsOnline => AuthError::NoOperatorsOnline, + AuthResult::Unspecified + | AuthResult::Success + | AuthResult::InvalidKey + | AuthResult::InvalidSignature + | AuthResult::Internal => AuthError::UnexpectedAuthResponse, + } +} + +async fn send_auth_challenge_request( + transport: &mut ClientTransport, + metadata: ClientMetadata, + key: &SigningKey, +) -> Result<(), AuthError> { + transport + .send(ClientRequest { + request_id: next_request_id(), + payload: Some(ClientRequestPayload::Auth(proto_auth::Request { + payload: Some(AuthRequestPayload::ChallengeRequest(AuthChallengeRequest { + pubkey: key.public_key().to_bytes(), + client_info: Some(ProtoClientInfo { + name: metadata.name, + description: metadata.description, + version: metadata.version, + }), + })), + })), + }) + .await + .map_err(|_| AuthError::UnexpectedAuthResponse) +} + +async fn receive_auth_challenge( + transport: &mut ClientTransport, +) -> Result { + let response = transport + .recv() + .await + .map_err(|_| AuthError::MissingAuthChallenge)?; + + let payload = response.payload.ok_or(AuthError::MissingAuthChallenge)?; + match payload { + ClientResponsePayload::Auth(response) => match response.payload { + Some(AuthResponsePayload::Challenge(challenge)) => Ok(challenge), + Some(AuthResponsePayload::Result(result)) => Err(map_auth_result(result)), + None => Err(AuthError::MissingAuthChallenge), + }, + _ => Err(AuthError::UnexpectedAuthResponse), + } +} + +async fn send_auth_challenge_solution( + transport: &mut ClientTransport, + key: &SigningKey, + challenge: AuthChallenge, +) -> Result<(), AuthError> { + let timestamp = DateTime::from_timestamp_nanos(challenge.timestamp_nanos.cast_signed()); + let challenge = authn::AuthChallenge { + nonce: *challenge + .random + .as_array() + .ok_or(AuthError::InvalidChallenge)?, + timestamp, + }; + let challenge_payload: Vec = challenge.format(); + let signature = key + .sign_message(&challenge_payload, CLIENT_CONTEXT) + .map_err(|_| AuthError::UnexpectedAuthResponse)? + .to_bytes(); + + transport + .send(ClientRequest { + request_id: next_request_id(), + payload: Some(ClientRequestPayload::Auth(proto_auth::Request { + payload: Some(AuthRequestPayload::ChallengeSolution( + AuthChallengeSolution { signature }, + )), + })), + }) + .await + .map_err(|_| AuthError::UnexpectedAuthResponse) +} + +async fn receive_auth_confirmation(transport: &mut ClientTransport) -> Result<(), AuthError> { + let response = transport + .recv() + .await + .map_err(|_| AuthError::UnexpectedAuthResponse)?; + + let payload = response.payload.ok_or(AuthError::UnexpectedAuthResponse)?; + match payload { + ClientResponsePayload::Auth(response) => match response.payload { + Some(AuthResponsePayload::Result(result)) + if AuthResult::try_from(result).ok() == Some(AuthResult::Success) => + { + Ok(()) + } + Some(AuthResponsePayload::Result(result)) => Err(map_auth_result(result)), + _ => Err(AuthError::UnexpectedAuthResponse), + }, + _ => Err(AuthError::UnexpectedAuthResponse), + } +} + +pub async fn authenticate( + transport: &mut ClientTransport, + metadata: ClientMetadata, + key: &SigningKey, +) -> Result<(), AuthError> { + send_auth_challenge_request(transport, metadata, key).await?; + let challenge = receive_auth_challenge(transport).await?; + send_auth_challenge_solution(transport, key, challenge).await?; + receive_auth_confirmation(transport).await +} diff --git a/server/crates/arbiter-client/src/bin/test_connect.rs b/server/crates/arbiter-client/src/bin/test_connect.rs index 618a449..ba956d0 100644 --- a/server/crates/arbiter-client/src/bin/test_connect.rs +++ b/server/crates/arbiter-client/src/bin/test_connect.rs @@ -1,44 +1,44 @@ -use arbiter_client::ArbiterClient; -use arbiter_proto::{ClientMetadata, url::ArbiterUrl}; - -use std::io::{self, Write}; - -#[tokio::main] -async fn main() { - println!("Testing connection to Arbiter server..."); - print!("Enter ArbiterUrl: "); - let _ = io::stdout().flush(); - - let mut input = String::new(); - if let Err(err) = io::stdin().read_line(&mut input) { - eprintln!("Failed to read input: {err}"); - return; - } - - let input = input.trim(); - if input.is_empty() { - eprintln!("ArbiterUrl cannot be empty"); - return; - } - - let url = match ArbiterUrl::try_from(input) { - Ok(url) => url, - Err(err) => { - eprintln!("Invalid ArbiterUrl: {err}"); - return; - } - }; - - println!("{url:#?}"); - - let metadata = ClientMetadata { - name: "arbiter-client test_connect".to_owned(), - description: Some("Manual connection smoke test".to_owned()), - version: Some(env!("CARGO_PKG_VERSION").to_owned()), - }; - - match ArbiterClient::connect(url, metadata).await { - Ok(_) => println!("Connected and authenticated successfully."), - Err(err) => eprintln!("Failed to connect: {err:#?}"), - } -} +use arbiter_client::ArbiterClient; +use arbiter_proto::{ClientMetadata, url::ArbiterUrl}; + +use std::io::{self, Write}; + +#[tokio::main] +async fn main() { + println!("Testing connection to Arbiter server..."); + print!("Enter ArbiterUrl: "); + let _ = io::stdout().flush(); + + let mut input = String::new(); + if let Err(err) = io::stdin().read_line(&mut input) { + eprintln!("Failed to read input: {err}"); + return; + } + + let input = input.trim(); + if input.is_empty() { + eprintln!("ArbiterUrl cannot be empty"); + return; + } + + let url = match ArbiterUrl::try_from(input) { + Ok(url) => url, + Err(err) => { + eprintln!("Invalid ArbiterUrl: {err}"); + return; + } + }; + + println!("{url:#?}"); + + let metadata = ClientMetadata { + name: "arbiter-client test_connect".to_owned(), + description: Some("Manual connection smoke test".to_owned()), + version: Some(env!("CARGO_PKG_VERSION").to_owned()), + }; + + match ArbiterClient::connect(url, metadata).await { + Ok(_) => println!("Connected and authenticated successfully."), + Err(err) => eprintln!("Failed to connect: {err:#?}"), + } +} diff --git a/server/crates/arbiter-client/src/client.rs b/server/crates/arbiter-client/src/client.rs index 7269772..fb8cf6a 100644 --- a/server/crates/arbiter-client/src/client.rs +++ b/server/crates/arbiter-client/src/client.rs @@ -1,101 +1,101 @@ -#[cfg(feature = "evm")] -use crate::wallets::evm::ArbiterEvmWallet; -use crate::{ - StorageError, - auth::{AuthError, authenticate}, - storage::{FileSigningKeyStorage, SigningKeyStorage}, - transport::{BUFFER_LENGTH, ClientTransport}, -}; -use arbiter_crypto::authn::SigningKey; -use arbiter_proto::{ - ClientMetadata, proto::arbiter_service_client::ArbiterServiceClient, url::ArbiterUrl, -}; - -use std::sync::Arc; -use tokio::sync::{Mutex, mpsc}; -use tokio_stream::wrappers::ReceiverStream; -use tonic::transport::ClientTlsConfig; - -#[derive(Debug, thiserror::Error)] -pub enum ArbiterClientError { - #[error("Authentication error")] - Authentication(#[from] AuthError), - - #[error("Could not establish connection")] - Connection(#[from] tonic::transport::Error), - - #[error("gRPC error")] - Grpc(#[from] tonic::Status), - - #[error("Invalid CA certificate")] - InvalidCaCert(#[from] webpki::Error), - - #[error("Invalid server URI")] - InvalidUri(#[from] http::uri::InvalidUri), - - #[error("Storage error")] - Storage(#[from] StorageError), -} - -pub struct ArbiterClient { - #[expect( - dead_code, - reason = "transport will be used in future methods for sending requests and receiving responses" - )] - transport: Arc>, -} - -impl ArbiterClient { - pub async fn connect( - url: ArbiterUrl, - metadata: ClientMetadata, - ) -> Result { - let storage = FileSigningKeyStorage::from_default_location()?; - Self::connect_with_storage(url, metadata, &storage).await - } - - pub async fn connect_with_storage( - url: ArbiterUrl, - metadata: ClientMetadata, - storage: &S, - ) -> Result { - let key = storage.load_or_create()?; - Self::connect_with_key(url, metadata, key).await - } - - pub async fn connect_with_key( - url: ArbiterUrl, - metadata: ClientMetadata, - key: SigningKey, - ) -> Result { - let anchor = webpki::anchor_from_trusted_cert(&url.ca_cert)?.to_owned(); - let tls = ClientTlsConfig::new().trust_anchor(anchor); - - let channel = - tonic::transport::Channel::from_shared(format!("https://{}:{}", url.host, url.port))? - .tls_config(tls)? - .connect() - .await?; - - let mut client = ArbiterServiceClient::new(channel); - let (tx, rx) = mpsc::channel(BUFFER_LENGTH); - let response_stream = client.client(ReceiverStream::new(rx)).await?.into_inner(); - - let mut transport = ClientTransport { - sender: tx, - receiver: response_stream, - }; - - authenticate(&mut transport, metadata, &key).await?; - - Ok(Self { - transport: Arc::new(Mutex::new(transport)), - }) - } - - #[cfg(feature = "evm")] - #[expect(clippy::unused_async, reason = "false positive")] - pub async fn evm_wallets(&self) -> Result, ArbiterClientError> { - todo!("fetch EVM wallet list from server") - } -} +#[cfg(feature = "evm")] +use crate::wallets::evm::ArbiterEvmWallet; +use crate::{ + StorageError, + auth::{AuthError, authenticate}, + storage::{FileSigningKeyStorage, SigningKeyStorage}, + transport::{BUFFER_LENGTH, ClientTransport}, +}; +use arbiter_crypto::authn::SigningKey; +use arbiter_proto::{ + ClientMetadata, proto::arbiter_service_client::ArbiterServiceClient, url::ArbiterUrl, +}; + +use std::sync::Arc; +use tokio::sync::{Mutex, mpsc}; +use tokio_stream::wrappers::ReceiverStream; +use tonic::transport::ClientTlsConfig; + +#[derive(Debug, thiserror::Error)] +pub enum ArbiterClientError { + #[error("Authentication error")] + Authentication(#[from] AuthError), + + #[error("Could not establish connection")] + Connection(#[from] tonic::transport::Error), + + #[error("gRPC error")] + Grpc(#[from] tonic::Status), + + #[error("Invalid CA certificate")] + InvalidCaCert(#[from] webpki::Error), + + #[error("Invalid server URI")] + InvalidUri(#[from] http::uri::InvalidUri), + + #[error("Storage error")] + Storage(#[from] StorageError), +} + +pub struct ArbiterClient { + #[expect( + dead_code, + reason = "transport will be used in future methods for sending requests and receiving responses" + )] + transport: Arc>, +} + +impl ArbiterClient { + pub async fn connect( + url: ArbiterUrl, + metadata: ClientMetadata, + ) -> Result { + let storage = FileSigningKeyStorage::from_default_location()?; + Self::connect_with_storage(url, metadata, &storage).await + } + + pub async fn connect_with_storage( + url: ArbiterUrl, + metadata: ClientMetadata, + storage: &S, + ) -> Result { + let key = storage.load_or_create()?; + Self::connect_with_key(url, metadata, key).await + } + + pub async fn connect_with_key( + url: ArbiterUrl, + metadata: ClientMetadata, + key: SigningKey, + ) -> Result { + let anchor = webpki::anchor_from_trusted_cert(&url.ca_cert)?.to_owned(); + let tls = ClientTlsConfig::new().trust_anchor(anchor); + + let channel = + tonic::transport::Channel::from_shared(format!("https://{}:{}", url.host, url.port))? + .tls_config(tls)? + .connect() + .await?; + + let mut client = ArbiterServiceClient::new(channel); + let (tx, rx) = mpsc::channel(BUFFER_LENGTH); + let response_stream = client.client(ReceiverStream::new(rx)).await?.into_inner(); + + let mut transport = ClientTransport { + sender: tx, + receiver: response_stream, + }; + + authenticate(&mut transport, metadata, &key).await?; + + Ok(Self { + transport: Arc::new(Mutex::new(transport)), + }) + } + + #[cfg(feature = "evm")] + #[expect(clippy::unused_async, reason = "false positive")] + pub async fn evm_wallets(&self) -> Result, ArbiterClientError> { + todo!("fetch EVM wallet list from server") + } +} diff --git a/server/crates/arbiter-client/src/lib.rs b/server/crates/arbiter-client/src/lib.rs index 54071ab..8e1e047 100644 --- a/server/crates/arbiter-client/src/lib.rs +++ b/server/crates/arbiter-client/src/lib.rs @@ -1,12 +1,12 @@ -mod auth; -mod client; -mod storage; -mod transport; -pub mod wallets; - -pub use auth::AuthError; -pub use client::{ArbiterClient, ArbiterClientError}; -pub use storage::{FileSigningKeyStorage, SigningKeyStorage, StorageError}; - -#[cfg(feature = "evm")] -pub use wallets::evm::{ArbiterEvmSignTransactionError, ArbiterEvmWallet}; +mod auth; +mod client; +mod storage; +mod transport; +pub mod wallets; + +pub use auth::AuthError; +pub use client::{ArbiterClient, ArbiterClientError}; +pub use storage::{FileSigningKeyStorage, SigningKeyStorage, StorageError}; + +#[cfg(feature = "evm")] +pub use wallets::evm::{ArbiterEvmSignTransactionError, ArbiterEvmWallet}; diff --git a/server/crates/arbiter-client/src/storage.rs b/server/crates/arbiter-client/src/storage.rs index 69d80c2..321b111 100644 --- a/server/crates/arbiter-client/src/storage.rs +++ b/server/crates/arbiter-client/src/storage.rs @@ -1,134 +1,134 @@ -use arbiter_crypto::authn::SigningKey; -use arbiter_proto::home_path; - -use std::path::{Path, PathBuf}; - -#[derive(Debug, thiserror::Error)] -pub enum StorageError { - #[error("Invalid signing key length in storage: expected {expected} bytes, got {actual} bytes")] - InvalidKeyLength { expected: usize, actual: usize }, - - #[error("I/O error")] - Io(#[from] std::io::Error), -} - -pub trait SigningKeyStorage { - fn load_or_create(&self) -> Result; -} - -#[derive(Debug, Clone)] -pub struct FileSigningKeyStorage { - path: PathBuf, -} - -impl FileSigningKeyStorage { - pub const DEFAULT_FILE_NAME: &str = "sdk_client_ml_dsa.key"; - - pub fn new(path: impl Into) -> Self { - Self { path: path.into() } - } - - pub fn from_default_location() -> Result { - Ok(Self::new(home_path()?.join(Self::DEFAULT_FILE_NAME))) - } - - fn read_key(path: &Path) -> Result { - let bytes = std::fs::read(path)?; - let raw: [u8; 32] = - bytes - .try_into() - .map_err(|v: Vec| StorageError::InvalidKeyLength { - expected: 32, - actual: v.len(), - })?; - Ok(SigningKey::from_seed(raw)) - } -} - -impl SigningKeyStorage for FileSigningKeyStorage { - fn load_or_create(&self) -> Result { - if let Some(parent) = self.path.parent() { - std::fs::create_dir_all(parent)?; - } - - if self.path.exists() { - return Self::read_key(&self.path); - } - - let key = SigningKey::generate(); - let raw_key = key.to_seed(); - - // Use create_new to prevent accidental overwrite if another process creates the key first. - match std::fs::OpenOptions::new() - .create_new(true) - .write(true) - .open(&self.path) - { - Ok(mut file) => { - use std::io::Write as _; - file.write_all(&raw_key)?; - Ok(key) - } - Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => { - Self::read_key(&self.path) - } - Err(err) => Err(StorageError::Io(err)), - } - } -} - -#[cfg(test)] -mod tests { - use super::{FileSigningKeyStorage, SigningKeyStorage, StorageError}; - - fn unique_temp_key_path() -> std::path::PathBuf { - let nanos = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .expect("clock should be after unix epoch") - .as_nanos(); - std::env::temp_dir().join(format!( - "arbiter-client-key-{}-{}.bin", - std::process::id(), - nanos - )) - } - - #[test] - fn file_storage_creates_and_reuses_key() { - let path = unique_temp_key_path(); - let storage = FileSigningKeyStorage::new(path.clone()); - - let key_a = storage - .load_or_create() - .expect("first load_or_create should create key"); - let key_b = storage - .load_or_create() - .expect("second load_or_create should read same key"); - - assert_eq!(key_a.to_seed(), key_b.to_seed()); - assert!(path.exists()); - - std::fs::remove_file(path).expect("temp key file should be removable"); - } - - #[test] - fn file_storage_rejects_invalid_key_length() { - let path = unique_temp_key_path(); - std::fs::write(&path, [42u8; 31]).expect("should write invalid key file"); - let storage = FileSigningKeyStorage::new(path.clone()); - - let err = storage - .load_or_create() - .expect_err("storage should reject non-32-byte key file"); - - match err { - StorageError::InvalidKeyLength { expected, actual } => { - assert_eq!(expected, 32); - assert_eq!(actual, 31); - } - other @ StorageError::Io(_) => panic!("unexpected error: {other:?}"), - } - - std::fs::remove_file(path).expect("temp key file should be removable"); - } -} +use arbiter_crypto::authn::SigningKey; +use arbiter_proto::home_path; + +use std::path::{Path, PathBuf}; + +#[derive(Debug, thiserror::Error)] +pub enum StorageError { + #[error("Invalid signing key length in storage: expected {expected} bytes, got {actual} bytes")] + InvalidKeyLength { expected: usize, actual: usize }, + + #[error("I/O error")] + Io(#[from] std::io::Error), +} + +pub trait SigningKeyStorage { + fn load_or_create(&self) -> Result; +} + +#[derive(Debug, Clone)] +pub struct FileSigningKeyStorage { + path: PathBuf, +} + +impl FileSigningKeyStorage { + pub const DEFAULT_FILE_NAME: &str = "sdk_client_ml_dsa.key"; + + pub fn new(path: impl Into) -> Self { + Self { path: path.into() } + } + + pub fn from_default_location() -> Result { + Ok(Self::new(home_path()?.join(Self::DEFAULT_FILE_NAME))) + } + + fn read_key(path: &Path) -> Result { + let bytes = std::fs::read(path)?; + let raw: [u8; 32] = + bytes + .try_into() + .map_err(|v: Vec| StorageError::InvalidKeyLength { + expected: 32, + actual: v.len(), + })?; + Ok(SigningKey::from_seed(raw)) + } +} + +impl SigningKeyStorage for FileSigningKeyStorage { + fn load_or_create(&self) -> Result { + if let Some(parent) = self.path.parent() { + std::fs::create_dir_all(parent)?; + } + + if self.path.exists() { + return Self::read_key(&self.path); + } + + let key = SigningKey::generate(); + let raw_key = key.to_seed(); + + // Use create_new to prevent accidental overwrite if another process creates the key first. + match std::fs::OpenOptions::new() + .create_new(true) + .write(true) + .open(&self.path) + { + Ok(mut file) => { + use std::io::Write as _; + file.write_all(&raw_key)?; + Ok(key) + } + Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => { + Self::read_key(&self.path) + } + Err(err) => Err(StorageError::Io(err)), + } + } +} + +#[cfg(test)] +mod tests { + use super::{FileSigningKeyStorage, SigningKeyStorage, StorageError}; + + fn unique_temp_key_path() -> std::path::PathBuf { + let nanos = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("clock should be after unix epoch") + .as_nanos(); + std::env::temp_dir().join(format!( + "arbiter-client-key-{}-{}.bin", + std::process::id(), + nanos + )) + } + + #[test] + fn file_storage_creates_and_reuses_key() { + let path = unique_temp_key_path(); + let storage = FileSigningKeyStorage::new(path.clone()); + + let key_a = storage + .load_or_create() + .expect("first load_or_create should create key"); + let key_b = storage + .load_or_create() + .expect("second load_or_create should read same key"); + + assert_eq!(key_a.to_seed(), key_b.to_seed()); + assert!(path.exists()); + + std::fs::remove_file(path).expect("temp key file should be removable"); + } + + #[test] + fn file_storage_rejects_invalid_key_length() { + let path = unique_temp_key_path(); + std::fs::write(&path, [42u8; 31]).expect("should write invalid key file"); + let storage = FileSigningKeyStorage::new(path.clone()); + + let err = storage + .load_or_create() + .expect_err("storage should reject non-32-byte key file"); + + match err { + StorageError::InvalidKeyLength { expected, actual } => { + assert_eq!(expected, 32); + assert_eq!(actual, 31); + } + other @ StorageError::Io(_) => panic!("unexpected error: {other:?}"), + } + + std::fs::remove_file(path).expect("temp key file should be removable"); + } +} diff --git a/server/crates/arbiter-client/src/transport.rs b/server/crates/arbiter-client/src/transport.rs index 0e1e44e..7ab15c1 100644 --- a/server/crates/arbiter-client/src/transport.rs +++ b/server/crates/arbiter-client/src/transport.rs @@ -1,41 +1,41 @@ -use arbiter_proto::proto::client::{ClientRequest, ClientResponse}; - -use std::sync::atomic::{AtomicI32, Ordering}; -use tokio::sync::mpsc; - -pub const BUFFER_LENGTH: usize = 16; -static NEXT_REQUEST_ID: AtomicI32 = AtomicI32::new(1); - -pub fn next_request_id() -> i32 { - NEXT_REQUEST_ID.fetch_add(1, Ordering::Relaxed) -} - -#[derive(Debug, thiserror::Error)] -pub enum ClientSignError { - #[error("Transport channel closed")] - ChannelClosed, - - #[error("Connection closed by server")] - ConnectionClosed, -} - -pub struct ClientTransport { - pub(crate) sender: mpsc::Sender, - pub(crate) receiver: tonic::Streaming, -} - -impl ClientTransport { - pub(crate) async fn send(&mut self, request: ClientRequest) -> Result<(), ClientSignError> { - self.sender - .send(request) - .await - .map_err(|_| ClientSignError::ChannelClosed) - } - - pub(crate) async fn recv(&mut self) -> Result { - match self.receiver.message().await { - Ok(Some(resp)) => Ok(resp), - Ok(None) | Err(_) => Err(ClientSignError::ConnectionClosed), - } - } -} +use arbiter_proto::proto::client::{ClientRequest, ClientResponse}; + +use std::sync::atomic::{AtomicI32, Ordering}; +use tokio::sync::mpsc; + +pub const BUFFER_LENGTH: usize = 16; +static NEXT_REQUEST_ID: AtomicI32 = AtomicI32::new(1); + +pub fn next_request_id() -> i32 { + NEXT_REQUEST_ID.fetch_add(1, Ordering::Relaxed) +} + +#[derive(Debug, thiserror::Error)] +pub enum ClientSignError { + #[error("Transport channel closed")] + ChannelClosed, + + #[error("Connection closed by server")] + ConnectionClosed, +} + +pub struct ClientTransport { + pub(crate) sender: mpsc::Sender, + pub(crate) receiver: tonic::Streaming, +} + +impl ClientTransport { + pub(crate) async fn send(&mut self, request: ClientRequest) -> Result<(), ClientSignError> { + self.sender + .send(request) + .await + .map_err(|_| ClientSignError::ChannelClosed) + } + + pub(crate) async fn recv(&mut self) -> Result { + match self.receiver.message().await { + Ok(Some(resp)) => Ok(resp), + Ok(None) | Err(_) => Err(ClientSignError::ConnectionClosed), + } + } +} diff --git a/server/crates/arbiter-client/src/wallets/evm.rs b/server/crates/arbiter-client/src/wallets/evm.rs index 0093715..e9f2b17 100644 --- a/server/crates/arbiter-client/src/wallets/evm.rs +++ b/server/crates/arbiter-client/src/wallets/evm.rs @@ -1,197 +1,197 @@ -use crate::transport::{ClientTransport, next_request_id}; -use arbiter_proto::proto::{ - client::{ - ClientRequest, - client_request::Payload as ClientRequestPayload, - client_response::Payload as ClientResponsePayload, - evm::{ - self as proto_evm, request::Payload as EvmRequestPayload, - response::Payload as EvmResponsePayload, - }, - }, - evm::{ - EvmSignTransactionRequest, - evm_sign_transaction_response::Result as EvmSignTransactionResult, - }, - shared::evm::TransactionEvalError, -}; - -use alloy::{ - consensus::SignableTransaction, - network::TxSigner, - primitives::{Address, B256, ChainId, Signature}, - signers::{Error, Result, Signer}, -}; -use async_trait::async_trait; -use std::sync::Arc; -use tokio::sync::Mutex; - -/// A typed error payload returned by [`ArbiterEvmWallet`] transaction signing. -/// -/// This is wrapped into `alloy::signers::Error::Other`, so consumers can downcast by [`TryFrom`] and -/// interpret the concrete policy evaluation failure instead of parsing strings. -#[derive(Debug, thiserror::Error)] -#[non_exhaustive] -pub enum ArbiterEvmSignTransactionError { - #[error("transaction rejected by policy: {0:?}")] - PolicyEval(TransactionEvalError), -} - -impl<'a> TryFrom<&'a Error> for &'a ArbiterEvmSignTransactionError { - type Error = (); - - fn try_from(value: &'a Error) -> Result { - if let Error::Other(inner) = value - && let Some(eval_error) = inner.downcast_ref() - { - Ok(eval_error) - } else { - Err(()) - } - } -} - -pub struct ArbiterEvmWallet { - transport: Arc>, - address: Address, - chain_id: Option, -} - -impl ArbiterEvmWallet { - #[expect( - dead_code, - reason = "new will be used in future methods for creating wallets with different parameters" - )] - pub(crate) const fn new(transport: Arc>, address: Address) -> Self { - Self { - transport, - address, - chain_id: None, - } - } - - pub const fn address(&self) -> Address { - self.address - } - - #[must_use] - pub const fn with_chain_id(mut self, chain_id: ChainId) -> Self { - self.chain_id = Some(chain_id); - self - } - - fn validate_chain_id(&self, tx: &mut dyn SignableTransaction) -> Result<()> { - if let Some(chain_id) = self.chain_id - && !tx.set_chain_id_checked(chain_id) - { - return Err(Error::TransactionChainIdMismatch { - signer: chain_id, - tx: tx.chain_id().unwrap(), - }); - } - - Ok(()) - } -} - -#[async_trait] -impl Signer for ArbiterEvmWallet { - async fn sign_hash(&self, _hash: &B256) -> Result { - Err(Error::other( - "hash-only signing is not supported for ArbiterEvmWallet; use transaction signing", - )) - } - - fn address(&self) -> Address { - self.address - } - - fn chain_id(&self) -> Option { - self.chain_id - } - - fn set_chain_id(&mut self, chain_id: Option) { - self.chain_id = chain_id; - } -} - -#[async_trait] -impl TxSigner for ArbiterEvmWallet { - fn address(&self) -> Address { - self.address - } - - async fn sign_transaction( - &self, - tx: &mut dyn SignableTransaction, - ) -> Result { - self.validate_chain_id(tx)?; - - let mut transport = self.transport.lock().await; - let request_id = next_request_id(); - let rlp_transaction = tx.encoded_for_signing(); - - transport - .send(ClientRequest { - request_id, - payload: Some(ClientRequestPayload::Evm(proto_evm::Request { - payload: Some(EvmRequestPayload::SignTransaction( - EvmSignTransactionRequest { - wallet_address: self.address.to_vec(), - rlp_transaction, - }, - )), - })), - }) - .await - .map_err(|_| Error::other("failed to send evm sign transaction request"))?; - - let response = transport - .recv() - .await - .map_err(|_| Error::other("failed to receive evm sign transaction response"))?; - drop(transport); - - if response.request_id != Some(request_id) { - return Err(Error::other( - "received mismatched response id for evm sign transaction", - )); - } - - let payload = response - .payload - .ok_or_else(|| Error::other("missing evm sign transaction response payload"))?; - - let ClientResponsePayload::Evm(proto_evm::Response { - payload: Some(payload), - }) = payload - else { - return Err(Error::other( - "unexpected response payload for evm sign transaction request", - )); - }; - - let EvmResponsePayload::SignTransaction(response) = payload else { - return Err(Error::other( - "unexpected evm response payload for sign transaction request", - )); - }; - - let result = response - .result - .ok_or_else(|| Error::other("missing evm sign transaction result"))?; - - match result { - EvmSignTransactionResult::Signature(signature) => { - Signature::try_from(signature.as_slice()) - .map_err(|_| Error::other("invalid signature returned by server")) - } - EvmSignTransactionResult::EvalError(eval_error) => Err(Error::other( - ArbiterEvmSignTransactionError::PolicyEval(eval_error), - )), - EvmSignTransactionResult::Error(code) => Err(Error::other(format!( - "server failed to sign transaction with error code {code}" - ))), - } - } -} +use crate::transport::{ClientTransport, next_request_id}; +use arbiter_proto::proto::{ + client::{ + ClientRequest, + client_request::Payload as ClientRequestPayload, + client_response::Payload as ClientResponsePayload, + evm::{ + self as proto_evm, request::Payload as EvmRequestPayload, + response::Payload as EvmResponsePayload, + }, + }, + evm::{ + EvmSignTransactionRequest, + evm_sign_transaction_response::Result as EvmSignTransactionResult, + }, + shared::evm::TransactionEvalError, +}; + +use alloy::{ + consensus::SignableTransaction, + network::TxSigner, + primitives::{Address, B256, ChainId, Signature}, + signers::{Error, Result, Signer}, +}; +use async_trait::async_trait; +use std::sync::Arc; +use tokio::sync::Mutex; + +/// A typed error payload returned by [`ArbiterEvmWallet`] transaction signing. +/// +/// This is wrapped into `alloy::signers::Error::Other`, so consumers can downcast by [`TryFrom`] and +/// interpret the concrete policy evaluation failure instead of parsing strings. +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum ArbiterEvmSignTransactionError { + #[error("transaction rejected by policy: {0:?}")] + PolicyEval(TransactionEvalError), +} + +impl<'a> TryFrom<&'a Error> for &'a ArbiterEvmSignTransactionError { + type Error = (); + + fn try_from(value: &'a Error) -> Result { + if let Error::Other(inner) = value + && let Some(eval_error) = inner.downcast_ref() + { + Ok(eval_error) + } else { + Err(()) + } + } +} + +pub struct ArbiterEvmWallet { + transport: Arc>, + address: Address, + chain_id: Option, +} + +impl ArbiterEvmWallet { + #[expect( + dead_code, + reason = "new will be used in future methods for creating wallets with different parameters" + )] + pub(crate) const fn new(transport: Arc>, address: Address) -> Self { + Self { + transport, + address, + chain_id: None, + } + } + + pub const fn address(&self) -> Address { + self.address + } + + #[must_use] + pub const fn with_chain_id(mut self, chain_id: ChainId) -> Self { + self.chain_id = Some(chain_id); + self + } + + fn validate_chain_id(&self, tx: &mut dyn SignableTransaction) -> Result<()> { + if let Some(chain_id) = self.chain_id + && !tx.set_chain_id_checked(chain_id) + { + return Err(Error::TransactionChainIdMismatch { + signer: chain_id, + tx: tx.chain_id().unwrap(), + }); + } + + Ok(()) + } +} + +#[async_trait] +impl Signer for ArbiterEvmWallet { + async fn sign_hash(&self, _hash: &B256) -> Result { + Err(Error::other( + "hash-only signing is not supported for ArbiterEvmWallet; use transaction signing", + )) + } + + fn address(&self) -> Address { + self.address + } + + fn chain_id(&self) -> Option { + self.chain_id + } + + fn set_chain_id(&mut self, chain_id: Option) { + self.chain_id = chain_id; + } +} + +#[async_trait] +impl TxSigner for ArbiterEvmWallet { + fn address(&self) -> Address { + self.address + } + + async fn sign_transaction( + &self, + tx: &mut dyn SignableTransaction, + ) -> Result { + self.validate_chain_id(tx)?; + + let mut transport = self.transport.lock().await; + let request_id = next_request_id(); + let rlp_transaction = tx.encoded_for_signing(); + + transport + .send(ClientRequest { + request_id, + payload: Some(ClientRequestPayload::Evm(proto_evm::Request { + payload: Some(EvmRequestPayload::SignTransaction( + EvmSignTransactionRequest { + wallet_address: self.address.to_vec(), + rlp_transaction, + }, + )), + })), + }) + .await + .map_err(|_| Error::other("failed to send evm sign transaction request"))?; + + let response = transport + .recv() + .await + .map_err(|_| Error::other("failed to receive evm sign transaction response"))?; + drop(transport); + + if response.request_id != Some(request_id) { + return Err(Error::other( + "received mismatched response id for evm sign transaction", + )); + } + + let payload = response + .payload + .ok_or_else(|| Error::other("missing evm sign transaction response payload"))?; + + let ClientResponsePayload::Evm(proto_evm::Response { + payload: Some(payload), + }) = payload + else { + return Err(Error::other( + "unexpected response payload for evm sign transaction request", + )); + }; + + let EvmResponsePayload::SignTransaction(response) = payload else { + return Err(Error::other( + "unexpected evm response payload for sign transaction request", + )); + }; + + let result = response + .result + .ok_or_else(|| Error::other("missing evm sign transaction result"))?; + + match result { + EvmSignTransactionResult::Signature(signature) => { + Signature::try_from(signature.as_slice()) + .map_err(|_| Error::other("invalid signature returned by server")) + } + EvmSignTransactionResult::EvalError(eval_error) => Err(Error::other( + ArbiterEvmSignTransactionError::PolicyEval(eval_error), + )), + EvmSignTransactionResult::Error(code) => Err(Error::other(format!( + "server failed to sign transaction with error code {code}" + ))), + } + } +} diff --git a/server/crates/arbiter-client/src/wallets/mod.rs b/server/crates/arbiter-client/src/wallets/mod.rs index b2c917e..54382a3 100644 --- a/server/crates/arbiter-client/src/wallets/mod.rs +++ b/server/crates/arbiter-client/src/wallets/mod.rs @@ -1,2 +1,2 @@ -#[cfg(feature = "evm")] -pub mod evm; +#[cfg(feature = "evm")] +pub mod evm; diff --git a/server/crates/arbiter-crypto/.gitignore b/server/crates/arbiter-crypto/.gitignore index ea8c4bf..0b42d2d 100644 --- a/server/crates/arbiter-crypto/.gitignore +++ b/server/crates/arbiter-crypto/.gitignore @@ -1 +1 @@ -/target +/target diff --git a/server/crates/arbiter-crypto/Cargo.toml b/server/crates/arbiter-crypto/Cargo.toml index 3cbe8ec..a14963b 100644 --- a/server/crates/arbiter-crypto/Cargo.toml +++ b/server/crates/arbiter-crypto/Cargo.toml @@ -1,25 +1,25 @@ -[package] -name = "arbiter-crypto" -version = "0.1.0" -edition = "2024" - -[dependencies] -ml-dsa = {workspace = true, optional = true } -rand = {workspace = true, optional = true} -memsafe = {version = "0.4.0", optional = true} -hmac.workspace = true -alloy.workspace = true -x-wing = { version = "0.1.0-rc.0", features = ["zeroize"] } -chrono.workspace = true -thiserror.workspace = true - -[lints] -workspace = true - -[features] -default = ["authn", "safecell"] -authn = ["dep:ml-dsa", "dep:rand"] -safecell = ["dep:memsafe"] - -[lib] -doctest = false +[package] +name = "arbiter-crypto" +version = "0.1.0" +edition = "2024" + +[dependencies] +ml-dsa = {workspace = true, optional = true } +rand = {workspace = true, optional = true} +memsafe = {version = "0.4.0", optional = true} +hmac.workspace = true +alloy.workspace = true +x-wing = { version = "0.1.0-rc.0", features = ["zeroize"] } +chrono.workspace = true +thiserror.workspace = true + +[lints] +workspace = true + +[features] +default = ["authn", "safecell"] +authn = ["dep:ml-dsa", "dep:rand"] +safecell = ["dep:memsafe"] + +[lib] +doctest = false diff --git a/server/crates/arbiter-crypto/src/authn/mod.rs b/server/crates/arbiter-crypto/src/authn/mod.rs index 3789969..5a76ab3 100644 --- a/server/crates/arbiter-crypto/src/authn/mod.rs +++ b/server/crates/arbiter-crypto/src/authn/mod.rs @@ -1,2 +1,2 @@ -pub mod v1; -pub use v1::*; +pub mod v1; +pub use v1::*; diff --git a/server/crates/arbiter-crypto/src/authn/v1.rs b/server/crates/arbiter-crypto/src/authn/v1.rs index 6f38e44..1ab55e4 100644 --- a/server/crates/arbiter-crypto/src/authn/v1.rs +++ b/server/crates/arbiter-crypto/src/authn/v1.rs @@ -1,252 +1,252 @@ -use chrono::{DateTime, Utc}; -use hmac::digest::Digest; -use ml_dsa::{ - EncodedVerifyingKey, Error, KeyGen, MlDsa87, Seed, Signature as MlDsaSignature, - SigningKey as MlDsaSigningKey, VerifyingKey as MlDsaVerifyingKey, signature::Keypair as _, -}; -use rand::RngExt; - -pub static CLIENT_CONTEXT: &[u8] = b"arbiter_client"; -pub static OPERATOR_CONTEXT: &[u8] = b"arbiter_operator"; - -const NONCE_SIZE: usize = 32; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)] -#[error("invalid length: expected {expected} bytes, got {actual} bytes")] -pub struct InvalidLength { - pub expected: usize, - pub actual: usize, -} - -#[derive(Debug, Clone)] -pub struct AuthChallenge { - pub nonce: [u8; NONCE_SIZE], - pub timestamp: DateTime, -} - -impl AuthChallenge { - pub fn generate(rng: &mut impl rand::CryptoRng) -> Self { - let timestamp = Utc::now(); - let nonce = { - let mut array = [0; NONCE_SIZE]; - rng.fill(&mut array); - array - }; - - Self { nonce, timestamp } - } - - pub fn format(&self) -> Vec { - { - let mut buffer = Vec::from(self.nonce); - - let stamp = self - .timestamp - .timestamp_nanos_opt() - .expect("We would be long dead by the time this triggers :)"); - buffer.extend_from_slice(stamp.to_be_bytes().as_slice()); - - buffer - } - } - - pub fn from_parts(nonce: &[u8], timestamp: i64) -> Result { - let random_nonce = nonce.as_array().ok_or(InvalidLength { - expected: NONCE_SIZE, - actual: nonce.len(), - })?; - Ok(Self { - nonce: *random_nonce, - timestamp: DateTime::from_timestamp_nanos(timestamp), - }) - } -} - -pub type KeyParams = MlDsa87; - -#[derive(Clone, Debug, PartialEq)] -pub struct PublicKey(Box>); - -impl crate::hashing::Hashable for PublicKey { - fn hash(&self, hasher: &mut H) { - hasher.update(self.to_bytes()); - } -} - -#[derive(Clone, Debug, PartialEq)] -pub struct Signature(Box>); - -#[derive(Debug)] -pub struct SigningKey(Box>); - -impl PublicKey { - pub fn to_bytes(&self) -> Vec { - self.0.encode().0.to_vec() - } - - #[must_use] - pub fn verify(&self, challenge: &AuthChallenge, context: &[u8], signature: &Signature) -> bool { - let challenge = challenge.format(); - self.0 - .verify_with_context(&challenge, context, &signature.0) - } -} - -impl Signature { - pub fn to_bytes(&self) -> Vec { - self.0.encode().0.to_vec() - } -} - -impl SigningKey { - pub fn generate() -> Self { - Self(Box::new(KeyParams::key_gen(&mut rand::rng()))) - } - - pub fn from_seed(seed: [u8; 32]) -> Self { - Self(Box::new(KeyParams::from_seed(&Seed::from(seed)))) - } - - pub fn to_seed(&self) -> [u8; 32] { - self.0.to_seed().into() - } - - pub fn public_key(&self) -> PublicKey { - self.0.verifying_key().into() - } - - pub fn sign_message(&self, message: &[u8], context: &[u8]) -> Result { - self.0 - .signing_key() - .sign_deterministic(message, context) - .map(Into::into) - } - - pub fn sign_challenge( - &self, - challenge: &AuthChallenge, - context: &[u8], - ) -> Result { - let challenge = challenge.format(); - - self.sign_message(&challenge, context) - } -} - -impl From> for PublicKey { - fn from(value: MlDsaVerifyingKey) -> Self { - Self(Box::new(value)) - } -} - -impl From> for Signature { - fn from(value: MlDsaSignature) -> Self { - Self(Box::new(value)) - } -} - -impl From> for SigningKey { - fn from(value: MlDsaSigningKey) -> Self { - Self(Box::new(value)) - } -} - -impl TryFrom> for PublicKey { - type Error = (); - - fn try_from(value: Vec) -> Result { - Self::try_from(value.as_slice()) - } -} - -impl TryFrom<&'_ [u8]> for PublicKey { - type Error = (); - - fn try_from(value: &[u8]) -> Result { - let encoded = EncodedVerifyingKey::::try_from(value).map_err(|_| ())?; - Ok(Self(Box::new(MlDsaVerifyingKey::decode(&encoded)))) - } -} - -impl TryFrom> for Signature { - type Error = (); - - fn try_from(value: Vec) -> Result { - Self::try_from(value.as_slice()) - } -} - -impl TryFrom<&'_ [u8]> for Signature { - type Error = (); - - fn try_from(value: &[u8]) -> Result { - MlDsaSignature::try_from(value) - .map(|sig| Self(Box::new(sig))) - .map_err(|_| ()) - } -} - -#[cfg(test)] -mod tests { - use ml_dsa::{KeyGen, MlDsa87, signature::Keypair as _}; - - use crate::authn::AuthChallenge; - - use super::{CLIENT_CONTEXT, PublicKey, Signature, SigningKey, OPERATOR_CONTEXT}; - - #[test] - fn public_key_round_trip_decodes() { - let key = MlDsa87::key_gen(&mut rand::rng()); - let encoded = PublicKey::from(key.verifying_key()).to_bytes(); - - let decoded = PublicKey::try_from(encoded.as_slice()).expect("public key should decode"); - - assert_eq!(decoded, PublicKey::from(key.verifying_key())); - } - - #[test] - fn signature_round_trip_decodes() { - let key = SigningKey::generate(); - let signature = key - .sign_message(b"challenge", CLIENT_CONTEXT) - .expect("signature should be created"); - - let decoded = - Signature::try_from(signature.to_bytes().as_slice()).expect("signature should decode"); - - assert_eq!(decoded, signature); - } - - #[test] - fn challenge_verification_uses_context_and_canonical_key_bytes() { - let key = SigningKey::generate(); - let public_key = key.public_key(); - let challenge = AuthChallenge::generate(&mut rand::rng()); - let signature = key - .sign_challenge(&challenge, CLIENT_CONTEXT) - .expect("signature should be created"); - - assert!(public_key.verify(&challenge, CLIENT_CONTEXT, &signature)); - assert!(!public_key.verify(&challenge, OPERATOR_CONTEXT, &signature)); - } - - #[test] - fn signing_key_round_trip_seed_preserves_public_key_and_signing() { - let original = SigningKey::generate(); - let restored = SigningKey::from_seed(original.to_seed()); - - assert_eq!(restored.public_key(), original.public_key()); - - let challenge = AuthChallenge::generate(&mut rand::rng()); - - let signature = restored - .sign_challenge(&challenge, CLIENT_CONTEXT) - .expect("signature should be created"); - - assert!( - restored - .public_key() - .verify(&challenge, CLIENT_CONTEXT, &signature) - ); - } -} +use chrono::{DateTime, Utc}; +use hmac::digest::Digest; +use ml_dsa::{ + EncodedVerifyingKey, Error, KeyGen, MlDsa87, Seed, Signature as MlDsaSignature, + SigningKey as MlDsaSigningKey, VerifyingKey as MlDsaVerifyingKey, signature::Keypair as _, +}; +use rand::RngExt; + +pub static CLIENT_CONTEXT: &[u8] = b"arbiter_client"; +pub static OPERATOR_CONTEXT: &[u8] = b"arbiter_operator"; + +const NONCE_SIZE: usize = 32; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)] +#[error("invalid length: expected {expected} bytes, got {actual} bytes")] +pub struct InvalidLength { + pub expected: usize, + pub actual: usize, +} + +#[derive(Debug, Clone)] +pub struct AuthChallenge { + pub nonce: [u8; NONCE_SIZE], + pub timestamp: DateTime, +} + +impl AuthChallenge { + pub fn generate(rng: &mut impl rand::CryptoRng) -> Self { + let timestamp = Utc::now(); + let nonce = { + let mut array = [0; NONCE_SIZE]; + rng.fill(&mut array); + array + }; + + Self { nonce, timestamp } + } + + pub fn format(&self) -> Vec { + { + let mut buffer = Vec::from(self.nonce); + + let stamp = self + .timestamp + .timestamp_nanos_opt() + .expect("We would be long dead by the time this triggers :)"); + buffer.extend_from_slice(stamp.to_be_bytes().as_slice()); + + buffer + } + } + + pub fn from_parts(nonce: &[u8], timestamp: i64) -> Result { + let random_nonce = nonce.as_array().ok_or(InvalidLength { + expected: NONCE_SIZE, + actual: nonce.len(), + })?; + Ok(Self { + nonce: *random_nonce, + timestamp: DateTime::from_timestamp_nanos(timestamp), + }) + } +} + +pub type KeyParams = MlDsa87; + +#[derive(Clone, Debug, PartialEq)] +pub struct PublicKey(Box>); + +impl crate::hashing::Hashable for PublicKey { + fn hash(&self, hasher: &mut H) { + hasher.update(self.to_bytes()); + } +} + +#[derive(Clone, Debug, PartialEq)] +pub struct Signature(Box>); + +#[derive(Debug)] +pub struct SigningKey(Box>); + +impl PublicKey { + pub fn to_bytes(&self) -> Vec { + self.0.encode().0.to_vec() + } + + #[must_use] + pub fn verify(&self, challenge: &AuthChallenge, context: &[u8], signature: &Signature) -> bool { + let challenge = challenge.format(); + self.0 + .verify_with_context(&challenge, context, &signature.0) + } +} + +impl Signature { + pub fn to_bytes(&self) -> Vec { + self.0.encode().0.to_vec() + } +} + +impl SigningKey { + pub fn generate() -> Self { + Self(Box::new(KeyParams::key_gen(&mut rand::rng()))) + } + + pub fn from_seed(seed: [u8; 32]) -> Self { + Self(Box::new(KeyParams::from_seed(&Seed::from(seed)))) + } + + pub fn to_seed(&self) -> [u8; 32] { + self.0.to_seed().into() + } + + pub fn public_key(&self) -> PublicKey { + self.0.verifying_key().into() + } + + pub fn sign_message(&self, message: &[u8], context: &[u8]) -> Result { + self.0 + .signing_key() + .sign_deterministic(message, context) + .map(Into::into) + } + + pub fn sign_challenge( + &self, + challenge: &AuthChallenge, + context: &[u8], + ) -> Result { + let challenge = challenge.format(); + + self.sign_message(&challenge, context) + } +} + +impl From> for PublicKey { + fn from(value: MlDsaVerifyingKey) -> Self { + Self(Box::new(value)) + } +} + +impl From> for Signature { + fn from(value: MlDsaSignature) -> Self { + Self(Box::new(value)) + } +} + +impl From> for SigningKey { + fn from(value: MlDsaSigningKey) -> Self { + Self(Box::new(value)) + } +} + +impl TryFrom> for PublicKey { + type Error = (); + + fn try_from(value: Vec) -> Result { + Self::try_from(value.as_slice()) + } +} + +impl TryFrom<&'_ [u8]> for PublicKey { + type Error = (); + + fn try_from(value: &[u8]) -> Result { + let encoded = EncodedVerifyingKey::::try_from(value).map_err(|_| ())?; + Ok(Self(Box::new(MlDsaVerifyingKey::decode(&encoded)))) + } +} + +impl TryFrom> for Signature { + type Error = (); + + fn try_from(value: Vec) -> Result { + Self::try_from(value.as_slice()) + } +} + +impl TryFrom<&'_ [u8]> for Signature { + type Error = (); + + fn try_from(value: &[u8]) -> Result { + MlDsaSignature::try_from(value) + .map(|sig| Self(Box::new(sig))) + .map_err(|_| ()) + } +} + +#[cfg(test)] +mod tests { + use ml_dsa::{KeyGen, MlDsa87, signature::Keypair as _}; + + use crate::authn::AuthChallenge; + + use super::{CLIENT_CONTEXT, PublicKey, Signature, SigningKey, OPERATOR_CONTEXT}; + + #[test] + fn public_key_round_trip_decodes() { + let key = MlDsa87::key_gen(&mut rand::rng()); + let encoded = PublicKey::from(key.verifying_key()).to_bytes(); + + let decoded = PublicKey::try_from(encoded.as_slice()).expect("public key should decode"); + + assert_eq!(decoded, PublicKey::from(key.verifying_key())); + } + + #[test] + fn signature_round_trip_decodes() { + let key = SigningKey::generate(); + let signature = key + .sign_message(b"challenge", CLIENT_CONTEXT) + .expect("signature should be created"); + + let decoded = + Signature::try_from(signature.to_bytes().as_slice()).expect("signature should decode"); + + assert_eq!(decoded, signature); + } + + #[test] + fn challenge_verification_uses_context_and_canonical_key_bytes() { + let key = SigningKey::generate(); + let public_key = key.public_key(); + let challenge = AuthChallenge::generate(&mut rand::rng()); + let signature = key + .sign_challenge(&challenge, CLIENT_CONTEXT) + .expect("signature should be created"); + + assert!(public_key.verify(&challenge, CLIENT_CONTEXT, &signature)); + assert!(!public_key.verify(&challenge, OPERATOR_CONTEXT, &signature)); + } + + #[test] + fn signing_key_round_trip_seed_preserves_public_key_and_signing() { + let original = SigningKey::generate(); + let restored = SigningKey::from_seed(original.to_seed()); + + assert_eq!(restored.public_key(), original.public_key()); + + let challenge = AuthChallenge::generate(&mut rand::rng()); + + let signature = restored + .sign_challenge(&challenge, CLIENT_CONTEXT) + .expect("signature should be created"); + + assert!( + restored + .public_key() + .verify(&challenge, CLIENT_CONTEXT, &signature) + ); + } +} diff --git a/server/crates/arbiter-crypto/src/hashing.rs b/server/crates/arbiter-crypto/src/hashing.rs index 12c90d4..30a7acb 100644 --- a/server/crates/arbiter-crypto/src/hashing.rs +++ b/server/crates/arbiter-crypto/src/hashing.rs @@ -1,112 +1,112 @@ -use std::collections::HashSet; - -pub use hmac::digest::Digest; - -/// Deterministically hash a value by feeding its fields into the hasher in a consistent order. -#[diagnostic::on_unimplemented( - note = "for local types consider adding `#[derive(arbiter_macros::Hashable)]` to your `{Self}` type", - note = "for types from other crates check whether the crate offers a `Hashable` implementation" -)] -pub trait Hashable { - fn hash(&self, hasher: &mut H); -} - -macro_rules! impl_numeric { - ($($t:ty),*) => { - $( - impl Hashable for $t { - fn hash(&self, hasher: &mut H) { - hasher.update(&self.to_be_bytes()); - } - } - )* - }; -} - -impl_numeric!(u8, u16, u32, u64, i8, i16, i32, i64); - -impl Hashable for &[u8] { - fn hash(&self, hasher: &mut H) { - hasher.update(self); - } -} - -impl Hashable for String { - fn hash(&self, hasher: &mut H) { - hasher.update(self.as_bytes()); - } -} - -impl Hashable for Vec { - fn hash(&self, hasher: &mut H) { - let ref_sorted = { - let mut sorted = self.iter().collect::>(); - sorted.sort_by(|a, b| a.partial_cmp(b).unwrap()); - sorted - }; - for item in ref_sorted { - item.hash(hasher); - } - } -} - -impl Hashable for HashSet { - fn hash(&self, hasher: &mut H) { - let ref_sorted = { - let mut sorted = self.iter().collect::>(); - sorted.sort_by(|a, b| a.partial_cmp(b).unwrap()); - sorted - }; - for item in ref_sorted { - item.hash(hasher); - } - } -} - -impl Hashable for Option { - fn hash(&self, hasher: &mut H) { - match self { - Some(value) => { - hasher.update([1]); - value.hash(hasher); - } - None => hasher.update([0]), - } - } -} - -impl Hashable for Box { - fn hash(&self, hasher: &mut H) { - self.as_ref().hash(hasher); - } -} - -impl Hashable for &T { - fn hash(&self, hasher: &mut H) { - (*self).hash(hasher); - } -} - -impl Hashable for alloy::primitives::Address { - fn hash(&self, hasher: &mut H) { - hasher.update(self.as_slice()); - } -} - -impl Hashable for alloy::primitives::U256 { - fn hash(&self, hasher: &mut H) { - hasher.update(self.to_be_bytes::<32>()); - } -} - -impl Hashable for chrono::Duration { - fn hash(&self, hasher: &mut H) { - hasher.update(self.num_seconds().to_be_bytes()); - } -} - -impl Hashable for chrono::DateTime { - fn hash(&self, hasher: &mut H) { - hasher.update(self.timestamp_millis().to_be_bytes()); - } -} +use std::collections::HashSet; + +pub use hmac::digest::Digest; + +/// Deterministically hash a value by feeding its fields into the hasher in a consistent order. +#[diagnostic::on_unimplemented( + note = "for local types consider adding `#[derive(arbiter_macros::Hashable)]` to your `{Self}` type", + note = "for types from other crates check whether the crate offers a `Hashable` implementation" +)] +pub trait Hashable { + fn hash(&self, hasher: &mut H); +} + +macro_rules! impl_numeric { + ($($t:ty),*) => { + $( + impl Hashable for $t { + fn hash(&self, hasher: &mut H) { + hasher.update(&self.to_be_bytes()); + } + } + )* + }; +} + +impl_numeric!(u8, u16, u32, u64, i8, i16, i32, i64); + +impl Hashable for &[u8] { + fn hash(&self, hasher: &mut H) { + hasher.update(self); + } +} + +impl Hashable for String { + fn hash(&self, hasher: &mut H) { + hasher.update(self.as_bytes()); + } +} + +impl Hashable for Vec { + fn hash(&self, hasher: &mut H) { + let ref_sorted = { + let mut sorted = self.iter().collect::>(); + sorted.sort_by(|a, b| a.partial_cmp(b).unwrap()); + sorted + }; + for item in ref_sorted { + item.hash(hasher); + } + } +} + +impl Hashable for HashSet { + fn hash(&self, hasher: &mut H) { + let ref_sorted = { + let mut sorted = self.iter().collect::>(); + sorted.sort_by(|a, b| a.partial_cmp(b).unwrap()); + sorted + }; + for item in ref_sorted { + item.hash(hasher); + } + } +} + +impl Hashable for Option { + fn hash(&self, hasher: &mut H) { + match self { + Some(value) => { + hasher.update([1]); + value.hash(hasher); + } + None => hasher.update([0]), + } + } +} + +impl Hashable for Box { + fn hash(&self, hasher: &mut H) { + self.as_ref().hash(hasher); + } +} + +impl Hashable for &T { + fn hash(&self, hasher: &mut H) { + (*self).hash(hasher); + } +} + +impl Hashable for alloy::primitives::Address { + fn hash(&self, hasher: &mut H) { + hasher.update(self.as_slice()); + } +} + +impl Hashable for alloy::primitives::U256 { + fn hash(&self, hasher: &mut H) { + hasher.update(self.to_be_bytes::<32>()); + } +} + +impl Hashable for chrono::Duration { + fn hash(&self, hasher: &mut H) { + hasher.update(self.num_seconds().to_be_bytes()); + } +} + +impl Hashable for chrono::DateTime { + fn hash(&self, hasher: &mut H) { + hasher.update(self.timestamp_millis().to_be_bytes()); + } +} diff --git a/server/crates/arbiter-crypto/src/lib.rs b/server/crates/arbiter-crypto/src/lib.rs index 8e1c9ce..29034b8 100644 --- a/server/crates/arbiter-crypto/src/lib.rs +++ b/server/crates/arbiter-crypto/src/lib.rs @@ -1,7 +1,7 @@ -#[cfg(feature = "authn")] -pub mod authn; -pub mod hashing; -#[cfg(feature = "safecell")] -pub mod safecell; - -pub use x_wing; +#[cfg(feature = "authn")] +pub mod authn; +pub mod hashing; +#[cfg(feature = "safecell")] +pub mod safecell; + +pub use x_wing; diff --git a/server/crates/arbiter-crypto/src/safecell.rs b/server/crates/arbiter-crypto/src/safecell.rs index 15b0044..b4ce4da 100644 --- a/server/crates/arbiter-crypto/src/safecell.rs +++ b/server/crates/arbiter-crypto/src/safecell.rs @@ -1,118 +1,118 @@ -use memsafe::MemSafe; -use std::{ - any::type_name, - fmt, - ops::{Deref, DerefMut}, -}; - -pub trait SafeCellHandle { - type CellRead<'a>: Deref - where - Self: 'a, - T: 'a; - type CellWrite<'a>: Deref + DerefMut - where - Self: 'a, - T: 'a; - - fn new(value: T) -> Self - where - Self: Sized; - - fn read(&mut self) -> Self::CellRead<'_>; - fn write(&mut self) -> Self::CellWrite<'_>; - - fn new_inline(f: F) -> Self - where - Self: Sized, - T: Default, - F: for<'a> FnOnce(&'a mut T), - { - let mut cell = Self::new(T::default()); - { - let mut handle = cell.write(); - f(&mut *handle); - } - cell - } - - #[inline(always)] - fn read_inline(&mut self, f: F) -> R - where - F: FnOnce(&T) -> R, - { - f(&*self.read()) - } - - #[inline(always)] - fn write_inline(&mut self, f: F) -> R - where - F: FnOnce(&mut T) -> R, - { - f(&mut *self.write()) - } -} - -pub struct MemSafeCell(MemSafe); - -impl fmt::Debug for MemSafeCell { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("MemSafeCell") - .field("inner", &format_args!("", type_name::())) - .finish() - } -} - -impl SafeCellHandle for MemSafeCell { - type CellRead<'a> - = memsafe::MemSafeRead<'a, T> - where - Self: 'a, - T: 'a; - type CellWrite<'a> - = memsafe::MemSafeWrite<'a, T> - where - Self: 'a, - T: 'a; - - fn new(value: T) -> Self { - match MemSafe::new(value) { - Ok(inner) => Self(inner), - Err(err) => { - // If protected memory cannot be allocated, process integrity is compromised. - abort_memory_breach("safe cell allocation", &err) - } - } - } - - #[inline(always)] - fn read(&mut self) -> Self::CellRead<'_> { - match self.0.read() { - Ok(inner) => inner, - Err(err) => abort_memory_breach("safe cell read", &err), - } - } - - #[inline(always)] - fn write(&mut self) -> Self::CellWrite<'_> { - match self.0.write() { - Ok(inner) => inner, - Err(err) => { - // If protected memory becomes unwritable here, treat it as a fatal memory breach. - abort_memory_breach("safe cell write", &err) - } - } - } -} - -fn abort_memory_breach(action: &str, err: &memsafe::error::MemoryError) -> ! { - eprintln!("fatal {action}: {err}"); - // SAFETY: Intentionally cause a segmentation fault to prevent further execution in a compromised state. - unsafe { - let unsafe_pointer = std::ptr::null_mut::(); - std::ptr::write_volatile(unsafe_pointer, 0); - } - std::process::abort(); -} - -pub type SafeCell = MemSafeCell; +use memsafe::MemSafe; +use std::{ + any::type_name, + fmt, + ops::{Deref, DerefMut}, +}; + +pub trait SafeCellHandle { + type CellRead<'a>: Deref + where + Self: 'a, + T: 'a; + type CellWrite<'a>: Deref + DerefMut + where + Self: 'a, + T: 'a; + + fn new(value: T) -> Self + where + Self: Sized; + + fn read(&mut self) -> Self::CellRead<'_>; + fn write(&mut self) -> Self::CellWrite<'_>; + + fn new_inline(f: F) -> Self + where + Self: Sized, + T: Default, + F: for<'a> FnOnce(&'a mut T), + { + let mut cell = Self::new(T::default()); + { + let mut handle = cell.write(); + f(&mut *handle); + } + cell + } + + #[inline(always)] + fn read_inline(&mut self, f: F) -> R + where + F: FnOnce(&T) -> R, + { + f(&*self.read()) + } + + #[inline(always)] + fn write_inline(&mut self, f: F) -> R + where + F: FnOnce(&mut T) -> R, + { + f(&mut *self.write()) + } +} + +pub struct MemSafeCell(MemSafe); + +impl fmt::Debug for MemSafeCell { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("MemSafeCell") + .field("inner", &format_args!("", type_name::())) + .finish() + } +} + +impl SafeCellHandle for MemSafeCell { + type CellRead<'a> + = memsafe::MemSafeRead<'a, T> + where + Self: 'a, + T: 'a; + type CellWrite<'a> + = memsafe::MemSafeWrite<'a, T> + where + Self: 'a, + T: 'a; + + fn new(value: T) -> Self { + match MemSafe::new(value) { + Ok(inner) => Self(inner), + Err(err) => { + // If protected memory cannot be allocated, process integrity is compromised. + abort_memory_breach("safe cell allocation", &err) + } + } + } + + #[inline(always)] + fn read(&mut self) -> Self::CellRead<'_> { + match self.0.read() { + Ok(inner) => inner, + Err(err) => abort_memory_breach("safe cell read", &err), + } + } + + #[inline(always)] + fn write(&mut self) -> Self::CellWrite<'_> { + match self.0.write() { + Ok(inner) => inner, + Err(err) => { + // If protected memory becomes unwritable here, treat it as a fatal memory breach. + abort_memory_breach("safe cell write", &err) + } + } + } +} + +fn abort_memory_breach(action: &str, err: &memsafe::error::MemoryError) -> ! { + eprintln!("fatal {action}: {err}"); + // SAFETY: Intentionally cause a segmentation fault to prevent further execution in a compromised state. + unsafe { + let unsafe_pointer = std::ptr::null_mut::(); + std::ptr::write_volatile(unsafe_pointer, 0); + } + std::process::abort(); +} + +pub type SafeCell = MemSafeCell; diff --git a/server/crates/arbiter-macros/Cargo.toml b/server/crates/arbiter-macros/Cargo.toml index 15a5070..3f74eaf 100644 --- a/server/crates/arbiter-macros/Cargo.toml +++ b/server/crates/arbiter-macros/Cargo.toml @@ -1,19 +1,19 @@ -[package] -name = "arbiter-macros" -version = "0.1.0" -edition = "2024" - -[lib] -proc-macro = true -doctest = false - -[dependencies] -proc-macro2 = "1.0" -quote = "1.0" -syn = { version = "2.0", features = ["derive", "fold", "full", "visit-mut"] } - -[dev-dependencies] -arbiter-crypto = { path = "../arbiter-crypto" } - -[lints] -workspace = true +[package] +name = "arbiter-macros" +version = "0.1.0" +edition = "2024" + +[lib] +proc-macro = true +doctest = false + +[dependencies] +proc-macro2 = "1.0" +quote = "1.0" +syn = { version = "2.0", features = ["derive", "fold", "full", "visit-mut"] } + +[dev-dependencies] +arbiter-crypto = { path = "../arbiter-crypto" } + +[lints] +workspace = true diff --git a/server/crates/arbiter-macros/src/hashable.rs b/server/crates/arbiter-macros/src/hashable.rs index bfaec3e..31ab576 100644 --- a/server/crates/arbiter-macros/src/hashable.rs +++ b/server/crates/arbiter-macros/src/hashable.rs @@ -1,131 +1,131 @@ -use crate::utils::{HASHABLE_TRAIT_PATH, HMAC_DIGEST_PATH}; - -use proc_macro2::{Span, TokenStream, TokenTree}; -use quote::quote; -use syn::{DataStruct, DeriveInput, Fields, Generics, Index, parse_quote, spanned::Spanned}; - -pub(crate) fn derive(input: &DeriveInput) -> TokenStream { - match &input.data { - syn::Data::Struct(struct_data) => hashable_struct(input, struct_data), - syn::Data::Enum(_) => { - syn::Error::new_spanned(input, "Hashable can currently be derived only for structs") - .to_compile_error() - } - syn::Data::Union(_) => { - syn::Error::new_spanned(input, "Hashable cannot be derived for unions") - .to_compile_error() - } - } -} - -fn hashable_struct(input: &DeriveInput, struct_data: &DataStruct) -> TokenStream { - let ident = &input.ident; - let hashable_trait = HASHABLE_TRAIT_PATH.to_path(); - let hmac_digest = HMAC_DIGEST_PATH.to_path(); - let generics = add_hashable_bounds(input.generics.clone(), &hashable_trait); - let field_accesses = collect_field_accesses(struct_data); - let hash_calls = build_hash_calls(&field_accesses, &hashable_trait); - - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - - quote! { - #[automatically_derived] - impl #impl_generics #hashable_trait for #ident #ty_generics #where_clause { - fn hash(&self, hasher: &mut H) { - #(#hash_calls)* - } - } - } -} - -fn add_hashable_bounds(mut generics: Generics, hashable_trait: &syn::Path) -> Generics { - for type_param in generics.type_params_mut() { - type_param.bounds.push(parse_quote!(#hashable_trait)); - } - - generics -} - -struct FieldAccess { - access: TokenStream, - span: Span, -} - -fn collect_field_accesses(struct_data: &DataStruct) -> Vec { - match &struct_data.fields { - Fields::Named(fields) => { - // Keep deterministic alphabetical order for named fields. - // Do not remove this sort, because it keeps hash output stable regardless of source order. - let mut named_fields = fields - .named - .iter() - .map(|field| { - let name = field - .ident - .as_ref() - .expect("Fields::Named(fields) must have names") - .clone(); - (name.to_string(), name) - }) - .collect::>(); - - named_fields.sort_by(|a, b| a.0.cmp(&b.0)); - - named_fields - .into_iter() - .map(|(_, name)| FieldAccess { - access: quote! { #name }, - span: name.span(), - }) - .collect() - } - Fields::Unnamed(fields) => fields - .unnamed - .iter() - .enumerate() - .map(|(i, field)| FieldAccess { - access: { - let index = Index::from(i); - quote! { #index } - }, - span: field.ty.span(), - }) - .collect(), - Fields::Unit => Vec::new(), - } -} - -fn build_hash_calls( - field_accesses: &[FieldAccess], - hashable_trait: &syn::Path, -) -> Vec { - field_accesses - .iter() - .map(|field| { - let access = &field.access; - let call = quote! { - #hashable_trait::hash(&self.#access, hasher); - }; - - respan(call, field.span) - }) - .collect() -} - -/// Recursively set span on all tokens, including interpolated ones. -fn respan(tokens: TokenStream, span: Span) -> TokenStream { - tokens - .into_iter() - .map(|tt| match tt { - TokenTree::Group(g) => { - let mut new = proc_macro2::Group::new(g.delimiter(), respan(g.stream(), span)); - new.set_span(span); - TokenTree::Group(new) - } - mut other => { - other.set_span(span); - other - } - }) - .collect() -} +use crate::utils::{HASHABLE_TRAIT_PATH, HMAC_DIGEST_PATH}; + +use proc_macro2::{Span, TokenStream, TokenTree}; +use quote::quote; +use syn::{DataStruct, DeriveInput, Fields, Generics, Index, parse_quote, spanned::Spanned}; + +pub(crate) fn derive(input: &DeriveInput) -> TokenStream { + match &input.data { + syn::Data::Struct(struct_data) => hashable_struct(input, struct_data), + syn::Data::Enum(_) => { + syn::Error::new_spanned(input, "Hashable can currently be derived only for structs") + .to_compile_error() + } + syn::Data::Union(_) => { + syn::Error::new_spanned(input, "Hashable cannot be derived for unions") + .to_compile_error() + } + } +} + +fn hashable_struct(input: &DeriveInput, struct_data: &DataStruct) -> TokenStream { + let ident = &input.ident; + let hashable_trait = HASHABLE_TRAIT_PATH.to_path(); + let hmac_digest = HMAC_DIGEST_PATH.to_path(); + let generics = add_hashable_bounds(input.generics.clone(), &hashable_trait); + let field_accesses = collect_field_accesses(struct_data); + let hash_calls = build_hash_calls(&field_accesses, &hashable_trait); + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + #[automatically_derived] + impl #impl_generics #hashable_trait for #ident #ty_generics #where_clause { + fn hash(&self, hasher: &mut H) { + #(#hash_calls)* + } + } + } +} + +fn add_hashable_bounds(mut generics: Generics, hashable_trait: &syn::Path) -> Generics { + for type_param in generics.type_params_mut() { + type_param.bounds.push(parse_quote!(#hashable_trait)); + } + + generics +} + +struct FieldAccess { + access: TokenStream, + span: Span, +} + +fn collect_field_accesses(struct_data: &DataStruct) -> Vec { + match &struct_data.fields { + Fields::Named(fields) => { + // Keep deterministic alphabetical order for named fields. + // Do not remove this sort, because it keeps hash output stable regardless of source order. + let mut named_fields = fields + .named + .iter() + .map(|field| { + let name = field + .ident + .as_ref() + .expect("Fields::Named(fields) must have names") + .clone(); + (name.to_string(), name) + }) + .collect::>(); + + named_fields.sort_by(|a, b| a.0.cmp(&b.0)); + + named_fields + .into_iter() + .map(|(_, name)| FieldAccess { + access: quote! { #name }, + span: name.span(), + }) + .collect() + } + Fields::Unnamed(fields) => fields + .unnamed + .iter() + .enumerate() + .map(|(i, field)| FieldAccess { + access: { + let index = Index::from(i); + quote! { #index } + }, + span: field.ty.span(), + }) + .collect(), + Fields::Unit => Vec::new(), + } +} + +fn build_hash_calls( + field_accesses: &[FieldAccess], + hashable_trait: &syn::Path, +) -> Vec { + field_accesses + .iter() + .map(|field| { + let access = &field.access; + let call = quote! { + #hashable_trait::hash(&self.#access, hasher); + }; + + respan(call, field.span) + }) + .collect() +} + +/// Recursively set span on all tokens, including interpolated ones. +fn respan(tokens: TokenStream, span: Span) -> TokenStream { + tokens + .into_iter() + .map(|tt| match tt { + TokenTree::Group(g) => { + let mut new = proc_macro2::Group::new(g.delimiter(), respan(g.stream(), span)); + new.set_span(span); + TokenTree::Group(new) + } + mut other => { + other.set_span(span); + other + } + }) + .collect() +} diff --git a/server/crates/arbiter-macros/src/lib.rs b/server/crates/arbiter-macros/src/lib.rs index 51b8f79..865eb1e 100644 --- a/server/crates/arbiter-macros/src/lib.rs +++ b/server/crates/arbiter-macros/src/lib.rs @@ -1,10 +1,10 @@ -use syn::{DeriveInput, parse_macro_input}; - -mod hashable; -mod utils; - -#[proc_macro_derive(Hashable)] -pub fn derive_hashable(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - hashable::derive(&input).into() -} +use syn::{DeriveInput, parse_macro_input}; + +mod hashable; +mod utils; + +#[proc_macro_derive(Hashable)] +pub fn derive_hashable(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input = parse_macro_input!(input as DeriveInput); + hashable::derive(&input).into() +} diff --git a/server/crates/arbiter-macros/src/utils.rs b/server/crates/arbiter-macros/src/utils.rs index c1ccf2e..24bf898 100644 --- a/server/crates/arbiter-macros/src/utils.rs +++ b/server/crates/arbiter-macros/src/utils.rs @@ -1,24 +1,24 @@ -pub(crate) struct ToPath(pub &'static str); - -impl ToPath { - pub(crate) fn to_path(&self) -> syn::Path { - syn::parse_str(self.0).expect("Invalid path") - } -} - -macro_rules! ensure_path { - ($path:path as $name:ident) => { - const _: () = { - #[cfg(test)] - #[expect( - unused_imports, - reason = "Ensures the path is valid and will cause a compile error if not" - )] - use $path as _; - }; - pub(crate) const $name: ToPath = ToPath(stringify!($path)); - }; -} - -ensure_path!(::arbiter_crypto::hashing::Hashable as HASHABLE_TRAIT_PATH); -ensure_path!(::arbiter_crypto::hashing::Digest as HMAC_DIGEST_PATH); +pub(crate) struct ToPath(pub &'static str); + +impl ToPath { + pub(crate) fn to_path(&self) -> syn::Path { + syn::parse_str(self.0).expect("Invalid path") + } +} + +macro_rules! ensure_path { + ($path:path as $name:ident) => { + const _: () = { + #[cfg(test)] + #[expect( + unused_imports, + reason = "Ensures the path is valid and will cause a compile error if not" + )] + use $path as _; + }; + pub(crate) const $name: ToPath = ToPath(stringify!($path)); + }; +} + +ensure_path!(::arbiter_crypto::hashing::Hashable as HASHABLE_TRAIT_PATH); +ensure_path!(::arbiter_crypto::hashing::Digest as HMAC_DIGEST_PATH); diff --git a/server/crates/arbiter-proto/Cargo.toml b/server/crates/arbiter-proto/Cargo.toml index b8667be..43e2c69 100644 --- a/server/crates/arbiter-proto/Cargo.toml +++ b/server/crates/arbiter-proto/Cargo.toml @@ -1,35 +1,35 @@ -[package] -name = "arbiter-proto" -version = "0.1.0" -edition = "2024" -repository = "https://git.markettakers.org/MarketTakers/arbiter" -license = "Apache-2.0" - -[dependencies] -tonic.workspace = true -tokio.workspace = true -futures.workspace = true -tonic-prost = "0.14.5" -prost.workspace = true -kameo.workspace = true -url = "2.5.8" -miette.workspace = true -thiserror.workspace = true -rustls-pki-types.workspace = true -base64.workspace = true -prost-types.workspace = true -async-trait.workspace = true -tokio-stream.workspace = true - -[build-dependencies] -tonic-prost-build = "0.14.5" - -[dev-dependencies] -rstest.workspace = true -rcgen.workspace = true - -[lib] -doctest = false - -[package.metadata.cargo-shear] -ignored = ["tonic-prost", "prost"] +[package] +name = "arbiter-proto" +version = "0.1.0" +edition = "2024" +repository = "https://git.markettakers.org/MarketTakers/arbiter" +license = "Apache-2.0" + +[dependencies] +tonic.workspace = true +tokio.workspace = true +futures.workspace = true +tonic-prost = "0.14.5" +prost.workspace = true +kameo.workspace = true +url = "2.5.8" +miette.workspace = true +thiserror.workspace = true +rustls-pki-types.workspace = true +base64.workspace = true +prost-types.workspace = true +async-trait.workspace = true +tokio-stream.workspace = true + +[build-dependencies] +tonic-prost-build = "0.14.5" + +[dev-dependencies] +rstest.workspace = true +rcgen.workspace = true + +[lib] +doctest = false + +[package.metadata.cargo-shear] +ignored = ["tonic-prost", "prost"] diff --git a/server/crates/arbiter-proto/build.rs b/server/crates/arbiter-proto/build.rs index a9250d3..0ee0dbf 100644 --- a/server/crates/arbiter-proto/build.rs +++ b/server/crates/arbiter-proto/build.rs @@ -1,21 +1,21 @@ -use tonic_prost_build::configure; - -static PROTOBUF_DIR: &str = "../../../protobufs"; - -fn main() -> Result<(), Box> { - println!("cargo::rerun-if-changed={PROTOBUF_DIR}"); - - configure() - .message_attribute(".", "#[derive(::kameo::Reply)]") - .compile_protos( - &[ - format!("{}/arbiter.proto", PROTOBUF_DIR), - format!("{}/operator.proto", PROTOBUF_DIR), - format!("{}/client.proto", PROTOBUF_DIR), - format!("{}/evm.proto", PROTOBUF_DIR), - ], - &[PROTOBUF_DIR.to_string()], - ) - .unwrap(); - Ok(()) -} +use tonic_prost_build::configure; + +static PROTOBUF_DIR: &str = "../../../protobufs"; + +fn main() -> Result<(), Box> { + println!("cargo::rerun-if-changed={PROTOBUF_DIR}"); + + configure() + .message_attribute(".", "#[derive(::kameo::Reply)]") + .compile_protos( + &[ + format!("{}/arbiter.proto", PROTOBUF_DIR), + format!("{}/operator.proto", PROTOBUF_DIR), + format!("{}/client.proto", PROTOBUF_DIR), + format!("{}/evm.proto", PROTOBUF_DIR), + ], + &[PROTOBUF_DIR.to_string()], + ) + .unwrap(); + Ok(()) +} diff --git a/server/crates/arbiter-proto/src/lib.rs b/server/crates/arbiter-proto/src/lib.rs index 0b91e11..a8b011a 100644 --- a/server/crates/arbiter-proto/src/lib.rs +++ b/server/crates/arbiter-proto/src/lib.rs @@ -1,84 +1,84 @@ -pub mod transport; -pub mod url; - -pub mod proto { - tonic::include_proto!("arbiter"); - - pub mod shared { - tonic::include_proto!("arbiter.shared"); - - pub mod evm { - tonic::include_proto!("arbiter.shared.evm"); - } - } - - pub mod operator { - tonic::include_proto!("arbiter.operator"); - - pub mod auth { - tonic::include_proto!("arbiter.operator.auth"); - } - - pub mod evm { - tonic::include_proto!("arbiter.operator.evm"); - } - - pub mod sdk_client { - tonic::include_proto!("arbiter.operator.sdk_client"); - } - - pub mod vault { - tonic::include_proto!("arbiter.operator.vault"); - - pub mod bootstrap { - tonic::include_proto!("arbiter.operator.vault.bootstrap"); - } - - pub mod unseal { - tonic::include_proto!("arbiter.operator.vault.unseal"); - } - } - } - - pub mod client { - tonic::include_proto!("arbiter.client"); - - pub mod auth { - tonic::include_proto!("arbiter.client.auth"); - } - - pub mod evm { - tonic::include_proto!("arbiter.client.evm"); - } - - pub mod vault { - tonic::include_proto!("arbiter.client.vault"); - } - } - - pub mod evm { - tonic::include_proto!("arbiter.evm"); - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ClientMetadata { - pub name: String, - pub description: Option, - pub version: Option, -} - -pub static BOOTSTRAP_PATH: &str = "bootstrap_token"; - -pub fn home_path() -> Result { - static ARBITER_HOME: &str = ".arbiter"; - let home_dir = std::env::home_dir().ok_or(std::io::Error::new( - std::io::ErrorKind::PermissionDenied, - "can not get home directory", - ))?; - - let arbiter_home = home_dir.join(ARBITER_HOME); - std::fs::create_dir_all(&arbiter_home)?; - - Ok(arbiter_home) -} +pub mod transport; +pub mod url; + +pub mod proto { + tonic::include_proto!("arbiter"); + + pub mod shared { + tonic::include_proto!("arbiter.shared"); + + pub mod evm { + tonic::include_proto!("arbiter.shared.evm"); + } + } + + pub mod operator { + tonic::include_proto!("arbiter.operator"); + + pub mod auth { + tonic::include_proto!("arbiter.operator.auth"); + } + + pub mod evm { + tonic::include_proto!("arbiter.operator.evm"); + } + + pub mod sdk_client { + tonic::include_proto!("arbiter.operator.sdk_client"); + } + + pub mod vault { + tonic::include_proto!("arbiter.operator.vault"); + + pub mod bootstrap { + tonic::include_proto!("arbiter.operator.vault.bootstrap"); + } + + pub mod unseal { + tonic::include_proto!("arbiter.operator.vault.unseal"); + } + } + } + + pub mod client { + tonic::include_proto!("arbiter.client"); + + pub mod auth { + tonic::include_proto!("arbiter.client.auth"); + } + + pub mod evm { + tonic::include_proto!("arbiter.client.evm"); + } + + pub mod vault { + tonic::include_proto!("arbiter.client.vault"); + } + } + + pub mod evm { + tonic::include_proto!("arbiter.evm"); + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ClientMetadata { + pub name: String, + pub description: Option, + pub version: Option, +} + +pub static BOOTSTRAP_PATH: &str = "bootstrap_token"; + +pub fn home_path() -> Result { + static ARBITER_HOME: &str = ".arbiter"; + let home_dir = std::env::home_dir().ok_or(std::io::Error::new( + std::io::ErrorKind::PermissionDenied, + "can not get home directory", + ))?; + + let arbiter_home = home_dir.join(ARBITER_HOME); + std::fs::create_dir_all(&arbiter_home)?; + + Ok(arbiter_home) +} diff --git a/server/crates/arbiter-proto/src/transport.rs b/server/crates/arbiter-proto/src/transport.rs index afa641b..592ca97 100644 --- a/server/crates/arbiter-proto/src/transport.rs +++ b/server/crates/arbiter-proto/src/transport.rs @@ -1,218 +1,218 @@ -//! Transport-facing abstractions shared by protocol/session code. -//! -//! This module defines a small set of transport traits that actors and other -//! protocol code can depend on without knowing anything about the concrete -//! transport underneath. -//! -//! The abstraction is split into: -//! - [`Sender`] for outbound delivery -//! - [`Receiver`] for inbound delivery -//! - [`Bi`] as the combined duplex form (`Sender + Receiver`) -//! -//! This split lets code depend only on the half it actually needs. For -//! example, some actor/session code only sends out-of-band messages, while -//! auth/state-machine code may need full duplex access. -//! -//! [`Bi`] remains intentionally minimal and transport-agnostic: -//! - [`Receiver::recv`] yields inbound messages -//! - [`Sender::send`] accepts outbound messages -//! -//! Transport-specific adapters, including protobuf or gRPC bridges, live in the -//! crates that own those boundaries rather than in `arbiter-proto`. -//! -//! [`Bi`] deliberately does not model request/response correlation. Some -//! transports may carry multiplexed request/response traffic, some may emit -//! out-of-band messages, and some may be one-message-at-a-time state machines. -//! Correlation concerns such as request IDs, pending response maps, and -//! out-of-band routing belong in the adapter or connection layer built on top -//! of [`Bi`], not in this abstraction itself. -//! -//! # Generic Ordering Rule -//! -//! This module consistently uses `Inbound` first and `Outbound` second in -//! generic parameter lists. -//! -//! For [`Receiver`], [`Sender`], and [`Bi`], this means: -//! - `Receiver` -//! - `Sender` -//! - `Bi` -//! -//! Concretely, for [`Bi`]: -//! - `recv() -> Option` -//! - `send(Outbound)` -//! -//! [`expect_message`] is a small helper for linear protocol steps: it reads one -//! inbound message from a transport and extracts a typed value from it, failing -//! if the channel closes or the message shape is not what the caller expected. -//! -//! [`DummyTransport`] is a no-op implementation useful for tests and local -//! actor execution where no real stream exists. -//! -//! # Design Notes -//! -//! - [`Bi::send`] returns [`Error`] only for transport delivery failures, such -//! as a closed outbound channel. -//! - [`Bi::recv`] returns `None` when the underlying transport closes. -//! - Message translation is intentionally out of scope for this module. -use async_trait::async_trait; -use kameo::{error::Infallible, prelude::*}; -use std::marker::PhantomData; - -/// Errors returned by transport adapters implementing [`Bi`]. -#[derive(thiserror::Error, Debug)] -pub enum Error { - #[error("Transport channel is closed")] - ChannelClosed, - #[error("Unexpected message received")] - UnexpectedMessage, -} - -/// Receives one message from `transport` and extracts a value from it using -/// `extractor`. Returns [`Error::ChannelClosed`] if the transport closes and -/// [`Error::UnexpectedMessage`] if `extractor` returns `None`. -pub async fn expect_message( - transport: &mut T, - extractor: F, -) -> Result -where - T: Bi + ?Sized, - F: FnOnce(Inbound) -> Option, -{ - let msg = transport.recv().await.ok_or(Error::ChannelClosed)?; - extractor(msg).ok_or(Error::UnexpectedMessage) -} - -#[async_trait] -pub trait Sender: Send + Sync { - async fn send(&mut self, item: Outbound) -> Result<(), Error>; -} - -#[async_trait] -pub trait Receiver: Send + Sync { - async fn recv(&mut self) -> Option; -} - -/// Minimal bidirectional transport abstraction used by protocol code. -/// -/// `Bi` is the combined duplex form of [`Sender`] and -/// [`Receiver`]. -/// -/// It models a channel with: -/// - inbound items of type `Inbound` read via [`Bi::recv`] -/// - outbound items of type `Outbound` written via [`Bi::send`] -/// -/// It does not imply request/response sequencing, one-at-a-time exchange, or -/// any built-in correlation mechanism between inbound and outbound items. -pub trait Bi: Sender + Receiver + Send + Sync {} - -#[async_trait] -impl Sender for &mut T -where - T: Sender + ?Sized, - Outbound: Send + 'static, -{ - async fn send(&mut self, item: Outbound) -> Result<(), Error> { - (**self).send(item).await - } -} - -#[async_trait] -impl Receiver for &mut T -where - T: Receiver + ?Sized, - Inbound: Send + 'static, -{ - async fn recv(&mut self) -> Option { - (**self).recv().await - } -} - -impl Bi for &mut T -where - T: Bi + ?Sized, - Inbound: Send + 'static, - Outbound: Send + 'static, -{ -} - -pub trait SplittableBi: Bi { - type Sender: Sender; - type Receiver: Receiver; - - fn split(self) -> (Self::Sender, Self::Receiver); - fn from_parts(sender: Self::Sender, receiver: Self::Receiver) -> Self; -} - -/// No-op [`Bi`] transport for tests and manual actor usage. -/// -/// `send` drops all items and succeeds. [`Bi::recv`] never resolves and therefore -/// does not busy-wait or spuriously close the stream. -pub struct DummyTransport { - _marker: PhantomData<(Inbound, Outbound)>, -} - -impl Default for DummyTransport { - fn default() -> Self { - Self { - _marker: PhantomData, - } - } -} - -#[async_trait] -impl Sender for DummyTransport -where - Inbound: Send + Sync + 'static, - Outbound: Send + Sync + 'static, -{ - async fn send(&mut self, _item: Outbound) -> Result<(), Error> { - Ok(()) - } -} - -#[async_trait] -impl Receiver for DummyTransport -where - Inbound: Send + Sync + 'static, - Outbound: Send + Sync + 'static, -{ - async fn recv(&mut self) -> Option { - std::future::pending::<()>().await; - None - } -} - -impl Bi for DummyTransport -where - Inbound: Send + Sync + 'static, - Outbound: Send + Sync + 'static, -{ -} - -pub mod grpc; - -#[derive(thiserror::Error, Debug)] -pub enum ForwardError { - #[error("Transport error: {0}")] - Transport(#[from] Error), - #[error("Actor delivery error: {0}")] - Actor(SendError), -} - -pub async fn forward_to_actor( - transport: &mut Transport, - actor: &ActorRef, -) -> Result<(), ForwardError> -where - Transport: Bi::Ok>, - Handler: Actor + Message, - Inbound: Send + 'static, - Outbound: Send + 'static + Reply, // `Infallible` to enforce contract that `Outbound` carries handler-level error -{ - while let Some(request) = transport.recv().await { - let resp = actor.ask(request).await.map_err(ForwardError::Actor)?; - transport.send(resp).await? - } - - Err(Error::ChannelClosed.into()) -} +//! Transport-facing abstractions shared by protocol/session code. +//! +//! This module defines a small set of transport traits that actors and other +//! protocol code can depend on without knowing anything about the concrete +//! transport underneath. +//! +//! The abstraction is split into: +//! - [`Sender`] for outbound delivery +//! - [`Receiver`] for inbound delivery +//! - [`Bi`] as the combined duplex form (`Sender + Receiver`) +//! +//! This split lets code depend only on the half it actually needs. For +//! example, some actor/session code only sends out-of-band messages, while +//! auth/state-machine code may need full duplex access. +//! +//! [`Bi`] remains intentionally minimal and transport-agnostic: +//! - [`Receiver::recv`] yields inbound messages +//! - [`Sender::send`] accepts outbound messages +//! +//! Transport-specific adapters, including protobuf or gRPC bridges, live in the +//! crates that own those boundaries rather than in `arbiter-proto`. +//! +//! [`Bi`] deliberately does not model request/response correlation. Some +//! transports may carry multiplexed request/response traffic, some may emit +//! out-of-band messages, and some may be one-message-at-a-time state machines. +//! Correlation concerns such as request IDs, pending response maps, and +//! out-of-band routing belong in the adapter or connection layer built on top +//! of [`Bi`], not in this abstraction itself. +//! +//! # Generic Ordering Rule +//! +//! This module consistently uses `Inbound` first and `Outbound` second in +//! generic parameter lists. +//! +//! For [`Receiver`], [`Sender`], and [`Bi`], this means: +//! - `Receiver` +//! - `Sender` +//! - `Bi` +//! +//! Concretely, for [`Bi`]: +//! - `recv() -> Option` +//! - `send(Outbound)` +//! +//! [`expect_message`] is a small helper for linear protocol steps: it reads one +//! inbound message from a transport and extracts a typed value from it, failing +//! if the channel closes or the message shape is not what the caller expected. +//! +//! [`DummyTransport`] is a no-op implementation useful for tests and local +//! actor execution where no real stream exists. +//! +//! # Design Notes +//! +//! - [`Bi::send`] returns [`Error`] only for transport delivery failures, such +//! as a closed outbound channel. +//! - [`Bi::recv`] returns `None` when the underlying transport closes. +//! - Message translation is intentionally out of scope for this module. +use async_trait::async_trait; +use kameo::{error::Infallible, prelude::*}; +use std::marker::PhantomData; + +/// Errors returned by transport adapters implementing [`Bi`]. +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Transport channel is closed")] + ChannelClosed, + #[error("Unexpected message received")] + UnexpectedMessage, +} + +/// Receives one message from `transport` and extracts a value from it using +/// `extractor`. Returns [`Error::ChannelClosed`] if the transport closes and +/// [`Error::UnexpectedMessage`] if `extractor` returns `None`. +pub async fn expect_message( + transport: &mut T, + extractor: F, +) -> Result +where + T: Bi + ?Sized, + F: FnOnce(Inbound) -> Option, +{ + let msg = transport.recv().await.ok_or(Error::ChannelClosed)?; + extractor(msg).ok_or(Error::UnexpectedMessage) +} + +#[async_trait] +pub trait Sender: Send + Sync { + async fn send(&mut self, item: Outbound) -> Result<(), Error>; +} + +#[async_trait] +pub trait Receiver: Send + Sync { + async fn recv(&mut self) -> Option; +} + +/// Minimal bidirectional transport abstraction used by protocol code. +/// +/// `Bi` is the combined duplex form of [`Sender`] and +/// [`Receiver`]. +/// +/// It models a channel with: +/// - inbound items of type `Inbound` read via [`Bi::recv`] +/// - outbound items of type `Outbound` written via [`Bi::send`] +/// +/// It does not imply request/response sequencing, one-at-a-time exchange, or +/// any built-in correlation mechanism between inbound and outbound items. +pub trait Bi: Sender + Receiver + Send + Sync {} + +#[async_trait] +impl Sender for &mut T +where + T: Sender + ?Sized, + Outbound: Send + 'static, +{ + async fn send(&mut self, item: Outbound) -> Result<(), Error> { + (**self).send(item).await + } +} + +#[async_trait] +impl Receiver for &mut T +where + T: Receiver + ?Sized, + Inbound: Send + 'static, +{ + async fn recv(&mut self) -> Option { + (**self).recv().await + } +} + +impl Bi for &mut T +where + T: Bi + ?Sized, + Inbound: Send + 'static, + Outbound: Send + 'static, +{ +} + +pub trait SplittableBi: Bi { + type Sender: Sender; + type Receiver: Receiver; + + fn split(self) -> (Self::Sender, Self::Receiver); + fn from_parts(sender: Self::Sender, receiver: Self::Receiver) -> Self; +} + +/// No-op [`Bi`] transport for tests and manual actor usage. +/// +/// `send` drops all items and succeeds. [`Bi::recv`] never resolves and therefore +/// does not busy-wait or spuriously close the stream. +pub struct DummyTransport { + _marker: PhantomData<(Inbound, Outbound)>, +} + +impl Default for DummyTransport { + fn default() -> Self { + Self { + _marker: PhantomData, + } + } +} + +#[async_trait] +impl Sender for DummyTransport +where + Inbound: Send + Sync + 'static, + Outbound: Send + Sync + 'static, +{ + async fn send(&mut self, _item: Outbound) -> Result<(), Error> { + Ok(()) + } +} + +#[async_trait] +impl Receiver for DummyTransport +where + Inbound: Send + Sync + 'static, + Outbound: Send + Sync + 'static, +{ + async fn recv(&mut self) -> Option { + std::future::pending::<()>().await; + None + } +} + +impl Bi for DummyTransport +where + Inbound: Send + Sync + 'static, + Outbound: Send + Sync + 'static, +{ +} + +pub mod grpc; + +#[derive(thiserror::Error, Debug)] +pub enum ForwardError { + #[error("Transport error: {0}")] + Transport(#[from] Error), + #[error("Actor delivery error: {0}")] + Actor(SendError), +} + +pub async fn forward_to_actor( + transport: &mut Transport, + actor: &ActorRef, +) -> Result<(), ForwardError> +where + Transport: Bi::Ok>, + Handler: Actor + Message, + Inbound: Send + 'static, + Outbound: Send + 'static + Reply, // `Infallible` to enforce contract that `Outbound` carries handler-level error +{ + while let Some(request) = transport.recv().await { + let resp = actor.ask(request).await.map_err(ForwardError::Actor)?; + transport.send(resp).await? + } + + Err(Error::ChannelClosed.into()) +} diff --git a/server/crates/arbiter-proto/src/transport/grpc.rs b/server/crates/arbiter-proto/src/transport/grpc.rs index 17b3c27..5a8a9cb 100644 --- a/server/crates/arbiter-proto/src/transport/grpc.rs +++ b/server/crates/arbiter-proto/src/transport/grpc.rs @@ -1,106 +1,106 @@ -use super::{Bi, Receiver, Sender}; - -use async_trait::async_trait; -use futures::StreamExt; -use tokio::sync::mpsc; -use tokio_stream::wrappers::ReceiverStream; - -pub struct GrpcSender { - tx: mpsc::Sender>, -} - -#[async_trait] -impl Sender> for GrpcSender -where - Outbound: Send + Sync + 'static, -{ - async fn send(&mut self, item: Result) -> Result<(), super::Error> { - self.tx - .send(item) - .await - .map_err(|_| super::Error::ChannelClosed) - } -} - -pub struct GrpcReceiver { - rx: tonic::Streaming, -} -#[async_trait] -impl Receiver> for GrpcReceiver -where - Inbound: Send + Sync + 'static, -{ - async fn recv(&mut self) -> Option> { - self.rx.next().await - } -} - -pub struct GrpcBi { - sender: GrpcSender, - receiver: GrpcReceiver, -} - -impl GrpcBi -where - Inbound: Send + Sync + 'static, - Outbound: Send + Sync + 'static, -{ - pub fn from_bi_stream( - receiver: tonic::Streaming, - ) -> (Self, ReceiverStream>) { - let (tx, rx) = mpsc::channel(10); - let sender = GrpcSender { tx }; - let receiver = GrpcReceiver { rx: receiver }; - let bi = GrpcBi { sender, receiver }; - (bi, ReceiverStream::new(rx)) - } -} - -#[async_trait] -impl Sender> for GrpcBi -where - Inbound: Send + Sync + 'static, - Outbound: Send + Sync + 'static, -{ - async fn send(&mut self, item: Result) -> Result<(), super::Error> { - self.sender.send(item).await - } -} - -#[async_trait] -impl Receiver> for GrpcBi -where - Inbound: Send + Sync + 'static, - Outbound: Send + Sync + 'static, -{ - async fn recv(&mut self) -> Option> { - self.receiver.recv().await - } -} - -impl Bi, Result> - for GrpcBi -where - Inbound: Send + Sync + 'static, - Outbound: Send + Sync + 'static, -{ -} - -impl - super::SplittableBi, Result> - for GrpcBi -where - Inbound: Send + Sync + 'static, - Outbound: Send + Sync + 'static, -{ - type Sender = GrpcSender; - type Receiver = GrpcReceiver; - - fn split(self) -> (Self::Sender, Self::Receiver) { - (self.sender, self.receiver) - } - - fn from_parts(sender: Self::Sender, receiver: Self::Receiver) -> Self { - GrpcBi { sender, receiver } - } -} +use super::{Bi, Receiver, Sender}; + +use async_trait::async_trait; +use futures::StreamExt; +use tokio::sync::mpsc; +use tokio_stream::wrappers::ReceiverStream; + +pub struct GrpcSender { + tx: mpsc::Sender>, +} + +#[async_trait] +impl Sender> for GrpcSender +where + Outbound: Send + Sync + 'static, +{ + async fn send(&mut self, item: Result) -> Result<(), super::Error> { + self.tx + .send(item) + .await + .map_err(|_| super::Error::ChannelClosed) + } +} + +pub struct GrpcReceiver { + rx: tonic::Streaming, +} +#[async_trait] +impl Receiver> for GrpcReceiver +where + Inbound: Send + Sync + 'static, +{ + async fn recv(&mut self) -> Option> { + self.rx.next().await + } +} + +pub struct GrpcBi { + sender: GrpcSender, + receiver: GrpcReceiver, +} + +impl GrpcBi +where + Inbound: Send + Sync + 'static, + Outbound: Send + Sync + 'static, +{ + pub fn from_bi_stream( + receiver: tonic::Streaming, + ) -> (Self, ReceiverStream>) { + let (tx, rx) = mpsc::channel(10); + let sender = GrpcSender { tx }; + let receiver = GrpcReceiver { rx: receiver }; + let bi = GrpcBi { sender, receiver }; + (bi, ReceiverStream::new(rx)) + } +} + +#[async_trait] +impl Sender> for GrpcBi +where + Inbound: Send + Sync + 'static, + Outbound: Send + Sync + 'static, +{ + async fn send(&mut self, item: Result) -> Result<(), super::Error> { + self.sender.send(item).await + } +} + +#[async_trait] +impl Receiver> for GrpcBi +where + Inbound: Send + Sync + 'static, + Outbound: Send + Sync + 'static, +{ + async fn recv(&mut self) -> Option> { + self.receiver.recv().await + } +} + +impl Bi, Result> + for GrpcBi +where + Inbound: Send + Sync + 'static, + Outbound: Send + Sync + 'static, +{ +} + +impl + super::SplittableBi, Result> + for GrpcBi +where + Inbound: Send + Sync + 'static, + Outbound: Send + Sync + 'static, +{ + type Sender = GrpcSender; + type Receiver = GrpcReceiver; + + fn split(self) -> (Self::Sender, Self::Receiver) { + (self.sender, self.receiver) + } + + fn from_parts(sender: Self::Sender, receiver: Self::Receiver) -> Self { + GrpcBi { sender, receiver } + } +} diff --git a/server/crates/arbiter-proto/src/url.rs b/server/crates/arbiter-proto/src/url.rs index abcf50c..36c98cb 100644 --- a/server/crates/arbiter-proto/src/url.rs +++ b/server/crates/arbiter-proto/src/url.rs @@ -1,128 +1,128 @@ -use base64::{Engine as _, prelude::BASE64_URL_SAFE}; -use rustls_pki_types::CertificateDer; -use std::fmt::Display; - -const ARBITER_URL_SCHEME: &str = "arbiter"; -const CERT_QUERY_KEY: &str = "cert"; -const BOOTSTRAP_TOKEN_QUERY_KEY: &str = "bootstrap_token"; - -#[derive(Debug, Clone)] -pub struct ArbiterUrl { - pub host: String, - pub port: u16, - pub ca_cert: CertificateDer<'static>, - pub bootstrap_token: Option, -} - -impl Display for ArbiterUrl { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut base = format!( - "{ARBITER_URL_SCHEME}://{}:{}?{CERT_QUERY_KEY}={}", - self.host, - self.port, - BASE64_URL_SAFE.encode(&self.ca_cert) - ); - if let Some(token) = &self.bootstrap_token { - base.push_str(&format!("&{BOOTSTRAP_TOKEN_QUERY_KEY}={}", token)); - } - f.write_str(&base) - } -} - -#[derive(Debug, thiserror::Error, miette::Diagnostic)] -pub enum Error { - #[error("Invalid URL scheme, expected '{ARBITER_URL_SCHEME}://'")] - #[diagnostic( - code(arbiter::url::invalid_scheme), - help("The URL must start with '{ARBITER_URL_SCHEME}://'") - )] - InvalidScheme, - #[error("Missing host in URL")] - #[diagnostic( - code(arbiter::url::missing_host), - help("The URL must include a host, e.g., '{ARBITER_URL_SCHEME}://127.0.0.1:'") - )] - MissingHost, - #[error("Missing port in URL")] - #[diagnostic( - code(arbiter::url::missing_port), - help("The URL must include a port, e.g., '{ARBITER_URL_SCHEME}://127.0.0.1:1234'") - )] - MissingPort, - #[error("Missing 'cert' query parameter in URL")] - #[diagnostic( - code(arbiter::url::missing_cert), - help("The URL must include a 'cert' query parameter") - )] - MissingCert, - #[error("Invalid base64 in 'cert' query parameter: {0}")] - #[diagnostic(code(arbiter::url::invalid_cert_base64))] - InvalidCertBase64(#[from] base64::DecodeError), -} - -impl<'a> TryFrom<&'a str> for ArbiterUrl { - type Error = Error; - - fn try_from(value: &'a str) -> Result { - let url = url::Url::parse(value).map_err(|_| Error::InvalidScheme)?; - - if url.scheme() != ARBITER_URL_SCHEME { - return Err(Error::InvalidScheme); - } - - let host = url.host_str().ok_or(Error::MissingHost)?.to_string(); - let port = url.port().ok_or(Error::MissingPort)?; - let cert_str = url - .query_pairs() - .find(|(k, _)| k == CERT_QUERY_KEY) - .ok_or(Error::MissingCert)? - .1; - - let cert = BASE64_URL_SAFE.decode(cert_str.as_ref())?; - let cert = CertificateDer::from_slice(&cert).into_owned(); - - let bootstrap_token = url - .query_pairs() - .find(|(k, _)| k == BOOTSTRAP_TOKEN_QUERY_KEY) - .map(|(_, v)| v.to_string()); - - Ok(ArbiterUrl { - host, - port, - ca_cert: cert, - bootstrap_token, - }) - } -} - -#[cfg(test)] -mod tests { - use rcgen::generate_simple_self_signed; - use rstest::rstest; - - use super::*; - - #[rstest] - - fn parsing_correctness( - #[values("127.0.0.1", "localhost", "192.168.1.1", "some.domain.com")] host: &str, - - #[values(None, Some("token123".to_string()))] bootstrap_token: Option, - ) { - let cert = generate_simple_self_signed(&["Arbiter CA".into()]).unwrap(); - let cert = cert.cert.der(); - - let url = ArbiterUrl { - host: host.to_string(), - port: 1234, - ca_cert: cert.clone().into_owned(), - bootstrap_token, - }; - let url_str = url.to_string(); - let parsed_url = ArbiterUrl::try_from(url_str.as_str()).unwrap(); - assert_eq!(url.host, parsed_url.host); - assert_eq!(url.port, parsed_url.port); - assert_eq!(url.ca_cert.to_vec(), parsed_url.ca_cert.to_vec()); - assert_eq!(url.bootstrap_token, parsed_url.bootstrap_token); - } -} +use base64::{Engine as _, prelude::BASE64_URL_SAFE}; +use rustls_pki_types::CertificateDer; +use std::fmt::Display; + +const ARBITER_URL_SCHEME: &str = "arbiter"; +const CERT_QUERY_KEY: &str = "cert"; +const BOOTSTRAP_TOKEN_QUERY_KEY: &str = "bootstrap_token"; + +#[derive(Debug, Clone)] +pub struct ArbiterUrl { + pub host: String, + pub port: u16, + pub ca_cert: CertificateDer<'static>, + pub bootstrap_token: Option, +} + +impl Display for ArbiterUrl { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut base = format!( + "{ARBITER_URL_SCHEME}://{}:{}?{CERT_QUERY_KEY}={}", + self.host, + self.port, + BASE64_URL_SAFE.encode(&self.ca_cert) + ); + if let Some(token) = &self.bootstrap_token { + base.push_str(&format!("&{BOOTSTRAP_TOKEN_QUERY_KEY}={}", token)); + } + f.write_str(&base) + } +} + +#[derive(Debug, thiserror::Error, miette::Diagnostic)] +pub enum Error { + #[error("Invalid URL scheme, expected '{ARBITER_URL_SCHEME}://'")] + #[diagnostic( + code(arbiter::url::invalid_scheme), + help("The URL must start with '{ARBITER_URL_SCHEME}://'") + )] + InvalidScheme, + #[error("Missing host in URL")] + #[diagnostic( + code(arbiter::url::missing_host), + help("The URL must include a host, e.g., '{ARBITER_URL_SCHEME}://127.0.0.1:'") + )] + MissingHost, + #[error("Missing port in URL")] + #[diagnostic( + code(arbiter::url::missing_port), + help("The URL must include a port, e.g., '{ARBITER_URL_SCHEME}://127.0.0.1:1234'") + )] + MissingPort, + #[error("Missing 'cert' query parameter in URL")] + #[diagnostic( + code(arbiter::url::missing_cert), + help("The URL must include a 'cert' query parameter") + )] + MissingCert, + #[error("Invalid base64 in 'cert' query parameter: {0}")] + #[diagnostic(code(arbiter::url::invalid_cert_base64))] + InvalidCertBase64(#[from] base64::DecodeError), +} + +impl<'a> TryFrom<&'a str> for ArbiterUrl { + type Error = Error; + + fn try_from(value: &'a str) -> Result { + let url = url::Url::parse(value).map_err(|_| Error::InvalidScheme)?; + + if url.scheme() != ARBITER_URL_SCHEME { + return Err(Error::InvalidScheme); + } + + let host = url.host_str().ok_or(Error::MissingHost)?.to_string(); + let port = url.port().ok_or(Error::MissingPort)?; + let cert_str = url + .query_pairs() + .find(|(k, _)| k == CERT_QUERY_KEY) + .ok_or(Error::MissingCert)? + .1; + + let cert = BASE64_URL_SAFE.decode(cert_str.as_ref())?; + let cert = CertificateDer::from_slice(&cert).into_owned(); + + let bootstrap_token = url + .query_pairs() + .find(|(k, _)| k == BOOTSTRAP_TOKEN_QUERY_KEY) + .map(|(_, v)| v.to_string()); + + Ok(ArbiterUrl { + host, + port, + ca_cert: cert, + bootstrap_token, + }) + } +} + +#[cfg(test)] +mod tests { + use rcgen::generate_simple_self_signed; + use rstest::rstest; + + use super::*; + + #[rstest] + + fn parsing_correctness( + #[values("127.0.0.1", "localhost", "192.168.1.1", "some.domain.com")] host: &str, + + #[values(None, Some("token123".to_string()))] bootstrap_token: Option, + ) { + let cert = generate_simple_self_signed(&["Arbiter CA".into()]).unwrap(); + let cert = cert.cert.der(); + + let url = ArbiterUrl { + host: host.to_string(), + port: 1234, + ca_cert: cert.clone().into_owned(), + bootstrap_token, + }; + let url_str = url.to_string(); + let parsed_url = ArbiterUrl::try_from(url_str.as_str()).unwrap(); + assert_eq!(url.host, parsed_url.host); + assert_eq!(url.port, parsed_url.port); + assert_eq!(url.ca_cert.to_vec(), parsed_url.ca_cert.to_vec()); + assert_eq!(url.bootstrap_token, parsed_url.bootstrap_token); + } +} diff --git a/server/crates/arbiter-server/Cargo.toml b/server/crates/arbiter-server/Cargo.toml index 7790bd6..00ad3f1 100644 --- a/server/crates/arbiter-server/Cargo.toml +++ b/server/crates/arbiter-server/Cargo.toml @@ -1,61 +1,61 @@ -[package] -name = "arbiter-server" -version = "0.1.0" -edition = "2024" -repository = "https://git.markettakers.org/MarketTakers/arbiter" -license = "Apache-2.0" - -[lints] -workspace = true - -[dependencies] -diesel = { version = "2.3.9", features = ["chrono", "returning_clauses_for_sqlite_3_35", "serde_json", "time", "uuid"] } -diesel-async = { version = "0.9.0", features = [ - "bb8", - "migrations", - "sqlite", - "tokio", -] } -arbiter-proto.path = "../arbiter-proto" -arbiter-crypto.path = "../arbiter-crypto" -arbiter-macros.path = "../arbiter-macros" -tracing.workspace = true -tracing-subscriber = { version = "0.3", features = ["env-filter"] } -tonic.workspace = true -tonic.features = ["tls-aws-lc"] -tokio.workspace = true -rustls.workspace = true -smlang.workspace = true -thiserror.workspace = true -diesel_migrations = { version = "2.3.2", features = ["sqlite"] } -async-trait.workspace = true -tokio-stream.workspace = true -rand.workspace = true -rcgen.workspace = true -chrono.workspace = true -kameo.workspace = true -chacha20poly1305 = { version = "0.10.1", features = ["std"] } -argon2 = { version = "0.5.3", features = ["zeroize"] } -restructed = "0.2.2" -strum = { version = "0.28.0", features = ["derive"] } -pem = "3.0.6" -sha2.workspace = true -hmac.workspace = true -alloy.workspace = true -prost-types.workspace = true -arbiter-tokens-registry.path = "../arbiter-tokens-registry" -anyhow = "1.0.102" -mutants.workspace = true -subtle = "2.6.1" -x25519-dalek.workspace = true -k256.workspace = true -kameo_actors.workspace = true - -[dev-dependencies] -proptest = "1.11.0" -rstest.workspace = true -test-log = { version = "0.2", default-features = false, features = ["trace"] } -ml-dsa.workspace = true - -[lib] -doctest = false +[package] +name = "arbiter-server" +version = "0.1.0" +edition = "2024" +repository = "https://git.markettakers.org/MarketTakers/arbiter" +license = "Apache-2.0" + +[lints] +workspace = true + +[dependencies] +diesel = { version = "2.3.9", features = ["chrono", "returning_clauses_for_sqlite_3_35", "serde_json", "time", "uuid"] } +diesel-async = { version = "0.9.0", features = [ + "bb8", + "migrations", + "sqlite", + "tokio", +] } +arbiter-proto.path = "../arbiter-proto" +arbiter-crypto.path = "../arbiter-crypto" +arbiter-macros.path = "../arbiter-macros" +tracing.workspace = true +tracing-subscriber = { version = "0.3", features = ["env-filter"] } +tonic.workspace = true +tonic.features = ["tls-aws-lc"] +tokio.workspace = true +rustls.workspace = true +smlang.workspace = true +thiserror.workspace = true +diesel_migrations = { version = "2.3.2", features = ["sqlite"] } +async-trait.workspace = true +tokio-stream.workspace = true +rand.workspace = true +rcgen.workspace = true +chrono.workspace = true +kameo.workspace = true +chacha20poly1305 = { version = "0.10.1", features = ["std"] } +argon2 = { version = "0.5.3", features = ["zeroize"] } +restructed = "0.2.2" +strum = { version = "0.28.0", features = ["derive"] } +pem = "3.0.6" +sha2.workspace = true +hmac.workspace = true +alloy.workspace = true +prost-types.workspace = true +arbiter-tokens-registry.path = "../arbiter-tokens-registry" +anyhow = "1.0.102" +mutants.workspace = true +subtle = "2.6.1" +x25519-dalek.workspace = true +k256.workspace = true +kameo_actors.workspace = true + +[dev-dependencies] +proptest = "1.11.0" +rstest.workspace = true +test-log = { version = "0.2", default-features = false, features = ["trace"] } +ml-dsa.workspace = true + +[lib] +doctest = false diff --git a/server/crates/arbiter-server/diesel.toml b/server/crates/arbiter-server/diesel.toml index bb1d1f7..9379a05 100644 --- a/server/crates/arbiter-server/diesel.toml +++ b/server/crates/arbiter-server/diesel.toml @@ -1,9 +1,9 @@ -# For documentation on how to configure this file, -# see https://diesel.rs/guides/configuring-diesel-cli - -[print_schema] -file = "src/db/schema.rs" -custom_type_derives = ["diesel::query_builder::QueryId", "Clone"] - -[migrations_directory] -dir = "migrations" +# For documentation on how to configure this file, +# see https://diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/db/schema.rs" +custom_type_derives = ["diesel::query_builder::QueryId", "Clone"] + +[migrations_directory] +dir = "migrations" diff --git a/server/crates/arbiter-server/migrations/2026-02-14-171124-0000_init/down.sql b/server/crates/arbiter-server/migrations/2026-02-14-171124-0000_init/down.sql index d9a93fe..48fc443 100644 --- a/server/crates/arbiter-server/migrations/2026-02-14-171124-0000_init/down.sql +++ b/server/crates/arbiter-server/migrations/2026-02-14-171124-0000_init/down.sql @@ -1 +1 @@ --- This file should undo anything in `up.sql` +-- This file should undo anything in `up.sql` diff --git a/server/crates/arbiter-server/migrations/2026-02-14-171124-0000_init/up.sql b/server/crates/arbiter-server/migrations/2026-02-14-171124-0000_init/up.sql index 0ab9a3f..35af702 100644 --- a/server/crates/arbiter-server/migrations/2026-02-14-171124-0000_init/up.sql +++ b/server/crates/arbiter-server/migrations/2026-02-14-171124-0000_init/up.sql @@ -1,206 +1,206 @@ -create table if not exists root_key_history ( - id INTEGER not null PRIMARY KEY, - -- root key stored as aead encrypted artifact, with only difference that it's decrypted by unseal key (derived from user password) - root_key_encryption_nonce blob not null default(1), -- if re-encrypted, this should be incremented. Used for encrypting root key - data_encryption_nonce blob not null default(1), -- nonce used for encrypting with key itself - ciphertext blob not null, - tag blob not null, - schema_version integer not null default(1), -- server would need to reencrypt, because this means that we have changed algorithm - salt blob not null -- for key deriviation -) STRICT; - -create table if not exists aead_encrypted ( - id INTEGER not null PRIMARY KEY, - current_nonce blob not null default(1), -- if re-encrypted, this should be incremented - ciphertext blob not null, - tag blob not null, - schema_version integer not null default(1), -- server would need to reencrypt, because this means that we have changed algorithm - associated_root_key_id integer not null references root_key_history (id) on delete RESTRICT, - created_at integer not null default(unixepoch ('now')) -) STRICT; - -create unique index if not exists uniq_nonce_per_root_key on aead_encrypted ( - current_nonce, - associated_root_key_id -); - -create table if not exists tls_history ( - id INTEGER not null PRIMARY KEY, - cert text not null, - cert_key text not null, -- PEM Encoded private key - ca_cert text not null, - ca_key text not null, -- PEM Encoded private key - created_at integer not null default(unixepoch ('now')) -) STRICT; - --- This is a singleton -create table if not exists arbiter_settings ( - id INTEGER not null PRIMARY KEY CHECK (id = 1), -- singleton row, id must be 1 - root_key_id integer references root_key_history (id) on delete RESTRICT, -- if null, means wasn't bootstrapped yet - tls_id integer references tls_history (id) on delete RESTRICT -) STRICT; - -insert into arbiter_settings (id) values (1) on conflict do nothing; --- ensure singleton row exists - -create table if not exists operator_client ( - id integer not null primary key, - public_key blob not null, - created_at integer not null default(unixepoch ('now')), - updated_at integer not null default(unixepoch ('now')) -) STRICT; -create unique index if not exists uniq_operator_client_public_key on operator_client (public_key); - -create table if not exists client_metadata ( - id integer not null primary key, - name text not null, -- human-readable name for the client - description text, -- optional description for the client - version text, -- client version for tracking and debugging - created_at integer not null default(unixepoch ('now')) -) STRICT; - --- created to track history of changes -create table if not exists client_metadata_history ( - id integer not null primary key, - metadata_id integer not null references client_metadata (id) on delete cascade, - client_id integer not null references program_client (id) on delete cascade, - created_at integer not null default(unixepoch ('now')) -) STRICT; - -create unique index if not exists uniq_metadata_binding_client on client_metadata_history (client_id); - -create table if not exists program_client ( - id integer not null primary key, - public_key blob not null, - metadata_id integer not null references client_metadata (id) on delete cascade, - created_at integer not null default(unixepoch ('now')), - updated_at integer not null default(unixepoch ('now')) -) STRICT; - -create unique index if not exists program_client_public_key_unique - on program_client (public_key); - -create unique index if not exists uniq_program_client_public_key on program_client (public_key); - -create table if not exists evm_wallet ( - id integer not null primary key, - address blob not null, -- 20-byte Ethereum address - aead_encrypted_id integer not null references aead_encrypted (id) on delete RESTRICT, - created_at integer not null default(unixepoch ('now')) -) STRICT; - -create unique index if not exists uniq_evm_wallet_address on evm_wallet (address); - -create unique index if not exists uniq_evm_wallet_aead on evm_wallet (aead_encrypted_id); - -create table if not exists evm_wallet_access ( - id integer not null primary key, - wallet_id integer not null references evm_wallet (id) on delete cascade, - client_id integer not null references program_client (id) on delete cascade, - created_at integer not null default(unixepoch ('now')) -) STRICT; - -create unique index if not exists uniq_wallet_access on evm_wallet_access (wallet_id, client_id); - -create table if not exists evm_ether_transfer_limit ( - id integer not null primary key, - window_secs integer not null, -- window duration in seconds - max_volume blob not null -- big-endian 32-byte U256 -) STRICT; - --- Shared grant properties: client scope, timeframe, fee caps, and rate limit -create table if not exists evm_basic_grant ( - id integer not null primary key, - wallet_access_id integer not null references evm_wallet_access (id) on delete restrict, - chain_id integer not null, -- EIP-155 chain ID - valid_from integer, -- unix timestamp (seconds), null = no lower bound - valid_until integer, -- unix timestamp (seconds), null = no upper bound - max_gas_fee_per_gas blob, -- big-endian 32-byte U256, null = unlimited - max_priority_fee_per_gas blob, -- big-endian 32-byte U256, null = unlimited - rate_limit_count integer, -- max transactions in window, null = unlimited - rate_limit_window_secs integer, -- window duration in seconds, null = unlimited - revoked_at integer, -- unix timestamp when revoked, null = still active - created_at integer not null default(unixepoch ('now')) -) STRICT; - --- Shared transaction log for all EVM grants, used for rate limit tracking and auditing -create table if not exists evm_transaction_log ( - id integer not null primary key, - wallet_access_id integer not null references evm_wallet_access (id) on delete restrict, - grant_id integer not null references evm_basic_grant (id) on delete restrict, - chain_id integer not null, - eth_value blob not null, -- always present on any EVM tx - signed_at integer not null default(unixepoch ('now')) -) STRICT; - -create index if not exists idx_evm_basic_grant_access_chain on evm_basic_grant (wallet_access_id, chain_id); - --- =============================== --- ERC20 token transfer grant --- =============================== -create table if not exists evm_token_transfer_grant ( - id integer not null primary key, - basic_grant_id integer not null unique references evm_basic_grant (id) on delete cascade, - token_contract blob not null, -- 20-byte ERC20 contract address - receiver blob -- 20-byte recipient address or null if every recipient allowed -) STRICT; - --- Per-window volume limits for token transfer grants -create table if not exists evm_token_transfer_volume_limit ( - id integer not null primary key, - grant_id integer not null references evm_token_transfer_grant (id) on delete cascade, - window_secs integer not null, -- window duration in seconds - max_volume blob not null -- big-endian 32-byte U256 -) STRICT; - --- Log table for token transfer grant usage -create table if not exists evm_token_transfer_log ( - id integer not null primary key, - grant_id integer not null references evm_token_transfer_grant (id) on delete restrict, - log_id integer not null references evm_transaction_log (id) on delete restrict, - chain_id integer not null, -- EIP-155 chain ID - token_contract blob not null, -- 20-byte ERC20 contract address - recipient_address blob not null, -- 20-byte recipient address - value blob not null, -- big-endian 32-byte U256 - created_at integer not null default(unixepoch ('now')) -) STRICT; - -create index if not exists idx_token_transfer_log_grant on evm_token_transfer_log (grant_id); - -create index if not exists idx_token_transfer_log_log_id on evm_token_transfer_log (log_id); - -create index if not exists idx_token_transfer_log_chain on evm_token_transfer_log (chain_id); - --- =============================== --- Ether transfer grant (uses base log) --- =============================== -create table if not exists evm_ether_transfer_grant ( - id integer not null primary key, - basic_grant_id integer not null unique references evm_basic_grant (id) on delete cascade, - limit_id integer not null references evm_ether_transfer_limit (id) on delete restrict -) STRICT; - --- Specific recipient addresses for an ether transfer grant -create table if not exists evm_ether_transfer_grant_target ( - id integer not null primary key, - grant_id integer not null references evm_ether_transfer_grant (id) on delete cascade, - address blob not null -- 20-byte recipient address -) STRICT; - -create unique index if not exists uniq_ether_transfer_target on evm_ether_transfer_grant_target (grant_id, address); - --- =============================== --- Integrity Envelopes --- =============================== -create table if not exists integrity_envelope ( - id integer not null primary key, - entity_kind text not null, - entity_id blob not null, - payload_version integer not null, - key_version integer not null, - mac blob not null, -- 20-byte recipient address - signed_at integer not null default(unixepoch ('now')), - created_at integer not null default(unixepoch ('now')) -) STRICT; - -create unique index if not exists uniq_integrity_envelope_entity on integrity_envelope (entity_kind, entity_id); +create table if not exists root_key_history ( + id INTEGER not null PRIMARY KEY, + -- root key stored as aead encrypted artifact, with only difference that it's decrypted by unseal key (derived from user password) + root_key_encryption_nonce blob not null default(1), -- if re-encrypted, this should be incremented. Used for encrypting root key + data_encryption_nonce blob not null default(1), -- nonce used for encrypting with key itself + ciphertext blob not null, + tag blob not null, + schema_version integer not null default(1), -- server would need to reencrypt, because this means that we have changed algorithm + salt blob not null -- for key deriviation +) STRICT; + +create table if not exists aead_encrypted ( + id INTEGER not null PRIMARY KEY, + current_nonce blob not null default(1), -- if re-encrypted, this should be incremented + ciphertext blob not null, + tag blob not null, + schema_version integer not null default(1), -- server would need to reencrypt, because this means that we have changed algorithm + associated_root_key_id integer not null references root_key_history (id) on delete RESTRICT, + created_at integer not null default(unixepoch ('now')) +) STRICT; + +create unique index if not exists uniq_nonce_per_root_key on aead_encrypted ( + current_nonce, + associated_root_key_id +); + +create table if not exists tls_history ( + id INTEGER not null PRIMARY KEY, + cert text not null, + cert_key text not null, -- PEM Encoded private key + ca_cert text not null, + ca_key text not null, -- PEM Encoded private key + created_at integer not null default(unixepoch ('now')) +) STRICT; + +-- This is a singleton +create table if not exists arbiter_settings ( + id INTEGER not null PRIMARY KEY CHECK (id = 1), -- singleton row, id must be 1 + root_key_id integer references root_key_history (id) on delete RESTRICT, -- if null, means wasn't bootstrapped yet + tls_id integer references tls_history (id) on delete RESTRICT +) STRICT; + +insert into arbiter_settings (id) values (1) on conflict do nothing; +-- ensure singleton row exists + +create table if not exists operator_client ( + id integer not null primary key, + public_key blob not null, + created_at integer not null default(unixepoch ('now')), + updated_at integer not null default(unixepoch ('now')) +) STRICT; +create unique index if not exists uniq_operator_client_public_key on operator_client (public_key); + +create table if not exists client_metadata ( + id integer not null primary key, + name text not null, -- human-readable name for the client + description text, -- optional description for the client + version text, -- client version for tracking and debugging + created_at integer not null default(unixepoch ('now')) +) STRICT; + +-- created to track history of changes +create table if not exists client_metadata_history ( + id integer not null primary key, + metadata_id integer not null references client_metadata (id) on delete cascade, + client_id integer not null references program_client (id) on delete cascade, + created_at integer not null default(unixepoch ('now')) +) STRICT; + +create unique index if not exists uniq_metadata_binding_client on client_metadata_history (client_id); + +create table if not exists program_client ( + id integer not null primary key, + public_key blob not null, + metadata_id integer not null references client_metadata (id) on delete cascade, + created_at integer not null default(unixepoch ('now')), + updated_at integer not null default(unixepoch ('now')) +) STRICT; + +create unique index if not exists program_client_public_key_unique + on program_client (public_key); + +create unique index if not exists uniq_program_client_public_key on program_client (public_key); + +create table if not exists evm_wallet ( + id integer not null primary key, + address blob not null, -- 20-byte Ethereum address + aead_encrypted_id integer not null references aead_encrypted (id) on delete RESTRICT, + created_at integer not null default(unixepoch ('now')) +) STRICT; + +create unique index if not exists uniq_evm_wallet_address on evm_wallet (address); + +create unique index if not exists uniq_evm_wallet_aead on evm_wallet (aead_encrypted_id); + +create table if not exists evm_wallet_access ( + id integer not null primary key, + wallet_id integer not null references evm_wallet (id) on delete cascade, + client_id integer not null references program_client (id) on delete cascade, + created_at integer not null default(unixepoch ('now')) +) STRICT; + +create unique index if not exists uniq_wallet_access on evm_wallet_access (wallet_id, client_id); + +create table if not exists evm_ether_transfer_limit ( + id integer not null primary key, + window_secs integer not null, -- window duration in seconds + max_volume blob not null -- big-endian 32-byte U256 +) STRICT; + +-- Shared grant properties: client scope, timeframe, fee caps, and rate limit +create table if not exists evm_basic_grant ( + id integer not null primary key, + wallet_access_id integer not null references evm_wallet_access (id) on delete restrict, + chain_id integer not null, -- EIP-155 chain ID + valid_from integer, -- unix timestamp (seconds), null = no lower bound + valid_until integer, -- unix timestamp (seconds), null = no upper bound + max_gas_fee_per_gas blob, -- big-endian 32-byte U256, null = unlimited + max_priority_fee_per_gas blob, -- big-endian 32-byte U256, null = unlimited + rate_limit_count integer, -- max transactions in window, null = unlimited + rate_limit_window_secs integer, -- window duration in seconds, null = unlimited + revoked_at integer, -- unix timestamp when revoked, null = still active + created_at integer not null default(unixepoch ('now')) +) STRICT; + +-- Shared transaction log for all EVM grants, used for rate limit tracking and auditing +create table if not exists evm_transaction_log ( + id integer not null primary key, + wallet_access_id integer not null references evm_wallet_access (id) on delete restrict, + grant_id integer not null references evm_basic_grant (id) on delete restrict, + chain_id integer not null, + eth_value blob not null, -- always present on any EVM tx + signed_at integer not null default(unixepoch ('now')) +) STRICT; + +create index if not exists idx_evm_basic_grant_access_chain on evm_basic_grant (wallet_access_id, chain_id); + +-- =============================== +-- ERC20 token transfer grant +-- =============================== +create table if not exists evm_token_transfer_grant ( + id integer not null primary key, + basic_grant_id integer not null unique references evm_basic_grant (id) on delete cascade, + token_contract blob not null, -- 20-byte ERC20 contract address + receiver blob -- 20-byte recipient address or null if every recipient allowed +) STRICT; + +-- Per-window volume limits for token transfer grants +create table if not exists evm_token_transfer_volume_limit ( + id integer not null primary key, + grant_id integer not null references evm_token_transfer_grant (id) on delete cascade, + window_secs integer not null, -- window duration in seconds + max_volume blob not null -- big-endian 32-byte U256 +) STRICT; + +-- Log table for token transfer grant usage +create table if not exists evm_token_transfer_log ( + id integer not null primary key, + grant_id integer not null references evm_token_transfer_grant (id) on delete restrict, + log_id integer not null references evm_transaction_log (id) on delete restrict, + chain_id integer not null, -- EIP-155 chain ID + token_contract blob not null, -- 20-byte ERC20 contract address + recipient_address blob not null, -- 20-byte recipient address + value blob not null, -- big-endian 32-byte U256 + created_at integer not null default(unixepoch ('now')) +) STRICT; + +create index if not exists idx_token_transfer_log_grant on evm_token_transfer_log (grant_id); + +create index if not exists idx_token_transfer_log_log_id on evm_token_transfer_log (log_id); + +create index if not exists idx_token_transfer_log_chain on evm_token_transfer_log (chain_id); + +-- =============================== +-- Ether transfer grant (uses base log) +-- =============================== +create table if not exists evm_ether_transfer_grant ( + id integer not null primary key, + basic_grant_id integer not null unique references evm_basic_grant (id) on delete cascade, + limit_id integer not null references evm_ether_transfer_limit (id) on delete restrict +) STRICT; + +-- Specific recipient addresses for an ether transfer grant +create table if not exists evm_ether_transfer_grant_target ( + id integer not null primary key, + grant_id integer not null references evm_ether_transfer_grant (id) on delete cascade, + address blob not null -- 20-byte recipient address +) STRICT; + +create unique index if not exists uniq_ether_transfer_target on evm_ether_transfer_grant_target (grant_id, address); + +-- =============================== +-- Integrity Envelopes +-- =============================== +create table if not exists integrity_envelope ( + id integer not null primary key, + entity_kind text not null, + entity_id blob not null, + payload_version integer not null, + key_version integer not null, + mac blob not null, -- 20-byte recipient address + signed_at integer not null default(unixepoch ('now')), + created_at integer not null default(unixepoch ('now')) +) STRICT; + +create unique index if not exists uniq_integrity_envelope_entity on integrity_envelope (entity_kind, entity_id); diff --git a/server/crates/arbiter-server/src/actors/bootstrap.rs b/server/crates/arbiter-server/src/actors/bootstrap.rs index 8ec0059..3ab7f21 100644 --- a/server/crates/arbiter-server/src/actors/bootstrap.rs +++ b/server/crates/arbiter-server/src/actors/bootstrap.rs @@ -1,98 +1,98 @@ -use crate::db::{self, DatabasePool, schema}; -use arbiter_proto::{BOOTSTRAP_PATH, home_path}; - -use diesel::QueryDsl; -use diesel_async::RunQueryDsl; -use kameo::{Actor, messages}; -use rand::{RngExt, distr::Alphanumeric, make_rng, rngs::StdRng}; -use subtle::ConstantTimeEq as _; -use thiserror::Error; - -const TOKEN_LENGTH: usize = 64; - -pub async fn generate_token() -> Result { - let rng: StdRng = make_rng(); - - let token = rng.sample_iter(Alphanumeric).take(TOKEN_LENGTH).fold( - String::default(), - |mut accum, char| { - accum += char.to_string().as_str(); - accum - }, - ); - - tokio::fs::write(home_path()?.join(BOOTSTRAP_PATH), token.as_str()).await?; - - Ok(token) -} - -#[derive(Error, Debug)] -pub enum Error { - #[error("Database error: {0}")] - Database(#[from] db::PoolError), - - #[error("I/O error: {0}")] - Io(#[from] std::io::Error), - - #[error("Database query error: {0}")] - Query(#[from] diesel::result::Error), -} - -#[derive(Actor)] -pub struct Bootstrapper { - token: Option, -} - -impl Bootstrapper { - pub async fn new(db: &DatabasePool) -> Result { - let row_count: i64 = { - let mut conn = db.get().await?; - - schema::operator_client::table - .count() - .get_result(&mut conn) - .await? - }; - - let token = if row_count == 0 { - let token = generate_token().await?; - Some(token) - } else { - None - }; - - Ok(Self { token }) - } -} - -#[messages] -impl Bootstrapper { - #[message] - pub fn is_correct_token(&self, token: String) -> bool { - self.token.as_ref().is_some_and(|expected| { - let expected_bytes = expected.as_bytes(); - let token_bytes = token.as_bytes(); - - let choice = expected_bytes.ct_eq(token_bytes); - bool::from(choice) - }) - } - - #[message] - pub fn consume_token(&mut self, token: String) -> bool { - if self.is_correct_token(token) { - self.token = None; - true - } else { - false - } - } -} - -#[messages] -impl Bootstrapper { - #[message] - pub fn get_token(&self) -> Option { - self.token.clone() - } -} +use crate::db::{self, DatabasePool, schema}; +use arbiter_proto::{BOOTSTRAP_PATH, home_path}; + +use diesel::QueryDsl; +use diesel_async::RunQueryDsl; +use kameo::{Actor, messages}; +use rand::{RngExt, distr::Alphanumeric, make_rng, rngs::StdRng}; +use subtle::ConstantTimeEq as _; +use thiserror::Error; + +const TOKEN_LENGTH: usize = 64; + +pub async fn generate_token() -> Result { + let rng: StdRng = make_rng(); + + let token = rng.sample_iter(Alphanumeric).take(TOKEN_LENGTH).fold( + String::default(), + |mut accum, char| { + accum += char.to_string().as_str(); + accum + }, + ); + + tokio::fs::write(home_path()?.join(BOOTSTRAP_PATH), token.as_str()).await?; + + Ok(token) +} + +#[derive(Error, Debug)] +pub enum Error { + #[error("Database error: {0}")] + Database(#[from] db::PoolError), + + #[error("I/O error: {0}")] + Io(#[from] std::io::Error), + + #[error("Database query error: {0}")] + Query(#[from] diesel::result::Error), +} + +#[derive(Actor)] +pub struct Bootstrapper { + token: Option, +} + +impl Bootstrapper { + pub async fn new(db: &DatabasePool) -> Result { + let row_count: i64 = { + let mut conn = db.get().await?; + + schema::operator_client::table + .count() + .get_result(&mut conn) + .await? + }; + + let token = if row_count == 0 { + let token = generate_token().await?; + Some(token) + } else { + None + }; + + Ok(Self { token }) + } +} + +#[messages] +impl Bootstrapper { + #[message] + pub fn is_correct_token(&self, token: String) -> bool { + self.token.as_ref().is_some_and(|expected| { + let expected_bytes = expected.as_bytes(); + let token_bytes = token.as_bytes(); + + let choice = expected_bytes.ct_eq(token_bytes); + bool::from(choice) + }) + } + + #[message] + pub fn consume_token(&mut self, token: String) -> bool { + if self.is_correct_token(token) { + self.token = None; + true + } else { + false + } + } +} + +#[messages] +impl Bootstrapper { + #[message] + pub fn get_token(&self) -> Option { + self.token.clone() + } +} diff --git a/server/crates/arbiter-server/src/actors/evm/mod.rs b/server/crates/arbiter-server/src/actors/evm/mod.rs index 06e672c..9284b80 100644 --- a/server/crates/arbiter-server/src/actors/evm/mod.rs +++ b/server/crates/arbiter-server/src/actors/evm/mod.rs @@ -1,260 +1,260 @@ -use crate::{ - actors::vault::{CreateNew, Decrypt, Vault}, - crypto::integrity, - db::{ - DatabaseError, DatabasePool, - models::{self}, - schema, - }, - evm::{ - self, ListError, RunKind, - policies::{ - CombinedSettings, Grant, SharedGrantSettings, SpecificGrant, SpecificMeaning, - ether_transfer::EtherTransfer, token_transfers::TokenTransfer, - }, - }, -}; -use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; - -use alloy::{ - consensus::TxEip1559, network::TxSignerSync as _, primitives::Address, signers::Signature, -}; -use diesel::{ - ExpressionMethods, OptionalExtension as _, QueryDsl, SelectableHelper as _, dsl::insert_into, -}; -use diesel_async::RunQueryDsl; -use kameo::{Actor, actor::ActorRef, messages}; -use rand::{SeedableRng, rng, rngs::StdRng}; - -pub use crate::evm::safe_signer; - -#[derive(Debug, thiserror::Error)] -pub enum SignTransactionError { - #[error("Wallet not found")] - WalletNotFound, - - #[error("Database error: {0}")] - Database(#[from] DatabaseError), - - #[error("Vault error: {0}")] - Vault(#[from] crate::actors::vault::Error), - - #[error("Vault mailbox error")] - VaultSend, - - #[error("Signing error: {0}")] - Signing(#[from] alloy::signers::Error), - - #[error("Policy error: {0}")] - Vet(#[from] evm::VetError), -} - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Vault error: {0}")] - Vault(#[from] crate::actors::vault::Error), - - #[error("Vault mailbox error")] - VaultSend, - - #[error("Database error: {0}")] - Database(#[from] DatabaseError), - - #[error("Integrity violation: {0}")] - Integrity(#[from] integrity::Error), -} - -#[derive(Actor)] -pub struct EvmActor { - pub vault: ActorRef, - pub db: DatabasePool, - pub rng: StdRng, - pub engine: evm::Engine, -} - -impl EvmActor { - pub fn new(vault: ActorRef, db: DatabasePool) -> Self { - // is it safe to seed rng from system once? - // todo: audit - let rng = StdRng::from_rng(&mut rng()); - let engine = evm::Engine::new(db.clone(), vault.clone()); - Self { - vault, - db, - rng, - engine, - } - } -} - -#[messages] -impl EvmActor { - #[message] - pub async fn generate(&mut self) -> Result<(i32, Address), Error> { - let (mut key_cell, address) = safe_signer::generate(&mut self.rng); - - let plaintext = key_cell.read_inline(|reader| SafeCell::new(reader.to_vec())); - - let aead_id: i32 = self - .vault - .ask(CreateNew { plaintext }) - .await - .map_err(|_| Error::VaultSend)?; - - let mut conn = self.db.get().await.map_err(DatabaseError::from)?; - let wallet_id = insert_into(schema::evm_wallet::table) - .values(&models::NewEvmWallet { - address: address.as_slice().to_vec(), - aead_encrypted_id: aead_id, - }) - .returning(schema::evm_wallet::id) - .get_result(&mut conn) - .await - .map_err(DatabaseError::from)?; - - Ok((wallet_id, address)) - } - - #[message] - pub async fn list_wallets(&self) -> Result, Error> { - let mut conn = self.db.get().await.map_err(DatabaseError::from)?; - let rows: Vec = schema::evm_wallet::table - .select(models::EvmWallet::as_select()) - .load(&mut conn) - .await - .map_err(DatabaseError::from)?; - - Ok(rows - .into_iter() - .map(|w| (w.id, Address::from_slice(&w.address))) - .collect()) - } -} - -#[messages] -impl EvmActor { - #[message] - pub async fn operator_create_grant( - &mut self, - basic: SharedGrantSettings, - grant: SpecificGrant, - ) -> Result { - match grant { - SpecificGrant::EtherTransfer(settings) => self - .engine - .create_grant::(CombinedSettings { - shared: basic, - specific: settings, - }) - .await - .map_err(Error::from), - SpecificGrant::TokenTransfer(settings) => self - .engine - .create_grant::(CombinedSettings { - shared: basic, - specific: settings, - }) - .await - .map_err(Error::from), - } - } - - #[message] - pub async fn useragent_delete_grant( - &mut self, - grant_id: i32, - ) -> Result<(), Error> { - self.engine - .revoke_grant(grant_id) - .await - .map_err(Error::from) - } - - #[message] - pub async fn operator_list_grants(&mut self) -> Result>, Error> { - match self.engine.list_all_grants().await { - Ok(grants) => Ok(grants), - Err(ListError::Database(db_err)) => Err(Error::Database(db_err)), - Err(ListError::Integrity(integrity_err)) => Err(Error::Integrity(integrity_err)), - } - } - - #[message] - pub async fn shared_analyze_transaction( - &mut self, - client_id: i32, - wallet_address: Address, - transaction: TxEip1559, - ) -> Result { - let mut conn = self.db.get().await.map_err(DatabaseError::from)?; - let wallet = schema::evm_wallet::table - .select(models::EvmWallet::as_select()) - .filter(schema::evm_wallet::address.eq(wallet_address.as_slice())) - .first(&mut conn) - .await - .optional() - .map_err(DatabaseError::from)? - .ok_or(SignTransactionError::WalletNotFound)?; - let wallet_access = schema::evm_wallet_access::table - .select(models::EvmWalletAccess::as_select()) - .filter(schema::evm_wallet_access::wallet_id.eq(wallet.id)) - .filter(schema::evm_wallet_access::client_id.eq(client_id)) - .first(&mut conn) - .await - .optional() - .map_err(DatabaseError::from)? - .ok_or(SignTransactionError::WalletNotFound)?; - drop(conn); - - let meaning = self - .engine - .evaluate_transaction(wallet_access, transaction.clone(), RunKind::Execution) - .await?; - - Ok(meaning) - } - - #[message] - pub async fn client_sign_transaction( - &mut self, - client_id: i32, - wallet_address: Address, - mut transaction: TxEip1559, - ) -> Result { - let mut conn = self.db.get().await.map_err(DatabaseError::from)?; - let wallet = schema::evm_wallet::table - .select(models::EvmWallet::as_select()) - .filter(schema::evm_wallet::address.eq(wallet_address.as_slice())) - .first(&mut conn) - .await - .optional() - .map_err(DatabaseError::from)? - .ok_or(SignTransactionError::WalletNotFound)?; - let wallet_access = schema::evm_wallet_access::table - .select(models::EvmWalletAccess::as_select()) - .filter(schema::evm_wallet_access::wallet_id.eq(wallet.id)) - .filter(schema::evm_wallet_access::client_id.eq(client_id)) - .first(&mut conn) - .await - .optional() - .map_err(DatabaseError::from)? - .ok_or(SignTransactionError::WalletNotFound)?; - drop(conn); - - let raw_key: SafeCell> = self - .vault - .ask(Decrypt { - aead_id: wallet.aead_encrypted_id, - }) - .await - .map_err(|_| SignTransactionError::VaultSend)?; - - let signer = safe_signer::SafeSigner::from_cell(raw_key)?; - - self.engine - .evaluate_transaction(wallet_access, transaction.clone(), RunKind::Execution) - .await?; - - Ok(signer.sign_transaction_sync(&mut transaction)?) - } -} +use crate::{ + actors::vault::{CreateNew, Decrypt, Vault}, + crypto::integrity, + db::{ + DatabaseError, DatabasePool, + models::{self}, + schema, + }, + evm::{ + self, ListError, RunKind, + policies::{ + CombinedSettings, Grant, SharedGrantSettings, SpecificGrant, SpecificMeaning, + ether_transfer::EtherTransfer, token_transfers::TokenTransfer, + }, + }, +}; +use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; + +use alloy::{ + consensus::TxEip1559, network::TxSignerSync as _, primitives::Address, signers::Signature, +}; +use diesel::{ + ExpressionMethods, OptionalExtension as _, QueryDsl, SelectableHelper as _, dsl::insert_into, +}; +use diesel_async::RunQueryDsl; +use kameo::{Actor, actor::ActorRef, messages}; +use rand::{SeedableRng, rng, rngs::StdRng}; + +pub use crate::evm::safe_signer; + +#[derive(Debug, thiserror::Error)] +pub enum SignTransactionError { + #[error("Wallet not found")] + WalletNotFound, + + #[error("Database error: {0}")] + Database(#[from] DatabaseError), + + #[error("Vault error: {0}")] + Vault(#[from] crate::actors::vault::Error), + + #[error("Vault mailbox error")] + VaultSend, + + #[error("Signing error: {0}")] + Signing(#[from] alloy::signers::Error), + + #[error("Policy error: {0}")] + Vet(#[from] evm::VetError), +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Vault error: {0}")] + Vault(#[from] crate::actors::vault::Error), + + #[error("Vault mailbox error")] + VaultSend, + + #[error("Database error: {0}")] + Database(#[from] DatabaseError), + + #[error("Integrity violation: {0}")] + Integrity(#[from] integrity::Error), +} + +#[derive(Actor)] +pub struct EvmActor { + pub vault: ActorRef, + pub db: DatabasePool, + pub rng: StdRng, + pub engine: evm::Engine, +} + +impl EvmActor { + pub fn new(vault: ActorRef, db: DatabasePool) -> Self { + // is it safe to seed rng from system once? + // todo: audit + let rng = StdRng::from_rng(&mut rng()); + let engine = evm::Engine::new(db.clone(), vault.clone()); + Self { + vault, + db, + rng, + engine, + } + } +} + +#[messages] +impl EvmActor { + #[message] + pub async fn generate(&mut self) -> Result<(i32, Address), Error> { + let (mut key_cell, address) = safe_signer::generate(&mut self.rng); + + let plaintext = key_cell.read_inline(|reader| SafeCell::new(reader.to_vec())); + + let aead_id: i32 = self + .vault + .ask(CreateNew { plaintext }) + .await + .map_err(|_| Error::VaultSend)?; + + let mut conn = self.db.get().await.map_err(DatabaseError::from)?; + let wallet_id = insert_into(schema::evm_wallet::table) + .values(&models::NewEvmWallet { + address: address.as_slice().to_vec(), + aead_encrypted_id: aead_id, + }) + .returning(schema::evm_wallet::id) + .get_result(&mut conn) + .await + .map_err(DatabaseError::from)?; + + Ok((wallet_id, address)) + } + + #[message] + pub async fn list_wallets(&self) -> Result, Error> { + let mut conn = self.db.get().await.map_err(DatabaseError::from)?; + let rows: Vec = schema::evm_wallet::table + .select(models::EvmWallet::as_select()) + .load(&mut conn) + .await + .map_err(DatabaseError::from)?; + + Ok(rows + .into_iter() + .map(|w| (w.id, Address::from_slice(&w.address))) + .collect()) + } +} + +#[messages] +impl EvmActor { + #[message] + pub async fn operator_create_grant( + &mut self, + basic: SharedGrantSettings, + grant: SpecificGrant, + ) -> Result { + match grant { + SpecificGrant::EtherTransfer(settings) => self + .engine + .create_grant::(CombinedSettings { + shared: basic, + specific: settings, + }) + .await + .map_err(Error::from), + SpecificGrant::TokenTransfer(settings) => self + .engine + .create_grant::(CombinedSettings { + shared: basic, + specific: settings, + }) + .await + .map_err(Error::from), + } + } + + #[message] + pub async fn useragent_delete_grant( + &mut self, + grant_id: i32, + ) -> Result<(), Error> { + self.engine + .revoke_grant(grant_id) + .await + .map_err(Error::from) + } + + #[message] + pub async fn operator_list_grants(&mut self) -> Result>, Error> { + match self.engine.list_all_grants().await { + Ok(grants) => Ok(grants), + Err(ListError::Database(db_err)) => Err(Error::Database(db_err)), + Err(ListError::Integrity(integrity_err)) => Err(Error::Integrity(integrity_err)), + } + } + + #[message] + pub async fn shared_analyze_transaction( + &mut self, + client_id: i32, + wallet_address: Address, + transaction: TxEip1559, + ) -> Result { + let mut conn = self.db.get().await.map_err(DatabaseError::from)?; + let wallet = schema::evm_wallet::table + .select(models::EvmWallet::as_select()) + .filter(schema::evm_wallet::address.eq(wallet_address.as_slice())) + .first(&mut conn) + .await + .optional() + .map_err(DatabaseError::from)? + .ok_or(SignTransactionError::WalletNotFound)?; + let wallet_access = schema::evm_wallet_access::table + .select(models::EvmWalletAccess::as_select()) + .filter(schema::evm_wallet_access::wallet_id.eq(wallet.id)) + .filter(schema::evm_wallet_access::client_id.eq(client_id)) + .first(&mut conn) + .await + .optional() + .map_err(DatabaseError::from)? + .ok_or(SignTransactionError::WalletNotFound)?; + drop(conn); + + let meaning = self + .engine + .evaluate_transaction(wallet_access, transaction.clone(), RunKind::Execution) + .await?; + + Ok(meaning) + } + + #[message] + pub async fn client_sign_transaction( + &mut self, + client_id: i32, + wallet_address: Address, + mut transaction: TxEip1559, + ) -> Result { + let mut conn = self.db.get().await.map_err(DatabaseError::from)?; + let wallet = schema::evm_wallet::table + .select(models::EvmWallet::as_select()) + .filter(schema::evm_wallet::address.eq(wallet_address.as_slice())) + .first(&mut conn) + .await + .optional() + .map_err(DatabaseError::from)? + .ok_or(SignTransactionError::WalletNotFound)?; + let wallet_access = schema::evm_wallet_access::table + .select(models::EvmWalletAccess::as_select()) + .filter(schema::evm_wallet_access::wallet_id.eq(wallet.id)) + .filter(schema::evm_wallet_access::client_id.eq(client_id)) + .first(&mut conn) + .await + .optional() + .map_err(DatabaseError::from)? + .ok_or(SignTransactionError::WalletNotFound)?; + drop(conn); + + let raw_key: SafeCell> = self + .vault + .ask(Decrypt { + aead_id: wallet.aead_encrypted_id, + }) + .await + .map_err(|_| SignTransactionError::VaultSend)?; + + let signer = safe_signer::SafeSigner::from_cell(raw_key)?; + + self.engine + .evaluate_transaction(wallet_access, transaction.clone(), RunKind::Execution) + .await?; + + Ok(signer.sign_transaction_sync(&mut transaction)?) + } +} diff --git a/server/crates/arbiter-server/src/actors/flow_coordinator/client_connect_approval.rs b/server/crates/arbiter-server/src/actors/flow_coordinator/client_connect_approval.rs index 31eecc3..97c027d 100644 --- a/server/crates/arbiter-server/src/actors/flow_coordinator/client_connect_approval.rs +++ b/server/crates/arbiter-server/src/actors/flow_coordinator/client_connect_approval.rs @@ -1,127 +1,127 @@ -use crate::{ - actors::flow_coordinator::ApprovalError, - peers::{ - client::ClientProfile, - operator::{OperatorSession, session::BeginNewClientApproval}, - }, -}; - -use kameo::{ - Actor, messages, - prelude::{ActorId, ActorRef, ActorStopReason, Context, WeakActorRef}, - reply::ReplySender, -}; -use std::{ops::ControlFlow, time::Duration}; - -const APPROVAL_TIMEOUT: Duration = Duration::from_secs(30); - -pub struct Args { - pub client: ClientProfile, - pub operators: Vec>, - pub reply: ReplySender>, -} - -pub struct ClientApprovalController { - /// Number of operators that have not yet responded (approval or denial) or died. - pending: usize, - /// Number of approvals received so far. - approved: usize, - reply: Option>>, -} - -impl ClientApprovalController { - fn send_reply(&mut self, result: Result) { - if let Some(reply) = self.reply.take() { - reply.send(result); - } - } -} - -impl Actor for ClientApprovalController { - type Args = Args; - type Error = (); - - async fn on_start( - Args { - client, - operators, - reply, - }: Self::Args, - actor_ref: ActorRef, - ) -> Result { - let this = Self { - pending: operators.len(), - approved: 0, - reply: Some(reply), - }; - - for operator in operators { - actor_ref.link(&operator).await; - - let _ = operator - .tell(BeginNewClientApproval { - client: client.clone(), - controller: actor_ref.clone(), - }) - .await; - } - - let weak = actor_ref.downgrade(); - tokio::spawn(async move { - tokio::time::sleep(APPROVAL_TIMEOUT).await; - if let Some(r) = weak.upgrade() { - let _ = r.tell(OnApprovalTimeout {}).await; - } - }); - - Ok(this) - } - - async fn on_link_died( - &mut self, - _: WeakActorRef, - _: ActorId, - _: ActorStopReason, - ) -> Result, Self::Error> { - // A linked operator died before responding — counts as a non-approval. - self.pending = self.pending.saturating_sub(1); - if self.pending == 0 { - // At least one operator didn't approve: deny. - self.send_reply(Ok(false)); - return Ok(ControlFlow::Break(ActorStopReason::Normal)); - } - Ok(ControlFlow::Continue(())) - } -} - -#[messages] -impl ClientApprovalController { - #[message(ctx)] - pub fn client_approval_answer(&mut self, approved: bool, ctx: &mut Context) { - if !approved { - // Denial wins immediately regardless of other pending responses. - self.send_reply(Ok(false)); - ctx.stop(); - return; - } - - self.approved += 1; - self.pending = self.pending.saturating_sub(1); - - if self.pending == 0 { - // Every connected operator approved. - self.send_reply(Ok(true)); - ctx.stop(); - } - } - - /// Fired after `APPROVAL_TIMEOUT` elapses. Any operator that hasn't responded - /// by then is treated as a denial to prevent zombie sessions from blocking the flow. - #[message(ctx)] - pub fn on_approval_timeout(&mut self, ctx: &mut Context) { - if self.pending > 0 { - self.send_reply(Ok(false)); - ctx.stop(); - } - } -} +use crate::{ + actors::flow_coordinator::ApprovalError, + peers::{ + client::ClientProfile, + operator::{OperatorSession, session::BeginNewClientApproval}, + }, +}; + +use kameo::{ + Actor, messages, + prelude::{ActorId, ActorRef, ActorStopReason, Context, WeakActorRef}, + reply::ReplySender, +}; +use std::{ops::ControlFlow, time::Duration}; + +const APPROVAL_TIMEOUT: Duration = Duration::from_secs(30); + +pub struct Args { + pub client: ClientProfile, + pub operators: Vec>, + pub reply: ReplySender>, +} + +pub struct ClientApprovalController { + /// Number of operators that have not yet responded (approval or denial) or died. + pending: usize, + /// Number of approvals received so far. + approved: usize, + reply: Option>>, +} + +impl ClientApprovalController { + fn send_reply(&mut self, result: Result) { + if let Some(reply) = self.reply.take() { + reply.send(result); + } + } +} + +impl Actor for ClientApprovalController { + type Args = Args; + type Error = (); + + async fn on_start( + Args { + client, + operators, + reply, + }: Self::Args, + actor_ref: ActorRef, + ) -> Result { + let this = Self { + pending: operators.len(), + approved: 0, + reply: Some(reply), + }; + + for operator in operators { + actor_ref.link(&operator).await; + + let _ = operator + .tell(BeginNewClientApproval { + client: client.clone(), + controller: actor_ref.clone(), + }) + .await; + } + + let weak = actor_ref.downgrade(); + tokio::spawn(async move { + tokio::time::sleep(APPROVAL_TIMEOUT).await; + if let Some(r) = weak.upgrade() { + let _ = r.tell(OnApprovalTimeout {}).await; + } + }); + + Ok(this) + } + + async fn on_link_died( + &mut self, + _: WeakActorRef, + _: ActorId, + _: ActorStopReason, + ) -> Result, Self::Error> { + // A linked operator died before responding — counts as a non-approval. + self.pending = self.pending.saturating_sub(1); + if self.pending == 0 { + // At least one operator didn't approve: deny. + self.send_reply(Ok(false)); + return Ok(ControlFlow::Break(ActorStopReason::Normal)); + } + Ok(ControlFlow::Continue(())) + } +} + +#[messages] +impl ClientApprovalController { + #[message(ctx)] + pub fn client_approval_answer(&mut self, approved: bool, ctx: &mut Context) { + if !approved { + // Denial wins immediately regardless of other pending responses. + self.send_reply(Ok(false)); + ctx.stop(); + return; + } + + self.approved += 1; + self.pending = self.pending.saturating_sub(1); + + if self.pending == 0 { + // Every connected operator approved. + self.send_reply(Ok(true)); + ctx.stop(); + } + } + + /// Fired after `APPROVAL_TIMEOUT` elapses. Any operator that hasn't responded + /// by then is treated as a denial to prevent zombie sessions from blocking the flow. + #[message(ctx)] + pub fn on_approval_timeout(&mut self, ctx: &mut Context) { + if self.pending > 0 { + self.send_reply(Ok(false)); + ctx.stop(); + } + } +} diff --git a/server/crates/arbiter-server/src/actors/flow_coordinator/mod.rs b/server/crates/arbiter-server/src/actors/flow_coordinator/mod.rs index fa31334..86cdae5 100644 --- a/server/crates/arbiter-server/src/actors/flow_coordinator/mod.rs +++ b/server/crates/arbiter-server/src/actors/flow_coordinator/mod.rs @@ -1,114 +1,114 @@ -use crate::{ - actors::{ - flow_coordinator::client_connect_approval::ClientApprovalController, - operator_registry::{GetConnected, OperatorRegistry}, - }, - peers::client::{ClientProfile, session::ClientSession}, -}; - -use kameo::{ - Actor, - actor::{ActorId, ActorRef, Spawn}, - messages, - prelude::{ActorStopReason, Context, WeakActorRef}, - reply::DelegatedReply, -}; -use std::{collections::HashMap, ops::ControlFlow}; -use tracing::info; - -pub mod client_connect_approval; - -pub struct FlowCoordinator { - pub clients: HashMap>, - operator_registry: ActorRef, -} - -impl FlowCoordinator { - pub fn new(operator_registry: ActorRef) -> Self { - Self { - clients: HashMap::default(), - operator_registry, - } - } -} - -impl Actor for FlowCoordinator { - type Args = Self; - - type Error = (); - - async fn on_start(args: Self::Args, _: ActorRef) -> Result { - Ok(args) - } - - async fn on_link_died( - &mut self, - _: WeakActorRef, - id: ActorId, - _: ActorStopReason, - ) -> Result, Self::Error> { - if self.clients.remove(&id).is_some() { - info!( - ?id, - actor = "FlowCoordinator", - event = "client.disconnected" - ); - } else { - info!( - ?id, - actor = "FlowCoordinator", - event = "unknown.actor.disconnected" - ); - } - Ok(ControlFlow::Continue(())) - } -} - -#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq, Hash)] -pub enum ApprovalError { - #[error("No operators connected")] - NoOperatorsConnected, -} - -#[messages] -impl FlowCoordinator { - #[message(ctx)] - pub async fn register_client( - &mut self, - actor: ActorRef, - ctx: &mut Context, - ) { - info!(id = %actor.id(), actor = "FlowCoordinator", event = "client.connected"); - ctx.actor_ref().link(&actor).await; - self.clients.insert(actor.id(), actor); - } - - #[message(ctx)] - pub async fn request_client_approval( - &mut self, - client: ClientProfile, - ctx: &mut Context>>, - ) -> DelegatedReply> { - let (reply, Some(reply_sender)) = ctx.reply_sender() else { - unreachable!("Expected `request_client_approval` to have callback channel"); - }; - - let Ok(refs) = self.operator_registry.ask(GetConnected).await else { - reply_sender.send(Err(ApprovalError::NoOperatorsConnected)); - return reply; - }; - - if refs.is_empty() { - reply_sender.send(Err(ApprovalError::NoOperatorsConnected)); - return reply; - } - - ClientApprovalController::spawn(client_connect_approval::Args { - client, - operators: refs, - reply: reply_sender, - }); - - reply - } -} +use crate::{ + actors::{ + flow_coordinator::client_connect_approval::ClientApprovalController, + operator_registry::{GetConnected, OperatorRegistry}, + }, + peers::client::{ClientProfile, session::ClientSession}, +}; + +use kameo::{ + Actor, + actor::{ActorId, ActorRef, Spawn}, + messages, + prelude::{ActorStopReason, Context, WeakActorRef}, + reply::DelegatedReply, +}; +use std::{collections::HashMap, ops::ControlFlow}; +use tracing::info; + +pub mod client_connect_approval; + +pub struct FlowCoordinator { + pub clients: HashMap>, + operator_registry: ActorRef, +} + +impl FlowCoordinator { + pub fn new(operator_registry: ActorRef) -> Self { + Self { + clients: HashMap::default(), + operator_registry, + } + } +} + +impl Actor for FlowCoordinator { + type Args = Self; + + type Error = (); + + async fn on_start(args: Self::Args, _: ActorRef) -> Result { + Ok(args) + } + + async fn on_link_died( + &mut self, + _: WeakActorRef, + id: ActorId, + _: ActorStopReason, + ) -> Result, Self::Error> { + if self.clients.remove(&id).is_some() { + info!( + ?id, + actor = "FlowCoordinator", + event = "client.disconnected" + ); + } else { + info!( + ?id, + actor = "FlowCoordinator", + event = "unknown.actor.disconnected" + ); + } + Ok(ControlFlow::Continue(())) + } +} + +#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq, Hash)] +pub enum ApprovalError { + #[error("No operators connected")] + NoOperatorsConnected, +} + +#[messages] +impl FlowCoordinator { + #[message(ctx)] + pub async fn register_client( + &mut self, + actor: ActorRef, + ctx: &mut Context, + ) { + info!(id = %actor.id(), actor = "FlowCoordinator", event = "client.connected"); + ctx.actor_ref().link(&actor).await; + self.clients.insert(actor.id(), actor); + } + + #[message(ctx)] + pub async fn request_client_approval( + &mut self, + client: ClientProfile, + ctx: &mut Context>>, + ) -> DelegatedReply> { + let (reply, Some(reply_sender)) = ctx.reply_sender() else { + unreachable!("Expected `request_client_approval` to have callback channel"); + }; + + let Ok(refs) = self.operator_registry.ask(GetConnected).await else { + reply_sender.send(Err(ApprovalError::NoOperatorsConnected)); + return reply; + }; + + if refs.is_empty() { + reply_sender.send(Err(ApprovalError::NoOperatorsConnected)); + return reply; + } + + ClientApprovalController::spawn(client_connect_approval::Args { + client, + operators: refs, + reply: reply_sender, + }); + + reply + } +} diff --git a/server/crates/arbiter-server/src/actors/mod.rs b/server/crates/arbiter-server/src/actors/mod.rs index e9900ae..8a8740f 100644 --- a/server/crates/arbiter-server/src/actors/mod.rs +++ b/server/crates/arbiter-server/src/actors/mod.rs @@ -1,59 +1,59 @@ -use crate::{ - actors::{ - bootstrap::Bootstrapper, evm::EvmActor, flow_coordinator::FlowCoordinator, - operator_registry::OperatorRegistry, vault::Vault, - }, - db, -}; - -use kameo::actor::{ActorRef, Spawn}; -use kameo_actors::{DeliveryStrategy, message_bus::MessageBus}; -use thiserror::Error; - -pub mod bootstrap; -pub mod evm; -pub mod flow_coordinator; -pub mod operator_registry; -pub mod vault; - -#[derive(Error, Debug)] -pub enum SpawnError { - #[error("Failed to spawn Bootstrapper actor")] - Bootstrapper(#[from] bootstrap::Error), - - #[error("Failed to spawn Vault actor")] - Vault(#[from] vault::Error), -} - -/// Long-lived actors that are shared across all connections and handle global state and operations -#[derive(Clone)] -pub struct GlobalActors { - pub vault: ActorRef, - pub bootstrapper: ActorRef, - pub flow_coordinator: ActorRef, - pub operator_registry: ActorRef, - pub evm: ActorRef, - pub events: ActorRef, -} - -impl GlobalActors { - pub fn spawn_message_bus() -> ActorRef { - MessageBus::spawn(MessageBus::new(DeliveryStrategy::Guaranteed)) - } - - pub async fn spawn(db: db::DatabasePool) -> Result { - let message_bus = Self::spawn_message_bus(); - let key_holder = Vault::spawn(Vault::new(db.clone(), message_bus.clone()).await?); - let operator_registry = OperatorRegistry::spawn(OperatorRegistry::default()); - Ok(Self { - bootstrapper: Bootstrapper::spawn(Bootstrapper::new(&db).await?), - evm: EvmActor::spawn(EvmActor::new(key_holder.clone(), db)), - vault: key_holder, - flow_coordinator: FlowCoordinator::spawn(FlowCoordinator::new( - operator_registry.clone(), - )), - operator_registry, - events: message_bus, - }) - } -} +use crate::{ + actors::{ + bootstrap::Bootstrapper, evm::EvmActor, flow_coordinator::FlowCoordinator, + operator_registry::OperatorRegistry, vault::Vault, + }, + db, +}; + +use kameo::actor::{ActorRef, Spawn}; +use kameo_actors::{DeliveryStrategy, message_bus::MessageBus}; +use thiserror::Error; + +pub mod bootstrap; +pub mod evm; +pub mod flow_coordinator; +pub mod operator_registry; +pub mod vault; + +#[derive(Error, Debug)] +pub enum SpawnError { + #[error("Failed to spawn Bootstrapper actor")] + Bootstrapper(#[from] bootstrap::Error), + + #[error("Failed to spawn Vault actor")] + Vault(#[from] vault::Error), +} + +/// Long-lived actors that are shared across all connections and handle global state and operations +#[derive(Clone)] +pub struct GlobalActors { + pub vault: ActorRef, + pub bootstrapper: ActorRef, + pub flow_coordinator: ActorRef, + pub operator_registry: ActorRef, + pub evm: ActorRef, + pub events: ActorRef, +} + +impl GlobalActors { + pub fn spawn_message_bus() -> ActorRef { + MessageBus::spawn(MessageBus::new(DeliveryStrategy::Guaranteed)) + } + + pub async fn spawn(db: db::DatabasePool) -> Result { + let message_bus = Self::spawn_message_bus(); + let key_holder = Vault::spawn(Vault::new(db.clone(), message_bus.clone()).await?); + let operator_registry = OperatorRegistry::spawn(OperatorRegistry::default()); + Ok(Self { + bootstrapper: Bootstrapper::spawn(Bootstrapper::new(&db).await?), + evm: EvmActor::spawn(EvmActor::new(key_holder.clone(), db)), + vault: key_holder, + flow_coordinator: FlowCoordinator::spawn(FlowCoordinator::new( + operator_registry.clone(), + )), + operator_registry, + events: message_bus, + }) + } +} diff --git a/server/crates/arbiter-server/src/actors/operator_registry.rs b/server/crates/arbiter-server/src/actors/operator_registry.rs index f25ebbc..feee0d8 100644 --- a/server/crates/arbiter-server/src/actors/operator_registry.rs +++ b/server/crates/arbiter-server/src/actors/operator_registry.rs @@ -1,61 +1,61 @@ -use crate::peers::operator::OperatorSession; - -use kameo::{ - Actor, - actor::{ActorId, ActorRef}, - error::Infallible, - messages, - prelude::{ActorStopReason, Context, WeakActorRef}, -}; -use std::{collections::HashMap, ops::ControlFlow}; -use tracing::info; - -#[derive(Default)] -pub struct OperatorRegistry { - connected: HashMap>, -} - -impl Actor for OperatorRegistry { - type Args = Self; - - type Error = Infallible; - - async fn on_start(args: Self::Args, _: ActorRef) -> Result { - Ok(args) - } - - async fn on_link_died( - &mut self, - _: WeakActorRef, - id: ActorId, - _: ActorStopReason, - ) -> Result, Self::Error> { - if self.connected.remove(&id).is_some() { - info!( - ?id, - actor = "OperatorRegistry", - event = "operator.disconnected" - ); - } - Ok(ControlFlow::Continue(())) - } -} - -#[messages] -impl OperatorRegistry { - #[message(ctx)] - pub async fn connect_operator( - &mut self, - actor: ActorRef, - ctx: &mut Context, - ) { - info!(id = %actor.id(), actor = "OperatorRegistry", event = "operator.connected"); - ctx.actor_ref().link(&actor).await; - self.connected.insert(actor.id(), actor); - } - - #[message] - pub fn get_connected(&self) -> Vec> { - self.connected.values().cloned().collect() - } -} +use crate::peers::operator::OperatorSession; + +use kameo::{ + Actor, + actor::{ActorId, ActorRef}, + error::Infallible, + messages, + prelude::{ActorStopReason, Context, WeakActorRef}, +}; +use std::{collections::HashMap, ops::ControlFlow}; +use tracing::info; + +#[derive(Default)] +pub struct OperatorRegistry { + connected: HashMap>, +} + +impl Actor for OperatorRegistry { + type Args = Self; + + type Error = Infallible; + + async fn on_start(args: Self::Args, _: ActorRef) -> Result { + Ok(args) + } + + async fn on_link_died( + &mut self, + _: WeakActorRef, + id: ActorId, + _: ActorStopReason, + ) -> Result, Self::Error> { + if self.connected.remove(&id).is_some() { + info!( + ?id, + actor = "OperatorRegistry", + event = "operator.disconnected" + ); + } + Ok(ControlFlow::Continue(())) + } +} + +#[messages] +impl OperatorRegistry { + #[message(ctx)] + pub async fn connect_operator( + &mut self, + actor: ActorRef, + ctx: &mut Context, + ) { + info!(id = %actor.id(), actor = "OperatorRegistry", event = "operator.connected"); + ctx.actor_ref().link(&actor).await; + self.connected.insert(actor.id(), actor); + } + + #[message] + pub fn get_connected(&self) -> Vec> { + self.connected.values().cloned().collect() + } +} diff --git a/server/crates/arbiter-server/src/actors/vault/mod.rs b/server/crates/arbiter-server/src/actors/vault/mod.rs index 74aa15e..9f14d20 100644 --- a/server/crates/arbiter-server/src/actors/vault/mod.rs +++ b/server/crates/arbiter-server/src/actors/vault/mod.rs @@ -1,462 +1,462 @@ -use crate::{ - crypto::{ - KeyCell, derive_key, - encryption::v1::{self, Nonce}, - integrity::v1::HmacSha256, - }, - db::{ - self, - models::{self, RootKeyHistory}, - schema::{self}, - }, -}; -use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; - -use chrono::Utc; -use diesel::{ - ExpressionMethods as _, OptionalExtension, QueryDsl, SelectableHelper, - dsl::{insert_into, update}, -}; -use diesel_async::{AsyncConnection, RunQueryDsl}; -use hmac::{KeyInit as _, Mac as _}; -use kameo::{Actor, Reply, actor::ActorRef, messages}; -use kameo_actors::message_bus::{MessageBus, Publish}; -use strum::{EnumDiscriminants, IntoDiscriminant}; -use tracing::{error, info}; - -pub mod events { - - #[derive(Clone, Copy)] - pub struct Bootstrapped; - - #[derive(Clone, Copy)] - pub struct Unsealed; - - #[derive(Clone, Copy)] - pub struct VaultResealed; -} - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Vault is already bootstrapped")] - AlreadyBootstrapped, - #[error("Vault is not bootstrapped")] - NotBootstrapped, - #[error("Vault is sealed")] - Sealed, - #[error("Invalid key provided")] - InvalidKey, - - #[error("Requested aead entry not found")] - NotFound, - - #[error("Encryption error: {0}")] - Encryption(#[from] chacha20poly1305::aead::Error), - - #[error("Database error: {0}")] - DatabaseConnection(#[from] db::PoolError), - - #[error("Database transaction error: {0}")] - DatabaseTransaction(#[from] diesel::result::Error), - - #[error("Broken database")] - BrokenDatabase, -} - -struct Unsealed { - root_key_history_id: i32, - root_key: KeyCell, -} - -#[derive(Default, EnumDiscriminants)] -#[strum_discriminants(derive(Reply), vis(pub), name(VaultState))] -enum State { - #[default] - Unbootstrapped, - Sealed { - root_key_history_id: i32, - }, - Unsealed(Unsealed), -} - -/// Manages vault root key and tracks current state of the vault (bootstrapped/unbootstrapped, sealed/unsealed). -/// -/// Provides API for encrypting and decrypting data using the vault root key. -/// Abstraction over database to make sure nonces are never reused and encryption keys are never exposed in plaintext outside of this actor. -#[derive(Actor)] -pub struct Vault { - db: db::DatabasePool, - state: State, - events: ActorRef, -} - -#[messages] -impl Vault { - pub async fn new(db: db::DatabasePool, events: ActorRef) -> Result { - let state = { - let mut conn = db.get().await?; - - let (root_key_history,) = schema::arbiter_settings::table - .left_join(schema::root_key_history::table) - .select((Option::::as_select(),)) - .get_result::<(Option,)>(&mut conn) - .await?; - - match root_key_history { - Some(root_key_history) => State::Sealed { - root_key_history_id: root_key_history.id, - }, - None => State::Unbootstrapped, - } - }; - - Ok(Self { db, state, events }) - } - - // Exclusive transaction to avoid race condtions if multiple vaults write - // additional layer of protection against nonce-reuse - async fn get_new_nonce(pool: &db::DatabasePool, root_key_id: i32) -> Result { - let mut conn = pool.get().await?; - - let nonce = conn - .exclusive_transaction(async |conn| { - let current_nonce: Vec = schema::root_key_history::table - .filter(schema::root_key_history::id.eq(root_key_id)) - .select(schema::root_key_history::data_encryption_nonce) - .first(&mut *conn) - .await?; - - let mut nonce = Nonce::try_from(current_nonce.as_slice()).map_err(|()| { - error!( - "Broken database: invalid nonce for root key history id={}", - root_key_id - ); - Error::BrokenDatabase - })?; - nonce.increment(); - - update(schema::root_key_history::table) - .filter(schema::root_key_history::id.eq(root_key_id)) - .set(schema::root_key_history::data_encryption_nonce.eq(nonce.to_vec())) - .execute(&mut *conn) - .await?; - - Result::<_, Error>::Ok(nonce) - }) - .await?; - - Ok(nonce) - } - - const fn expect_unsealed(state: &mut State) -> Result<&mut Unsealed, Error> { - match state { - State::Unsealed(unsealed) => Ok(unsealed), - State::Unbootstrapped => Err(Error::NotBootstrapped), - State::Sealed { .. } => Err(Error::Sealed), - } - } - - #[message] - pub async fn bootstrap(&mut self, seal_key_raw: SafeCell>) -> Result<(), Error> { - if !matches!(self.state, State::Unbootstrapped) { - return Err(Error::AlreadyBootstrapped); - } - let salt = v1::generate_salt(); - let mut seal_key = derive_key(seal_key_raw, &salt); - let mut root_key = KeyCell::new_secure_random(); - - // Zero nonces are fine because they are one-time - let root_key_nonce = Nonce::default(); - let data_encryption_nonce = Nonce::default(); - - let root_key_ciphertext: Vec = root_key.0.read_inline(|reader| { - let root_key_reader = reader.as_slice(); - seal_key - .encrypt(&root_key_nonce, v1::ROOT_KEY_TAG, root_key_reader) - .map_err(|err| { - error!(?err, "Fatal bootstrap error"); - Error::Encryption(err) - }) - })?; - - let mut conn = self.db.get().await?; - - let data_encryption_nonce_bytes = data_encryption_nonce.to_vec(); - let root_key_history_id = conn - .transaction(async |conn| { - let root_key_history_id: i32 = insert_into(schema::root_key_history::table) - .values(&models::NewRootKeyHistory { - ciphertext: root_key_ciphertext.clone(), - tag: v1::ROOT_KEY_TAG.to_vec(), - root_key_encryption_nonce: root_key_nonce.to_vec(), - data_encryption_nonce: data_encryption_nonce_bytes.clone(), - schema_version: 1, - salt: salt.to_vec(), - }) - .returning(schema::root_key_history::id) - .get_result(&mut *conn) - .await?; - - update(schema::arbiter_settings::table) - .set(schema::arbiter_settings::root_key_id.eq(root_key_history_id)) - .execute(&mut *conn) - .await?; - - Result::<_, diesel::result::Error>::Ok(root_key_history_id) - }) - .await?; - - self.state = State::Unsealed(Unsealed { - root_key, - root_key_history_id, - }); - - info!("Vault bootstrapped successfully"); - let _ = self.events.tell(Publish(events::Bootstrapped)).await; - - Ok(()) - } - - #[message] - pub async fn try_unseal(&mut self, seal_key_raw: SafeCell>) -> Result<(), Error> { - let State::Sealed { - root_key_history_id, - } = &self.state - else { - return Err(Error::NotBootstrapped); - }; - - // We don't want to hold connection while doing expensive KDF work - let current_key = { - let mut conn = self.db.get().await?; - schema::root_key_history::table - .filter(schema::root_key_history::id.eq(*root_key_history_id)) - .select(RootKeyHistory::as_select()) - .first(&mut conn) - .await? - }; - - let salt = ¤t_key.salt; - let salt = v1::Salt::try_from(salt.as_slice()).map_err(|_| { - error!("Broken database: invalid salt for root key"); - Error::BrokenDatabase - })?; - let mut seal_key = derive_key(seal_key_raw, &salt); - - let mut root_key = SafeCell::new(current_key.ciphertext.clone()); - - let nonce = - Nonce::try_from(current_key.root_key_encryption_nonce.as_slice()).map_err(|()| { - error!("Broken database: invalid nonce for root key"); - Error::BrokenDatabase - })?; - - seal_key - .decrypt_in_place(&nonce, v1::ROOT_KEY_TAG, &mut root_key) - .map_err(|err| { - error!(?err, "Failed to unseal root key: invalid seal key"); - Error::InvalidKey - })?; - - self.state = State::Unsealed(Unsealed { - root_key_history_id: current_key.id, - root_key: KeyCell::try_from(root_key).map_err(|err| { - error!(?err, "Broken database: invalid encryption key size"); - Error::BrokenDatabase - })?, - }); - - info!("Vault unsealed successfully"); - let _ = self.events.tell(Publish(events::Unsealed)).await; - - Ok(()) - } - - #[message] - pub async fn decrypt(&mut self, aead_id: i32) -> Result>, Error> { - let Unsealed { root_key, .. } = Self::expect_unsealed(&mut self.state)?; - - let row: models::AeadEncrypted = { - let mut conn = self.db.get().await?; - schema::aead_encrypted::table - .select(models::AeadEncrypted::as_select()) - .filter(schema::aead_encrypted::id.eq(aead_id)) - .first(&mut conn) - .await - .optional()? - .ok_or(Error::NotFound)? - }; - - let nonce = Nonce::try_from(row.current_nonce.as_slice()).map_err(|()| { - error!( - "Broken database: invalid nonce for aead_encrypted id={}", - aead_id - ); - Error::BrokenDatabase - })?; - let mut output = SafeCell::new(row.ciphertext); - root_key.decrypt_in_place(&nonce, v1::TAG, &mut output)?; - Ok(output) - } - - // Creates new `aead_encrypted` entry in the database and returns it's ID - #[message] - pub async fn create_new(&mut self, mut plaintext: SafeCell>) -> Result { - let Unsealed { - root_key, - root_key_history_id, - } = Self::expect_unsealed(&mut self.state)?; - - // Order matters here - `get_new_nonce` acquires connection, so we need to call it before next acquire - // Borrow checker note: &mut borrow a few lines above is disjoint from this field - let nonce = Self::get_new_nonce(&self.db, *root_key_history_id).await?; - - let mut ciphertext_buffer = plaintext.write(); - let ciphertext_buffer: &mut Vec = ciphertext_buffer.as_mut(); - root_key.encrypt_in_place(&nonce, v1::TAG, &mut *ciphertext_buffer)?; - - let ciphertext = std::mem::take(ciphertext_buffer); - - let mut conn = self.db.get().await?; - let aead_id: i32 = insert_into(schema::aead_encrypted::table) - .values(&models::NewAeadEncrypted { - ciphertext, - tag: v1::TAG.to_vec(), - current_nonce: nonce.to_vec(), - schema_version: 1, - associated_root_key_id: *root_key_history_id, - created_at: Utc::now().into(), - }) - .returning(schema::aead_encrypted::id) - .get_result(&mut conn) - .await?; - - Ok(aead_id) - } - - #[message] - pub fn get_state(&self) -> VaultState { - self.state.discriminant() - } - - #[message] - pub fn sign_integrity(&mut self, mac_input: Vec) -> Result<(i32, Vec), Error> { - let Unsealed { - root_key, - root_key_history_id, - } = Self::expect_unsealed(&mut self.state)?; - - let mut hmac = root_key.0.read_inline(|k| { - HmacSha256::new_from_slice(k) - .unwrap_or_else(|_| unreachable!("HMAC accepts keys of any size")) - }); - hmac.update(&root_key_history_id.to_be_bytes()); - hmac.update(&mac_input); - - let mac = hmac.finalize().into_bytes().to_vec(); - Ok((*root_key_history_id, mac)) - } - - #[message] - pub fn verify_integrity( - &mut self, - mac_input: Vec, - expected_mac: Vec, - key_version: i32, - ) -> Result { - let Unsealed { - root_key, - root_key_history_id, - } = Self::expect_unsealed(&mut self.state)?; - - if *root_key_history_id != key_version { - return Ok(false); - } - - let mut hmac = root_key.0.read_inline(|k| { - HmacSha256::new_from_slice(k) - .unwrap_or_else(|_| unreachable!("HMAC accepts keys of any size")) - }); - hmac.update(&key_version.to_be_bytes()); - hmac.update(&mac_input); - - Ok(hmac.verify_slice(&expected_mac).is_ok()) - } - - #[message] - pub async fn seal(&mut self) -> Result<(), Error> { - let Unsealed { - root_key_history_id, - .. - } = Self::expect_unsealed(&mut self.state)?; - - self.state = State::Sealed { - root_key_history_id: *root_key_history_id, - }; - let _ = self.events.tell(Publish(events::VaultResealed)).await; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use crate::actors::GlobalActors; - use arbiter_crypto::safecell::SafeCellHandle as _; - - use super::*; - - async fn bootstrapped_actor(db: &db::DatabasePool) -> Vault { - let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) - .await - .unwrap(); - let seal_key = SafeCell::new(b"test-seal-key".to_vec()); - actor.bootstrap(seal_key).await.unwrap(); - actor - } - - #[tokio::test] - #[test_log::test] - async fn nonce_monotonic_even_when_nonce_allocation_interleaves() { - let db = db::create_test_pool().await; - let mut actor = bootstrapped_actor(&db).await; - - let State::Unsealed(Unsealed { - root_key_history_id, - .. - }) = actor.state - else { - panic!("expected unsealed state") - }; - - let n1 = Vault::get_new_nonce(&db, root_key_history_id) - .await - .unwrap(); - let n2 = Vault::get_new_nonce(&db, root_key_history_id) - .await - .unwrap(); - assert!(n2.to_vec() > n1.to_vec(), "nonce must increase"); - - let mut conn = db.get().await.unwrap(); - let root_row: RootKeyHistory = schema::root_key_history::table - .select(RootKeyHistory::as_select()) - .first(&mut conn) - .await - .unwrap(); - assert_eq!(root_row.data_encryption_nonce, n2.to_vec()); - - let id = actor - .create_new(SafeCell::new(b"post-interleave".to_vec())) - .await - .unwrap(); - let row: models::AeadEncrypted = schema::aead_encrypted::table - .filter(schema::aead_encrypted::id.eq(id)) - .select(models::AeadEncrypted::as_select()) - .first(&mut conn) - .await - .unwrap(); - assert!( - row.current_nonce > n2.to_vec(), - "next write must advance nonce" - ); - } -} +use crate::{ + crypto::{ + KeyCell, derive_key, + encryption::v1::{self, Nonce}, + integrity::v1::HmacSha256, + }, + db::{ + self, + models::{self, RootKeyHistory}, + schema::{self}, + }, +}; +use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; + +use chrono::Utc; +use diesel::{ + ExpressionMethods as _, OptionalExtension, QueryDsl, SelectableHelper, + dsl::{insert_into, update}, +}; +use diesel_async::{AsyncConnection, RunQueryDsl}; +use hmac::{KeyInit as _, Mac as _}; +use kameo::{Actor, Reply, actor::ActorRef, messages}; +use kameo_actors::message_bus::{MessageBus, Publish}; +use strum::{EnumDiscriminants, IntoDiscriminant}; +use tracing::{error, info}; + +pub mod events { + + #[derive(Clone, Copy)] + pub struct Bootstrapped; + + #[derive(Clone, Copy)] + pub struct Unsealed; + + #[derive(Clone, Copy)] + pub struct VaultResealed; +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Vault is already bootstrapped")] + AlreadyBootstrapped, + #[error("Vault is not bootstrapped")] + NotBootstrapped, + #[error("Vault is sealed")] + Sealed, + #[error("Invalid key provided")] + InvalidKey, + + #[error("Requested aead entry not found")] + NotFound, + + #[error("Encryption error: {0}")] + Encryption(#[from] chacha20poly1305::aead::Error), + + #[error("Database error: {0}")] + DatabaseConnection(#[from] db::PoolError), + + #[error("Database transaction error: {0}")] + DatabaseTransaction(#[from] diesel::result::Error), + + #[error("Broken database")] + BrokenDatabase, +} + +struct Unsealed { + root_key_history_id: i32, + root_key: KeyCell, +} + +#[derive(Default, EnumDiscriminants)] +#[strum_discriminants(derive(Reply), vis(pub), name(VaultState))] +enum State { + #[default] + Unbootstrapped, + Sealed { + root_key_history_id: i32, + }, + Unsealed(Unsealed), +} + +/// Manages vault root key and tracks current state of the vault (bootstrapped/unbootstrapped, sealed/unsealed). +/// +/// Provides API for encrypting and decrypting data using the vault root key. +/// Abstraction over database to make sure nonces are never reused and encryption keys are never exposed in plaintext outside of this actor. +#[derive(Actor)] +pub struct Vault { + db: db::DatabasePool, + state: State, + events: ActorRef, +} + +#[messages] +impl Vault { + pub async fn new(db: db::DatabasePool, events: ActorRef) -> Result { + let state = { + let mut conn = db.get().await?; + + let (root_key_history,) = schema::arbiter_settings::table + .left_join(schema::root_key_history::table) + .select((Option::::as_select(),)) + .get_result::<(Option,)>(&mut conn) + .await?; + + match root_key_history { + Some(root_key_history) => State::Sealed { + root_key_history_id: root_key_history.id, + }, + None => State::Unbootstrapped, + } + }; + + Ok(Self { db, state, events }) + } + + // Exclusive transaction to avoid race condtions if multiple vaults write + // additional layer of protection against nonce-reuse + async fn get_new_nonce(pool: &db::DatabasePool, root_key_id: i32) -> Result { + let mut conn = pool.get().await?; + + let nonce = conn + .exclusive_transaction(async |conn| { + let current_nonce: Vec = schema::root_key_history::table + .filter(schema::root_key_history::id.eq(root_key_id)) + .select(schema::root_key_history::data_encryption_nonce) + .first(&mut *conn) + .await?; + + let mut nonce = Nonce::try_from(current_nonce.as_slice()).map_err(|()| { + error!( + "Broken database: invalid nonce for root key history id={}", + root_key_id + ); + Error::BrokenDatabase + })?; + nonce.increment(); + + update(schema::root_key_history::table) + .filter(schema::root_key_history::id.eq(root_key_id)) + .set(schema::root_key_history::data_encryption_nonce.eq(nonce.to_vec())) + .execute(&mut *conn) + .await?; + + Result::<_, Error>::Ok(nonce) + }) + .await?; + + Ok(nonce) + } + + const fn expect_unsealed(state: &mut State) -> Result<&mut Unsealed, Error> { + match state { + State::Unsealed(unsealed) => Ok(unsealed), + State::Unbootstrapped => Err(Error::NotBootstrapped), + State::Sealed { .. } => Err(Error::Sealed), + } + } + + #[message] + pub async fn bootstrap(&mut self, seal_key_raw: SafeCell>) -> Result<(), Error> { + if !matches!(self.state, State::Unbootstrapped) { + return Err(Error::AlreadyBootstrapped); + } + let salt = v1::generate_salt(); + let mut seal_key = derive_key(seal_key_raw, &salt); + let mut root_key = KeyCell::new_secure_random(); + + // Zero nonces are fine because they are one-time + let root_key_nonce = Nonce::default(); + let data_encryption_nonce = Nonce::default(); + + let root_key_ciphertext: Vec = root_key.0.read_inline(|reader| { + let root_key_reader = reader.as_slice(); + seal_key + .encrypt(&root_key_nonce, v1::ROOT_KEY_TAG, root_key_reader) + .map_err(|err| { + error!(?err, "Fatal bootstrap error"); + Error::Encryption(err) + }) + })?; + + let mut conn = self.db.get().await?; + + let data_encryption_nonce_bytes = data_encryption_nonce.to_vec(); + let root_key_history_id = conn + .transaction(async |conn| { + let root_key_history_id: i32 = insert_into(schema::root_key_history::table) + .values(&models::NewRootKeyHistory { + ciphertext: root_key_ciphertext.clone(), + tag: v1::ROOT_KEY_TAG.to_vec(), + root_key_encryption_nonce: root_key_nonce.to_vec(), + data_encryption_nonce: data_encryption_nonce_bytes.clone(), + schema_version: 1, + salt: salt.to_vec(), + }) + .returning(schema::root_key_history::id) + .get_result(&mut *conn) + .await?; + + update(schema::arbiter_settings::table) + .set(schema::arbiter_settings::root_key_id.eq(root_key_history_id)) + .execute(&mut *conn) + .await?; + + Result::<_, diesel::result::Error>::Ok(root_key_history_id) + }) + .await?; + + self.state = State::Unsealed(Unsealed { + root_key, + root_key_history_id, + }); + + info!("Vault bootstrapped successfully"); + let _ = self.events.tell(Publish(events::Bootstrapped)).await; + + Ok(()) + } + + #[message] + pub async fn try_unseal(&mut self, seal_key_raw: SafeCell>) -> Result<(), Error> { + let State::Sealed { + root_key_history_id, + } = &self.state + else { + return Err(Error::NotBootstrapped); + }; + + // We don't want to hold connection while doing expensive KDF work + let current_key = { + let mut conn = self.db.get().await?; + schema::root_key_history::table + .filter(schema::root_key_history::id.eq(*root_key_history_id)) + .select(RootKeyHistory::as_select()) + .first(&mut conn) + .await? + }; + + let salt = ¤t_key.salt; + let salt = v1::Salt::try_from(salt.as_slice()).map_err(|_| { + error!("Broken database: invalid salt for root key"); + Error::BrokenDatabase + })?; + let mut seal_key = derive_key(seal_key_raw, &salt); + + let mut root_key = SafeCell::new(current_key.ciphertext.clone()); + + let nonce = + Nonce::try_from(current_key.root_key_encryption_nonce.as_slice()).map_err(|()| { + error!("Broken database: invalid nonce for root key"); + Error::BrokenDatabase + })?; + + seal_key + .decrypt_in_place(&nonce, v1::ROOT_KEY_TAG, &mut root_key) + .map_err(|err| { + error!(?err, "Failed to unseal root key: invalid seal key"); + Error::InvalidKey + })?; + + self.state = State::Unsealed(Unsealed { + root_key_history_id: current_key.id, + root_key: KeyCell::try_from(root_key).map_err(|err| { + error!(?err, "Broken database: invalid encryption key size"); + Error::BrokenDatabase + })?, + }); + + info!("Vault unsealed successfully"); + let _ = self.events.tell(Publish(events::Unsealed)).await; + + Ok(()) + } + + #[message] + pub async fn decrypt(&mut self, aead_id: i32) -> Result>, Error> { + let Unsealed { root_key, .. } = Self::expect_unsealed(&mut self.state)?; + + let row: models::AeadEncrypted = { + let mut conn = self.db.get().await?; + schema::aead_encrypted::table + .select(models::AeadEncrypted::as_select()) + .filter(schema::aead_encrypted::id.eq(aead_id)) + .first(&mut conn) + .await + .optional()? + .ok_or(Error::NotFound)? + }; + + let nonce = Nonce::try_from(row.current_nonce.as_slice()).map_err(|()| { + error!( + "Broken database: invalid nonce for aead_encrypted id={}", + aead_id + ); + Error::BrokenDatabase + })?; + let mut output = SafeCell::new(row.ciphertext); + root_key.decrypt_in_place(&nonce, v1::TAG, &mut output)?; + Ok(output) + } + + // Creates new `aead_encrypted` entry in the database and returns it's ID + #[message] + pub async fn create_new(&mut self, mut plaintext: SafeCell>) -> Result { + let Unsealed { + root_key, + root_key_history_id, + } = Self::expect_unsealed(&mut self.state)?; + + // Order matters here - `get_new_nonce` acquires connection, so we need to call it before next acquire + // Borrow checker note: &mut borrow a few lines above is disjoint from this field + let nonce = Self::get_new_nonce(&self.db, *root_key_history_id).await?; + + let mut ciphertext_buffer = plaintext.write(); + let ciphertext_buffer: &mut Vec = ciphertext_buffer.as_mut(); + root_key.encrypt_in_place(&nonce, v1::TAG, &mut *ciphertext_buffer)?; + + let ciphertext = std::mem::take(ciphertext_buffer); + + let mut conn = self.db.get().await?; + let aead_id: i32 = insert_into(schema::aead_encrypted::table) + .values(&models::NewAeadEncrypted { + ciphertext, + tag: v1::TAG.to_vec(), + current_nonce: nonce.to_vec(), + schema_version: 1, + associated_root_key_id: *root_key_history_id, + created_at: Utc::now().into(), + }) + .returning(schema::aead_encrypted::id) + .get_result(&mut conn) + .await?; + + Ok(aead_id) + } + + #[message] + pub fn get_state(&self) -> VaultState { + self.state.discriminant() + } + + #[message] + pub fn sign_integrity(&mut self, mac_input: Vec) -> Result<(i32, Vec), Error> { + let Unsealed { + root_key, + root_key_history_id, + } = Self::expect_unsealed(&mut self.state)?; + + let mut hmac = root_key.0.read_inline(|k| { + HmacSha256::new_from_slice(k) + .unwrap_or_else(|_| unreachable!("HMAC accepts keys of any size")) + }); + hmac.update(&root_key_history_id.to_be_bytes()); + hmac.update(&mac_input); + + let mac = hmac.finalize().into_bytes().to_vec(); + Ok((*root_key_history_id, mac)) + } + + #[message] + pub fn verify_integrity( + &mut self, + mac_input: Vec, + expected_mac: Vec, + key_version: i32, + ) -> Result { + let Unsealed { + root_key, + root_key_history_id, + } = Self::expect_unsealed(&mut self.state)?; + + if *root_key_history_id != key_version { + return Ok(false); + } + + let mut hmac = root_key.0.read_inline(|k| { + HmacSha256::new_from_slice(k) + .unwrap_or_else(|_| unreachable!("HMAC accepts keys of any size")) + }); + hmac.update(&key_version.to_be_bytes()); + hmac.update(&mac_input); + + Ok(hmac.verify_slice(&expected_mac).is_ok()) + } + + #[message] + pub async fn seal(&mut self) -> Result<(), Error> { + let Unsealed { + root_key_history_id, + .. + } = Self::expect_unsealed(&mut self.state)?; + + self.state = State::Sealed { + root_key_history_id: *root_key_history_id, + }; + let _ = self.events.tell(Publish(events::VaultResealed)).await; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use crate::actors::GlobalActors; + use arbiter_crypto::safecell::SafeCellHandle as _; + + use super::*; + + async fn bootstrapped_actor(db: &db::DatabasePool) -> Vault { + let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) + .await + .unwrap(); + let seal_key = SafeCell::new(b"test-seal-key".to_vec()); + actor.bootstrap(seal_key).await.unwrap(); + actor + } + + #[tokio::test] + #[test_log::test] + async fn nonce_monotonic_even_when_nonce_allocation_interleaves() { + let db = db::create_test_pool().await; + let mut actor = bootstrapped_actor(&db).await; + + let State::Unsealed(Unsealed { + root_key_history_id, + .. + }) = actor.state + else { + panic!("expected unsealed state") + }; + + let n1 = Vault::get_new_nonce(&db, root_key_history_id) + .await + .unwrap(); + let n2 = Vault::get_new_nonce(&db, root_key_history_id) + .await + .unwrap(); + assert!(n2.to_vec() > n1.to_vec(), "nonce must increase"); + + let mut conn = db.get().await.unwrap(); + let root_row: RootKeyHistory = schema::root_key_history::table + .select(RootKeyHistory::as_select()) + .first(&mut conn) + .await + .unwrap(); + assert_eq!(root_row.data_encryption_nonce, n2.to_vec()); + + let id = actor + .create_new(SafeCell::new(b"post-interleave".to_vec())) + .await + .unwrap(); + let row: models::AeadEncrypted = schema::aead_encrypted::table + .filter(schema::aead_encrypted::id.eq(id)) + .select(models::AeadEncrypted::as_select()) + .first(&mut conn) + .await + .unwrap(); + assert!( + row.current_nonce > n2.to_vec(), + "next write must advance nonce" + ); + } +} diff --git a/server/crates/arbiter-server/src/context/mod.rs b/server/crates/arbiter-server/src/context/mod.rs index e1f7fe5..d045069 100644 --- a/server/crates/arbiter-server/src/context/mod.rs +++ b/server/crates/arbiter-server/src/context/mod.rs @@ -1,57 +1,57 @@ -use crate::{ - actors::GlobalActors, - context::tls::TlsManager, - db::{self}, -}; - -use std::sync::Arc; -use thiserror::Error; - -pub mod tls; - -#[derive(Error, Debug)] -pub enum InitError { - #[error("Database setup failed: {0}")] - DatabaseSetup(#[from] db::DatabaseSetupError), - - #[error("Connection acquire failed: {0}")] - DatabasePool(#[from] db::PoolError), - - #[error("Database query error: {0}")] - DatabaseQuery(#[from] diesel::result::Error), - - #[error("TLS initialization failed: {0}")] - Tls(#[from] tls::InitError), - - #[error("Actor spawn failed: {0}")] - ActorSpawn(#[from] crate::actors::SpawnError), - - #[error("I/O Error: {0}")] - Io(#[from] std::io::Error), -} - -pub struct __ServerContextInner { - pub db: db::DatabasePool, - pub tls: TlsManager, - pub actors: GlobalActors, -} -#[derive(Clone)] -pub struct ServerContext(Arc<__ServerContextInner>); - -impl std::ops::Deref for ServerContext { - type Target = __ServerContextInner; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl ServerContext { - pub async fn new(db: db::DatabasePool) -> Result { - Ok(Self(Arc::new(__ServerContextInner { - actors: GlobalActors::spawn(db.clone()).await?, - tls: TlsManager::new(db.clone()).await?, - db, - }))) - } -} +use crate::{ + actors::GlobalActors, + context::tls::TlsManager, + db::{self}, +}; + +use std::sync::Arc; +use thiserror::Error; + +pub mod tls; + +#[derive(Error, Debug)] +pub enum InitError { + #[error("Database setup failed: {0}")] + DatabaseSetup(#[from] db::DatabaseSetupError), + + #[error("Connection acquire failed: {0}")] + DatabasePool(#[from] db::PoolError), + + #[error("Database query error: {0}")] + DatabaseQuery(#[from] diesel::result::Error), + + #[error("TLS initialization failed: {0}")] + Tls(#[from] tls::InitError), + + #[error("Actor spawn failed: {0}")] + ActorSpawn(#[from] crate::actors::SpawnError), + + #[error("I/O Error: {0}")] + Io(#[from] std::io::Error), +} + +pub struct __ServerContextInner { + pub db: db::DatabasePool, + pub tls: TlsManager, + pub actors: GlobalActors, +} +#[derive(Clone)] +pub struct ServerContext(Arc<__ServerContextInner>); + +impl std::ops::Deref for ServerContext { + type Target = __ServerContextInner; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl ServerContext { + pub async fn new(db: db::DatabasePool) -> Result { + Ok(Self(Arc::new(__ServerContextInner { + actors: GlobalActors::spawn(db.clone()).await?, + tls: TlsManager::new(db.clone()).await?, + db, + }))) + } +} diff --git a/server/crates/arbiter-server/src/context/tls.rs b/server/crates/arbiter-server/src/context/tls.rs index 7765ee8..6c6b272 100644 --- a/server/crates/arbiter-server/src/context/tls.rs +++ b/server/crates/arbiter-server/src/context/tls.rs @@ -1,257 +1,257 @@ -use crate::db::{ - self, - models::{NewTlsHistory, TlsHistory}, - schema::{ - arbiter_settings, - tls_history::{self}, - }, -}; - -use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper as _}; -use diesel_async::{AsyncConnection, RunQueryDsl}; -use pem::Pem; -use rcgen::{ - BasicConstraints, Certificate, CertificateParams, CertifiedIssuer, DistinguishedName, DnType, - IsCa, Issuer, KeyPair, KeyUsagePurpose, SanType, -}; -use rustls::pki_types::pem::PemObject; -use std::{net::Ipv4Addr, string::FromUtf8Error}; -use thiserror::Error; -use tonic::transport::CertificateDer; - -const ENCODE_CONFIG: pem::EncodeConfig = { - let line_ending = if cfg!(target_family = "windows") { - pem::LineEnding::CRLF - } else { - pem::LineEnding::LF - }; - pem::EncodeConfig::new().set_line_ending(line_ending) -}; - -#[derive(Error, Debug)] -pub enum InitError { - #[error("Key generation error during TLS initialization: {0}")] - KeyGeneration(#[from] rcgen::Error), - - #[error("Key invalid format: {0}")] - KeyInvalidFormat(#[from] FromUtf8Error), - - #[error("Key deserialization error: {0}")] - KeyDeserializationError(rcgen::Error), - - #[error("Database error during TLS initialization: {0}")] - DatabaseError(#[from] diesel::result::Error), - - #[error("Pem deserialization error during TLS initialization: {0}")] - PemDeserializationError(#[from] rustls::pki_types::pem::Error), - - #[error("Database pool acquire error during TLS initialization: {0}")] - DatabasePoolAcquire(#[from] db::PoolError), -} - -pub type PemCert = String; - -pub fn encode_cert_to_pem(cert: &CertificateDer<'_>) -> PemCert { - pem::encode_config(&Pem::new("CERTIFICATE", cert.to_vec()), ENCODE_CONFIG) -} - -#[expect( - unused, - reason = "may be needed for future cert rotation implementation" -)] -struct SerializedTls { - cert_pem: PemCert, - cert_key_pem: String, -} - -struct TlsCa { - issuer: Issuer<'static, KeyPair>, - cert: CertificateDer<'static>, -} - -impl TlsCa { - fn generate() -> Result { - let keypair = KeyPair::generate()?; - let mut params = CertificateParams::new(["Arbiter Instance CA".into()])?; - params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained); - params.key_usages = vec![ - KeyUsagePurpose::KeyCertSign, - KeyUsagePurpose::CrlSign, - KeyUsagePurpose::DigitalSignature, - ]; - - let mut dn = DistinguishedName::new(); - dn.push(DnType::CommonName, "Arbiter Instance CA"); - params.distinguished_name = dn; - let certified_issuer = CertifiedIssuer::self_signed(params, keypair)?; - - let cert_key_pem = certified_issuer.key().serialize_pem(); - - #[expect( - clippy::unwrap_used, - reason = "Broken cert couldn't bootstrap server anyway" - )] - let issuer = Issuer::from_ca_cert_pem( - &certified_issuer.pem(), - KeyPair::from_pem(cert_key_pem.as_ref()).unwrap(), - ) - .unwrap(); - - Ok(Self { - issuer, - cert: certified_issuer.der().clone(), - }) - } - fn generate_leaf(&self) -> Result { - let cert_key = KeyPair::generate()?; - let mut params = CertificateParams::new(["Arbiter Instance Leaf".into()])?; - params.is_ca = IsCa::NoCa; - params.key_usages = vec![ - KeyUsagePurpose::DigitalSignature, - KeyUsagePurpose::KeyEncipherment, - ]; - params - .subject_alt_names - .push(SanType::IpAddress(Ipv4Addr::LOCALHOST.into())); - - let mut dn = DistinguishedName::new(); - dn.push(DnType::CommonName, "Arbiter Instance Leaf"); - params.distinguished_name = dn; - - let new_cert = params.signed_by(&cert_key, &self.issuer)?; - - Ok(TlsCert { - cert: new_cert, - cert_key, - }) - } - - #[expect( - unused, - clippy::unnecessary_wraps, - reason = "may be needed for future cert rotation implementation" - )] - fn serialize(&self) -> Result { - let cert_key_pem = self.issuer.key().serialize_pem(); - Ok(SerializedTls { - cert_pem: encode_cert_to_pem(&self.cert), - cert_key_pem, - }) - } - - #[expect( - unused, - reason = "may be needed for future cert rotation implementation" - )] - fn try_deserialize(cert_pem: &str, cert_key_pem: &str) -> Result { - let keypair = - KeyPair::from_pem(cert_key_pem).map_err(InitError::KeyDeserializationError)?; - let issuer = Issuer::from_ca_cert_pem(cert_pem, keypair)?; - Ok(Self { - issuer, - cert: CertificateDer::from_pem_slice(cert_pem.as_bytes())?, - }) - } -} - -struct TlsCert { - cert: Certificate, - cert_key: KeyPair, -} - -// TODO: Implement cert rotation -pub struct TlsManager { - cert: CertificateDer<'static>, - keypair: KeyPair, - ca_cert: CertificateDer<'static>, - _db: db::DatabasePool, -} - -impl TlsManager { - pub async fn generate_new(db: &db::DatabasePool) -> Result { - let ca = TlsCa::generate()?; - let new_cert = ca.generate_leaf()?; - - { - let mut conn = db.get().await?; - conn.transaction(async |conn| { - let new_tls_history = NewTlsHistory { - cert: new_cert.cert.pem(), - cert_key: new_cert.cert_key.serialize_pem(), - ca_cert: encode_cert_to_pem(&ca.cert), - ca_key: ca.issuer.key().serialize_pem(), - }; - - let inserted_tls_history: i32 = diesel::insert_into(tls_history::table) - .values(&new_tls_history) - .returning(tls_history::id) - .get_result(&mut *conn) - .await?; - - diesel::update(arbiter_settings::table) - .set(arbiter_settings::tls_id.eq(inserted_tls_history)) - .execute(&mut *conn) - .await?; - - Result::<_, diesel::result::Error>::Ok(()) - }) - .await?; - } - - Ok(Self { - cert: new_cert.cert.der().clone(), - keypair: new_cert.cert_key, - ca_cert: ca.cert, - _db: db.clone(), - }) - } - - pub async fn new(db: db::DatabasePool) -> Result { - let cert_data: Option = { - let mut conn = db.get().await?; - arbiter_settings::table - .left_join(tls_history::table) - .select(Option::::as_select()) - .first(&mut conn) - .await? - }; - - match cert_data { - Some(data) => { - let try_load = || -> Result<_, Box> { - let keypair = KeyPair::from_pem(&data.cert_key)?; - let cert = CertificateDer::from_pem_slice(data.cert.as_bytes())?; - let ca_cert = CertificateDer::from_pem_slice(data.ca_cert.as_bytes())?; - Ok(Self { - cert, - keypair, - ca_cert, - _db: db.clone(), - }) - }; - match try_load() { - Ok(manager) => Ok(manager), - Err(e) => { - eprintln!("Failed to load existing TLS certs: {e}. Generating new ones."); - Self::generate_new(&db).await - } - } - } - None => Self::generate_new(&db).await, - } - } - - pub const fn cert(&self) -> &CertificateDer<'static> { - &self.cert - } - pub const fn ca_cert(&self) -> &CertificateDer<'static> { - &self.ca_cert - } - - pub fn cert_pem(&self) -> PemCert { - encode_cert_to_pem(&self.cert) - } - pub fn key_pem(&self) -> String { - self.keypair.serialize_pem() - } -} +use crate::db::{ + self, + models::{NewTlsHistory, TlsHistory}, + schema::{ + arbiter_settings, + tls_history::{self}, + }, +}; + +use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper as _}; +use diesel_async::{AsyncConnection, RunQueryDsl}; +use pem::Pem; +use rcgen::{ + BasicConstraints, Certificate, CertificateParams, CertifiedIssuer, DistinguishedName, DnType, + IsCa, Issuer, KeyPair, KeyUsagePurpose, SanType, +}; +use rustls::pki_types::pem::PemObject; +use std::{net::Ipv4Addr, string::FromUtf8Error}; +use thiserror::Error; +use tonic::transport::CertificateDer; + +const ENCODE_CONFIG: pem::EncodeConfig = { + let line_ending = if cfg!(target_family = "windows") { + pem::LineEnding::CRLF + } else { + pem::LineEnding::LF + }; + pem::EncodeConfig::new().set_line_ending(line_ending) +}; + +#[derive(Error, Debug)] +pub enum InitError { + #[error("Key generation error during TLS initialization: {0}")] + KeyGeneration(#[from] rcgen::Error), + + #[error("Key invalid format: {0}")] + KeyInvalidFormat(#[from] FromUtf8Error), + + #[error("Key deserialization error: {0}")] + KeyDeserializationError(rcgen::Error), + + #[error("Database error during TLS initialization: {0}")] + DatabaseError(#[from] diesel::result::Error), + + #[error("Pem deserialization error during TLS initialization: {0}")] + PemDeserializationError(#[from] rustls::pki_types::pem::Error), + + #[error("Database pool acquire error during TLS initialization: {0}")] + DatabasePoolAcquire(#[from] db::PoolError), +} + +pub type PemCert = String; + +pub fn encode_cert_to_pem(cert: &CertificateDer<'_>) -> PemCert { + pem::encode_config(&Pem::new("CERTIFICATE", cert.to_vec()), ENCODE_CONFIG) +} + +#[expect( + unused, + reason = "may be needed for future cert rotation implementation" +)] +struct SerializedTls { + cert_pem: PemCert, + cert_key_pem: String, +} + +struct TlsCa { + issuer: Issuer<'static, KeyPair>, + cert: CertificateDer<'static>, +} + +impl TlsCa { + fn generate() -> Result { + let keypair = KeyPair::generate()?; + let mut params = CertificateParams::new(["Arbiter Instance CA".into()])?; + params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained); + params.key_usages = vec![ + KeyUsagePurpose::KeyCertSign, + KeyUsagePurpose::CrlSign, + KeyUsagePurpose::DigitalSignature, + ]; + + let mut dn = DistinguishedName::new(); + dn.push(DnType::CommonName, "Arbiter Instance CA"); + params.distinguished_name = dn; + let certified_issuer = CertifiedIssuer::self_signed(params, keypair)?; + + let cert_key_pem = certified_issuer.key().serialize_pem(); + + #[expect( + clippy::unwrap_used, + reason = "Broken cert couldn't bootstrap server anyway" + )] + let issuer = Issuer::from_ca_cert_pem( + &certified_issuer.pem(), + KeyPair::from_pem(cert_key_pem.as_ref()).unwrap(), + ) + .unwrap(); + + Ok(Self { + issuer, + cert: certified_issuer.der().clone(), + }) + } + fn generate_leaf(&self) -> Result { + let cert_key = KeyPair::generate()?; + let mut params = CertificateParams::new(["Arbiter Instance Leaf".into()])?; + params.is_ca = IsCa::NoCa; + params.key_usages = vec![ + KeyUsagePurpose::DigitalSignature, + KeyUsagePurpose::KeyEncipherment, + ]; + params + .subject_alt_names + .push(SanType::IpAddress(Ipv4Addr::LOCALHOST.into())); + + let mut dn = DistinguishedName::new(); + dn.push(DnType::CommonName, "Arbiter Instance Leaf"); + params.distinguished_name = dn; + + let new_cert = params.signed_by(&cert_key, &self.issuer)?; + + Ok(TlsCert { + cert: new_cert, + cert_key, + }) + } + + #[expect( + unused, + clippy::unnecessary_wraps, + reason = "may be needed for future cert rotation implementation" + )] + fn serialize(&self) -> Result { + let cert_key_pem = self.issuer.key().serialize_pem(); + Ok(SerializedTls { + cert_pem: encode_cert_to_pem(&self.cert), + cert_key_pem, + }) + } + + #[expect( + unused, + reason = "may be needed for future cert rotation implementation" + )] + fn try_deserialize(cert_pem: &str, cert_key_pem: &str) -> Result { + let keypair = + KeyPair::from_pem(cert_key_pem).map_err(InitError::KeyDeserializationError)?; + let issuer = Issuer::from_ca_cert_pem(cert_pem, keypair)?; + Ok(Self { + issuer, + cert: CertificateDer::from_pem_slice(cert_pem.as_bytes())?, + }) + } +} + +struct TlsCert { + cert: Certificate, + cert_key: KeyPair, +} + +// TODO: Implement cert rotation +pub struct TlsManager { + cert: CertificateDer<'static>, + keypair: KeyPair, + ca_cert: CertificateDer<'static>, + _db: db::DatabasePool, +} + +impl TlsManager { + pub async fn generate_new(db: &db::DatabasePool) -> Result { + let ca = TlsCa::generate()?; + let new_cert = ca.generate_leaf()?; + + { + let mut conn = db.get().await?; + conn.transaction(async |conn| { + let new_tls_history = NewTlsHistory { + cert: new_cert.cert.pem(), + cert_key: new_cert.cert_key.serialize_pem(), + ca_cert: encode_cert_to_pem(&ca.cert), + ca_key: ca.issuer.key().serialize_pem(), + }; + + let inserted_tls_history: i32 = diesel::insert_into(tls_history::table) + .values(&new_tls_history) + .returning(tls_history::id) + .get_result(&mut *conn) + .await?; + + diesel::update(arbiter_settings::table) + .set(arbiter_settings::tls_id.eq(inserted_tls_history)) + .execute(&mut *conn) + .await?; + + Result::<_, diesel::result::Error>::Ok(()) + }) + .await?; + } + + Ok(Self { + cert: new_cert.cert.der().clone(), + keypair: new_cert.cert_key, + ca_cert: ca.cert, + _db: db.clone(), + }) + } + + pub async fn new(db: db::DatabasePool) -> Result { + let cert_data: Option = { + let mut conn = db.get().await?; + arbiter_settings::table + .left_join(tls_history::table) + .select(Option::::as_select()) + .first(&mut conn) + .await? + }; + + match cert_data { + Some(data) => { + let try_load = || -> Result<_, Box> { + let keypair = KeyPair::from_pem(&data.cert_key)?; + let cert = CertificateDer::from_pem_slice(data.cert.as_bytes())?; + let ca_cert = CertificateDer::from_pem_slice(data.ca_cert.as_bytes())?; + Ok(Self { + cert, + keypair, + ca_cert, + _db: db.clone(), + }) + }; + match try_load() { + Ok(manager) => Ok(manager), + Err(e) => { + eprintln!("Failed to load existing TLS certs: {e}. Generating new ones."); + Self::generate_new(&db).await + } + } + } + None => Self::generate_new(&db).await, + } + } + + pub const fn cert(&self) -> &CertificateDer<'static> { + &self.cert + } + pub const fn ca_cert(&self) -> &CertificateDer<'static> { + &self.ca_cert + } + + pub fn cert_pem(&self) -> PemCert { + encode_cert_to_pem(&self.cert) + } + pub fn key_pem(&self) -> String { + self.keypair.serialize_pem() + } +} diff --git a/server/crates/arbiter-server/src/crypto/encryption/mod.rs b/server/crates/arbiter-server/src/crypto/encryption/mod.rs index 44c6ed4..696ac95 100644 --- a/server/crates/arbiter-server/src/crypto/encryption/mod.rs +++ b/server/crates/arbiter-server/src/crypto/encryption/mod.rs @@ -1,3 +1,3 @@ -pub mod v1; - -pub use v1::*; +pub mod v1; + +pub use v1::*; diff --git a/server/crates/arbiter-server/src/crypto/encryption/v1.rs b/server/crates/arbiter-server/src/crypto/encryption/v1.rs index 0dac366..4c73ce6 100644 --- a/server/crates/arbiter-server/src/crypto/encryption/v1.rs +++ b/server/crates/arbiter-server/src/crypto/encryption/v1.rs @@ -1,102 +1,102 @@ -use argon2::password_hash::Salt as ArgonSalt; -use rand::{ - Rng as _, SeedableRng, - rngs::{StdRng, SysRng}, -}; - -pub const ROOT_KEY_TAG: &[u8] = b"arbiter/seal/v1"; -pub const TAG: &[u8] = b"arbiter/private-key/v1"; - -pub const NONCE_LENGTH: usize = 24; - -#[derive(Default)] -pub struct Nonce(pub [u8; NONCE_LENGTH]); -impl Nonce { - pub fn increment(&mut self) { - for i in (0..self.0.len()).rev() { - if let Some(byte) = self.0.get_mut(i) { - if *byte == 0xFF { - *byte = 0; - } else { - *byte += 1; - break; - } - } - } - } - - pub fn to_vec(&self) -> Vec { - self.0.to_vec() - } -} -impl<'a> TryFrom<&'a [u8]> for Nonce { - type Error = (); - - fn try_from(value: &'a [u8]) -> Result { - if value.len() != NONCE_LENGTH { - return Err(()); - } - let mut nonce = [0u8; NONCE_LENGTH]; - nonce.copy_from_slice(value); - Ok(Self(nonce)) - } -} - -pub type Salt = [u8; ArgonSalt::RECOMMENDED_LENGTH]; - -pub fn generate_salt() -> Salt { - let mut salt = Salt::default(); - let mut rng = - StdRng::try_from_rng(&mut SysRng).expect("Rng failure is unrecoverable and should panic"); - rng.fill_bytes(&mut salt); - salt -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::crypto::derive_key; - use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; - - #[test] - fn derive_seal_key_deterministic() { - static PASSWORD: &[u8] = b"password"; - let password = SafeCell::new(PASSWORD.to_vec()); - let password2 = SafeCell::new(PASSWORD.to_vec()); - let salt = generate_salt(); - - let mut key1 = derive_key(password, &salt); - let mut key2 = derive_key(password2, &salt); - - let key1_reader = key1.0.read(); - let key2_reader = key2.0.read(); - - assert_eq!(&*key1_reader, &*key2_reader); - } - - #[test] - fn successful_derive() { - static PASSWORD: &[u8] = b"password"; - let password = SafeCell::new(PASSWORD.to_vec()); - let salt = generate_salt(); - - let mut key = derive_key(password, &salt); - let key_reader = key.0.read(); - - assert_ne!(key_reader.as_slice(), &[0u8; 32][..]); - } - - #[test] - // We should fuzz this - pub fn nonce_increment() { - let mut nonce = Nonce([0u8; NONCE_LENGTH]); - nonce.increment(); - - assert_eq!( - nonce.0, - [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 - ] - ); - } -} +use argon2::password_hash::Salt as ArgonSalt; +use rand::{ + Rng as _, SeedableRng, + rngs::{StdRng, SysRng}, +}; + +pub const ROOT_KEY_TAG: &[u8] = b"arbiter/seal/v1"; +pub const TAG: &[u8] = b"arbiter/private-key/v1"; + +pub const NONCE_LENGTH: usize = 24; + +#[derive(Default)] +pub struct Nonce(pub [u8; NONCE_LENGTH]); +impl Nonce { + pub fn increment(&mut self) { + for i in (0..self.0.len()).rev() { + if let Some(byte) = self.0.get_mut(i) { + if *byte == 0xFF { + *byte = 0; + } else { + *byte += 1; + break; + } + } + } + } + + pub fn to_vec(&self) -> Vec { + self.0.to_vec() + } +} +impl<'a> TryFrom<&'a [u8]> for Nonce { + type Error = (); + + fn try_from(value: &'a [u8]) -> Result { + if value.len() != NONCE_LENGTH { + return Err(()); + } + let mut nonce = [0u8; NONCE_LENGTH]; + nonce.copy_from_slice(value); + Ok(Self(nonce)) + } +} + +pub type Salt = [u8; ArgonSalt::RECOMMENDED_LENGTH]; + +pub fn generate_salt() -> Salt { + let mut salt = Salt::default(); + let mut rng = + StdRng::try_from_rng(&mut SysRng).expect("Rng failure is unrecoverable and should panic"); + rng.fill_bytes(&mut salt); + salt +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::crypto::derive_key; + use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; + + #[test] + fn derive_seal_key_deterministic() { + static PASSWORD: &[u8] = b"password"; + let password = SafeCell::new(PASSWORD.to_vec()); + let password2 = SafeCell::new(PASSWORD.to_vec()); + let salt = generate_salt(); + + let mut key1 = derive_key(password, &salt); + let mut key2 = derive_key(password2, &salt); + + let key1_reader = key1.0.read(); + let key2_reader = key2.0.read(); + + assert_eq!(&*key1_reader, &*key2_reader); + } + + #[test] + fn successful_derive() { + static PASSWORD: &[u8] = b"password"; + let password = SafeCell::new(PASSWORD.to_vec()); + let salt = generate_salt(); + + let mut key = derive_key(password, &salt); + let key_reader = key.0.read(); + + assert_ne!(key_reader.as_slice(), &[0u8; 32][..]); + } + + #[test] + // We should fuzz this + pub fn nonce_increment() { + let mut nonce = Nonce([0u8; NONCE_LENGTH]); + nonce.increment(); + + assert_eq!( + nonce.0, + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 + ] + ); + } +} diff --git a/server/crates/arbiter-server/src/crypto/integrity/mod.rs b/server/crates/arbiter-server/src/crypto/integrity/mod.rs index 44c6ed4..696ac95 100644 --- a/server/crates/arbiter-server/src/crypto/integrity/mod.rs +++ b/server/crates/arbiter-server/src/crypto/integrity/mod.rs @@ -1,3 +1,3 @@ -pub mod v1; - -pub use v1::*; +pub mod v1; + +pub use v1::*; diff --git a/server/crates/arbiter-server/src/crypto/integrity/v1.rs b/server/crates/arbiter-server/src/crypto/integrity/v1.rs index edb2274..2cbad6a 100644 --- a/server/crates/arbiter-server/src/crypto/integrity/v1.rs +++ b/server/crates/arbiter-server/src/crypto/integrity/v1.rs @@ -1,334 +1,334 @@ -use crate::{ - actors::vault::{self, GetState, SignIntegrity, Vault, VerifyIntegrity}, - db::{ - self, - models::{IntegrityEnvelope, NewIntegrityEnvelope}, - schema::integrity_envelope, - }, -}; -use arbiter_crypto::hashing::Hashable; - -use diesel::{ExpressionMethods as _, QueryDsl, dsl::insert_into, sqlite::Sqlite}; -use diesel_async::{AsyncConnection, RunQueryDsl}; -use hmac::Hmac; -use kameo::{actor::ActorRef, error::SendError}; -use sha2::{Digest as _, Sha256}; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Database error: {0}")] - Database(#[from] db::DatabaseError), - - #[error("Vault error: {0}")] - Vault(#[from] vault::Error), - - #[error("Vault mailbox error")] - VaultSend, - - #[error("Integrity envelope is missing for entity {entity_kind}")] - MissingEnvelope { entity_kind: &'static str }, - - #[error( - "Integrity payload version mismatch for entity {entity_kind}: expected {expected}, found {found}" - )] - PayloadVersionMismatch { - entity_kind: &'static str, - expected: i32, - found: i32, - }, - - #[error("Integrity MAC mismatch for entity {entity_kind}")] - MacMismatch { entity_kind: &'static str }, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum AttestationStatus { - Attested, - Unavailable, -} - -pub const CURRENT_PAYLOAD_VERSION: i32 = 1; -pub const INTEGRITY_SUBKEY_TAG: &[u8] = b"arbiter/db-integrity-key/v1"; - -pub type HmacSha256 = Hmac; - -pub trait Integrable: Hashable { - const KIND: &'static str; - const VERSION: i32 = 1; -} - -fn payload_hash(payload: &impl Hashable) -> [u8; 32] { - let mut hasher = Sha256::new(); - payload.hash(&mut hasher); - hasher.finalize().into() -} - -fn push_len_prefixed(out: &mut Vec, bytes: &[u8]) { - #[expect( - clippy::cast_possible_truncation, - clippy::as_conversions, - reason = "fixme! #85" - )] - out.extend_from_slice(&(bytes.len() as u32).to_be_bytes()); - out.extend_from_slice(bytes); -} - -fn build_mac_input( - entity_kind: &str, - entity_id: &[u8], - payload_version: i32, - payload_hash: &[u8; 32], -) -> Vec { - let mut out = Vec::with_capacity(8 + entity_kind.len() + entity_id.len() + 32); - push_len_prefixed(&mut out, entity_kind.as_bytes()); - push_len_prefixed(&mut out, entity_id); - out.extend_from_slice(&payload_version.to_be_bytes()); - out.extend_from_slice(payload_hash); - out -} - -pub trait IntoId { - fn into_id(self) -> Vec; -} - -impl IntoId for i32 { - fn into_id(self) -> Vec { - self.to_be_bytes().to_vec() - } -} - -impl IntoId for &'_ [u8] { - fn into_id(self) -> Vec { - self.to_vec() - } -} - -pub async fn sign_entity( - conn: &mut impl AsyncConnection, - vault: &ActorRef, - entity: &E, - entity_id: impl IntoId, -) -> Result<(), Error> { - let payload_hash = payload_hash(&entity); - - let entity_id = entity_id.into_id(); - - let mac_input = build_mac_input(E::KIND, &entity_id, E::VERSION, &payload_hash); - - let (key_version, mac) = - vault - .ask(SignIntegrity { mac_input }) - .await - .map_err(|err| match err { - SendError::HandlerError(inner) => Error::Vault(inner), - _ => Error::VaultSend, - })?; - - insert_into(integrity_envelope::table) - .values(NewIntegrityEnvelope { - entity_kind: E::KIND.to_owned(), - entity_id, - payload_version: E::VERSION, - key_version, - mac: mac.clone(), - }) - .on_conflict(( - integrity_envelope::entity_id, - integrity_envelope::entity_kind, - )) - .do_update() - .set(( - integrity_envelope::payload_version.eq(E::VERSION), - integrity_envelope::key_version.eq(key_version), - integrity_envelope::mac.eq(mac), - )) - .execute(conn) - .await - .map_err(db::DatabaseError::from)?; - - Ok(()) -} - -pub async fn verify_entity( - conn: &mut impl AsyncConnection, - vault: &ActorRef, - entity: &E, - entity_id: impl IntoId, -) -> Result { - let entity_id = entity_id.into_id(); - let envelope: IntegrityEnvelope = integrity_envelope::table - .filter(integrity_envelope::entity_kind.eq(E::KIND)) - .filter(integrity_envelope::entity_id.eq(&entity_id)) - .first(conn) - .await - .map_err(|err| match err { - diesel::result::Error::NotFound => Error::MissingEnvelope { - entity_kind: E::KIND, - }, - other => Error::Database(db::DatabaseError::from(other)), - })?; - - if envelope.payload_version != E::VERSION { - return Err(Error::PayloadVersionMismatch { - entity_kind: E::KIND, - expected: E::VERSION, - found: envelope.payload_version, - }); - } - - let payload_hash = payload_hash(&entity); - let mac_input = build_mac_input(E::KIND, &entity_id, envelope.payload_version, &payload_hash); - - let result = vault - .ask(VerifyIntegrity { - mac_input, - expected_mac: envelope.mac, - key_version: envelope.key_version, - }) - .await; - - match result { - Ok(true) => Ok(AttestationStatus::Attested), - Ok(false) => Err(Error::MacMismatch { - entity_kind: E::KIND, - }), - Err(SendError::HandlerError(vault::Error::Sealed)) => Ok(AttestationStatus::Unavailable), - Err(_) => Err(Error::VaultSend), - } -} - -pub async fn is_signing_available(vault: &ActorRef) -> Result { - let state = vault.ask(GetState).await.map_err(|_| Error::VaultSend)?; - Ok(matches!(state, vault::VaultState::Unsealed)) -} - -#[cfg(test)] -mod tests { - use diesel::{ExpressionMethods as _, QueryDsl}; - use diesel_async::RunQueryDsl; - use kameo::{actor::ActorRef, prelude::Spawn}; - - use crate::{ - actors::{ - GlobalActors, - vault::{Bootstrap, Vault}, - }, - db::{self, schema}, - }; - use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; - - use super::{Error, Integrable, sign_entity, verify_entity}; - #[derive(Clone, arbiter_macros::Hashable)] - struct DummyEntity { - payload_version: i32, - payload: Vec, - } - impl Integrable for DummyEntity { - const KIND: &'static str = "dummy_entity"; - } - - async fn bootstrapped_vault(db: &db::DatabasePool) -> ActorRef { - let actor = Vault::spawn( - Vault::new(db.clone(), GlobalActors::spawn_message_bus()) - .await - .unwrap(), - ); - actor - .ask(Bootstrap { - seal_key_raw: SafeCell::new(b"integrity-test-seal-key".to_vec()), - }) - .await - .unwrap(); - actor - } - - #[tokio::test] - async fn sign_writes_envelope_and_verify_passes() { - const ENTITY_ID: &[u8] = b"entity-id-7"; - - let db = db::create_test_pool().await; - let vault = bootstrapped_vault(&db).await; - let mut conn = db.get().await.unwrap(); - - let entity = DummyEntity { - payload_version: 1, - payload: b"payload-v1".to_vec(), - }; - - sign_entity(&mut conn, &vault, &entity, ENTITY_ID) - .await - .unwrap(); - - let count: i64 = schema::integrity_envelope::table - .filter(schema::integrity_envelope::entity_kind.eq("dummy_entity")) - .filter(schema::integrity_envelope::entity_id.eq(ENTITY_ID)) - .count() - .get_result(&mut conn) - .await - .unwrap(); - - assert_eq!(count, 1, "envelope row must be created exactly once"); - verify_entity(&mut conn, &vault, &entity, ENTITY_ID) - .await - .unwrap(); - } - - #[tokio::test] - async fn tampered_mac_fails_verification() { - const ENTITY_ID: &[u8] = b"entity-id-11"; - - let db = db::create_test_pool().await; - let vault = bootstrapped_vault(&db).await; - let mut conn = db.get().await.unwrap(); - - let entity = DummyEntity { - payload_version: 1, - payload: b"payload-v1".to_vec(), - }; - - sign_entity(&mut conn, &vault, &entity, ENTITY_ID) - .await - .unwrap(); - - diesel::update(schema::integrity_envelope::table) - .filter(schema::integrity_envelope::entity_kind.eq("dummy_entity")) - .filter(schema::integrity_envelope::entity_id.eq(ENTITY_ID)) - .set(schema::integrity_envelope::mac.eq(vec![0u8; 32])) - .execute(&mut conn) - .await - .unwrap(); - - let err = verify_entity(&mut conn, &vault, &entity, ENTITY_ID) - .await - .unwrap_err(); - assert!(matches!(err, Error::MacMismatch { .. })); - } - - #[tokio::test] - async fn changed_payload_fails_verification() { - const ENTITY_ID: &[u8] = b"entity-id-21"; - - let db = db::create_test_pool().await; - let vault = bootstrapped_vault(&db).await; - let mut conn = db.get().await.unwrap(); - - let entity = DummyEntity { - payload_version: 1, - payload: b"payload-v1".to_vec(), - }; - - sign_entity(&mut conn, &vault, &entity, ENTITY_ID) - .await - .unwrap(); - - let tampered = DummyEntity { - payload: b"payload-v1-but-tampered".to_vec(), - ..entity - }; - - let err = verify_entity(&mut conn, &vault, &tampered, ENTITY_ID) - .await - .unwrap_err(); - assert!(matches!(err, Error::MacMismatch { .. })); - } -} +use crate::{ + actors::vault::{self, GetState, SignIntegrity, Vault, VerifyIntegrity}, + db::{ + self, + models::{IntegrityEnvelope, NewIntegrityEnvelope}, + schema::integrity_envelope, + }, +}; +use arbiter_crypto::hashing::Hashable; + +use diesel::{ExpressionMethods as _, QueryDsl, dsl::insert_into, sqlite::Sqlite}; +use diesel_async::{AsyncConnection, RunQueryDsl}; +use hmac::Hmac; +use kameo::{actor::ActorRef, error::SendError}; +use sha2::{Digest as _, Sha256}; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Database error: {0}")] + Database(#[from] db::DatabaseError), + + #[error("Vault error: {0}")] + Vault(#[from] vault::Error), + + #[error("Vault mailbox error")] + VaultSend, + + #[error("Integrity envelope is missing for entity {entity_kind}")] + MissingEnvelope { entity_kind: &'static str }, + + #[error( + "Integrity payload version mismatch for entity {entity_kind}: expected {expected}, found {found}" + )] + PayloadVersionMismatch { + entity_kind: &'static str, + expected: i32, + found: i32, + }, + + #[error("Integrity MAC mismatch for entity {entity_kind}")] + MacMismatch { entity_kind: &'static str }, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AttestationStatus { + Attested, + Unavailable, +} + +pub const CURRENT_PAYLOAD_VERSION: i32 = 1; +pub const INTEGRITY_SUBKEY_TAG: &[u8] = b"arbiter/db-integrity-key/v1"; + +pub type HmacSha256 = Hmac; + +pub trait Integrable: Hashable { + const KIND: &'static str; + const VERSION: i32 = 1; +} + +fn payload_hash(payload: &impl Hashable) -> [u8; 32] { + let mut hasher = Sha256::new(); + payload.hash(&mut hasher); + hasher.finalize().into() +} + +fn push_len_prefixed(out: &mut Vec, bytes: &[u8]) { + #[expect( + clippy::cast_possible_truncation, + clippy::as_conversions, + reason = "fixme! #85" + )] + out.extend_from_slice(&(bytes.len() as u32).to_be_bytes()); + out.extend_from_slice(bytes); +} + +fn build_mac_input( + entity_kind: &str, + entity_id: &[u8], + payload_version: i32, + payload_hash: &[u8; 32], +) -> Vec { + let mut out = Vec::with_capacity(8 + entity_kind.len() + entity_id.len() + 32); + push_len_prefixed(&mut out, entity_kind.as_bytes()); + push_len_prefixed(&mut out, entity_id); + out.extend_from_slice(&payload_version.to_be_bytes()); + out.extend_from_slice(payload_hash); + out +} + +pub trait IntoId { + fn into_id(self) -> Vec; +} + +impl IntoId for i32 { + fn into_id(self) -> Vec { + self.to_be_bytes().to_vec() + } +} + +impl IntoId for &'_ [u8] { + fn into_id(self) -> Vec { + self.to_vec() + } +} + +pub async fn sign_entity( + conn: &mut impl AsyncConnection, + vault: &ActorRef, + entity: &E, + entity_id: impl IntoId, +) -> Result<(), Error> { + let payload_hash = payload_hash(&entity); + + let entity_id = entity_id.into_id(); + + let mac_input = build_mac_input(E::KIND, &entity_id, E::VERSION, &payload_hash); + + let (key_version, mac) = + vault + .ask(SignIntegrity { mac_input }) + .await + .map_err(|err| match err { + SendError::HandlerError(inner) => Error::Vault(inner), + _ => Error::VaultSend, + })?; + + insert_into(integrity_envelope::table) + .values(NewIntegrityEnvelope { + entity_kind: E::KIND.to_owned(), + entity_id, + payload_version: E::VERSION, + key_version, + mac: mac.clone(), + }) + .on_conflict(( + integrity_envelope::entity_id, + integrity_envelope::entity_kind, + )) + .do_update() + .set(( + integrity_envelope::payload_version.eq(E::VERSION), + integrity_envelope::key_version.eq(key_version), + integrity_envelope::mac.eq(mac), + )) + .execute(conn) + .await + .map_err(db::DatabaseError::from)?; + + Ok(()) +} + +pub async fn verify_entity( + conn: &mut impl AsyncConnection, + vault: &ActorRef, + entity: &E, + entity_id: impl IntoId, +) -> Result { + let entity_id = entity_id.into_id(); + let envelope: IntegrityEnvelope = integrity_envelope::table + .filter(integrity_envelope::entity_kind.eq(E::KIND)) + .filter(integrity_envelope::entity_id.eq(&entity_id)) + .first(conn) + .await + .map_err(|err| match err { + diesel::result::Error::NotFound => Error::MissingEnvelope { + entity_kind: E::KIND, + }, + other => Error::Database(db::DatabaseError::from(other)), + })?; + + if envelope.payload_version != E::VERSION { + return Err(Error::PayloadVersionMismatch { + entity_kind: E::KIND, + expected: E::VERSION, + found: envelope.payload_version, + }); + } + + let payload_hash = payload_hash(&entity); + let mac_input = build_mac_input(E::KIND, &entity_id, envelope.payload_version, &payload_hash); + + let result = vault + .ask(VerifyIntegrity { + mac_input, + expected_mac: envelope.mac, + key_version: envelope.key_version, + }) + .await; + + match result { + Ok(true) => Ok(AttestationStatus::Attested), + Ok(false) => Err(Error::MacMismatch { + entity_kind: E::KIND, + }), + Err(SendError::HandlerError(vault::Error::Sealed)) => Ok(AttestationStatus::Unavailable), + Err(_) => Err(Error::VaultSend), + } +} + +pub async fn is_signing_available(vault: &ActorRef) -> Result { + let state = vault.ask(GetState).await.map_err(|_| Error::VaultSend)?; + Ok(matches!(state, vault::VaultState::Unsealed)) +} + +#[cfg(test)] +mod tests { + use diesel::{ExpressionMethods as _, QueryDsl}; + use diesel_async::RunQueryDsl; + use kameo::{actor::ActorRef, prelude::Spawn}; + + use crate::{ + actors::{ + GlobalActors, + vault::{Bootstrap, Vault}, + }, + db::{self, schema}, + }; + use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; + + use super::{Error, Integrable, sign_entity, verify_entity}; + #[derive(Clone, arbiter_macros::Hashable)] + struct DummyEntity { + payload_version: i32, + payload: Vec, + } + impl Integrable for DummyEntity { + const KIND: &'static str = "dummy_entity"; + } + + async fn bootstrapped_vault(db: &db::DatabasePool) -> ActorRef { + let actor = Vault::spawn( + Vault::new(db.clone(), GlobalActors::spawn_message_bus()) + .await + .unwrap(), + ); + actor + .ask(Bootstrap { + seal_key_raw: SafeCell::new(b"integrity-test-seal-key".to_vec()), + }) + .await + .unwrap(); + actor + } + + #[tokio::test] + async fn sign_writes_envelope_and_verify_passes() { + const ENTITY_ID: &[u8] = b"entity-id-7"; + + let db = db::create_test_pool().await; + let vault = bootstrapped_vault(&db).await; + let mut conn = db.get().await.unwrap(); + + let entity = DummyEntity { + payload_version: 1, + payload: b"payload-v1".to_vec(), + }; + + sign_entity(&mut conn, &vault, &entity, ENTITY_ID) + .await + .unwrap(); + + let count: i64 = schema::integrity_envelope::table + .filter(schema::integrity_envelope::entity_kind.eq("dummy_entity")) + .filter(schema::integrity_envelope::entity_id.eq(ENTITY_ID)) + .count() + .get_result(&mut conn) + .await + .unwrap(); + + assert_eq!(count, 1, "envelope row must be created exactly once"); + verify_entity(&mut conn, &vault, &entity, ENTITY_ID) + .await + .unwrap(); + } + + #[tokio::test] + async fn tampered_mac_fails_verification() { + const ENTITY_ID: &[u8] = b"entity-id-11"; + + let db = db::create_test_pool().await; + let vault = bootstrapped_vault(&db).await; + let mut conn = db.get().await.unwrap(); + + let entity = DummyEntity { + payload_version: 1, + payload: b"payload-v1".to_vec(), + }; + + sign_entity(&mut conn, &vault, &entity, ENTITY_ID) + .await + .unwrap(); + + diesel::update(schema::integrity_envelope::table) + .filter(schema::integrity_envelope::entity_kind.eq("dummy_entity")) + .filter(schema::integrity_envelope::entity_id.eq(ENTITY_ID)) + .set(schema::integrity_envelope::mac.eq(vec![0u8; 32])) + .execute(&mut conn) + .await + .unwrap(); + + let err = verify_entity(&mut conn, &vault, &entity, ENTITY_ID) + .await + .unwrap_err(); + assert!(matches!(err, Error::MacMismatch { .. })); + } + + #[tokio::test] + async fn changed_payload_fails_verification() { + const ENTITY_ID: &[u8] = b"entity-id-21"; + + let db = db::create_test_pool().await; + let vault = bootstrapped_vault(&db).await; + let mut conn = db.get().await.unwrap(); + + let entity = DummyEntity { + payload_version: 1, + payload: b"payload-v1".to_vec(), + }; + + sign_entity(&mut conn, &vault, &entity, ENTITY_ID) + .await + .unwrap(); + + let tampered = DummyEntity { + payload: b"payload-v1-but-tampered".to_vec(), + ..entity + }; + + let err = verify_entity(&mut conn, &vault, &tampered, ENTITY_ID) + .await + .unwrap_err(); + assert!(matches!(err, Error::MacMismatch { .. })); + } +} diff --git a/server/crates/arbiter-server/src/crypto/mod.rs b/server/crates/arbiter-server/src/crypto/mod.rs index 440cb24..b83061b 100644 --- a/server/crates/arbiter-server/src/crypto/mod.rs +++ b/server/crates/arbiter-server/src/crypto/mod.rs @@ -1,155 +1,155 @@ -use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; -use encryption::v1::{Nonce, Salt}; - -use argon2::{Algorithm, Argon2}; -use chacha20poly1305::{ - AeadInPlace, Key, KeyInit as _, XChaCha20Poly1305, XNonce, - aead::{AeadMut, Error, Payload}, -}; -use rand::{ - Rng as _, SeedableRng as _, - rngs::{StdRng, SysRng}, -}; - -pub mod encryption; -pub mod integrity; - -pub struct KeyCell(pub SafeCell); -impl From> for KeyCell { - fn from(value: SafeCell) -> Self { - Self(value) - } -} -impl TryFrom>> for KeyCell { - type Error = (); - - fn try_from(mut value: SafeCell>) -> Result { - let value = value.read(); - if value.len() != size_of::() { - return Err(()); - } - let cell = SafeCell::new_inline(|cell_write: &mut Key| { - cell_write.copy_from_slice(&value); - }); - Ok(Self(cell)) - } -} - -impl KeyCell { - pub fn new_secure_random() -> Self { - let key = SafeCell::new_inline(|key_buffer: &mut Key| { - let mut rng = StdRng::try_from_rng(&mut SysRng) - .expect("Rng failure is unrecoverable and should panic"); - rng.fill_bytes(key_buffer); - }); - - key.into() - } - - pub fn encrypt_in_place( - &mut self, - nonce: &Nonce, - associated_data: &[u8], - mut buffer: impl AsMut>, - ) -> Result<(), Error> { - let key_reader = self.0.read(); - let cipher = XChaCha20Poly1305::new(&key_reader); - let nonce = XNonce::from_slice(nonce.0.as_ref()); - let buffer = buffer.as_mut(); - cipher.encrypt_in_place(nonce, associated_data, buffer) - } - pub fn decrypt_in_place( - &mut self, - nonce: &Nonce, - associated_data: &[u8], - buffer: &mut SafeCell>, - ) -> Result<(), Error> { - let key_reader = self.0.read(); - let cipher = XChaCha20Poly1305::new(&key_reader); - let nonce = XNonce::from_slice(nonce.0.as_ref()); - let mut buffer = buffer.write(); - let buffer: &mut Vec = buffer.as_mut(); - cipher.decrypt_in_place(nonce, associated_data, buffer) - } - - pub fn encrypt( - &mut self, - nonce: &Nonce, - associated_data: &[u8], - plaintext: impl AsRef<[u8]>, - ) -> Result, Error> { - let key_reader = self.0.read(); - let mut cipher = XChaCha20Poly1305::new(&key_reader); - let nonce = XNonce::from_slice(nonce.0.as_ref()); - - let ciphertext = cipher.encrypt( - nonce, - Payload { - msg: plaintext.as_ref(), - aad: associated_data, - }, - )?; - Ok(ciphertext) - } -} - -/// Derive a fixed-length key from the password using Argon2id, which is designed for password hashing and key derivation. -pub fn derive_key(mut password: SafeCell>, salt: &Salt) -> KeyCell { - let params = { - #[cfg(debug_assertions)] - { - argon2::Params::new(8, 1, 1, None).unwrap() - } - - #[cfg(not(debug_assertions))] - { - argon2::Params::new(262_144, 3, 4, None).unwrap() - } - }; - - let hasher = Argon2::new(Algorithm::Argon2id, argon2::Version::V0x13, params); - let mut key = SafeCell::new(Key::default()); - password.read_inline(|password_source| { - let mut key_buffer = key.write(); - let key_buffer: &mut [u8] = key_buffer.as_mut(); - - hasher - .hash_password_into(password_source, salt, key_buffer) - .expect("Better fail completely than return a weak key"); - }); - - key.into() -} - -#[cfg(test)] -mod tests { - use super::{ - derive_key, - encryption::v1::{Nonce, generate_salt}, - }; - use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; - - #[test] - fn encrypt_decrypt() { - static PASSWORD: &[u8] = b"password"; - let password = SafeCell::new(PASSWORD.to_vec()); - let salt = generate_salt(); - - let mut key = derive_key(password, &salt); - let nonce = Nonce(*b"unique nonce 123 1231233"); // 24 bytes for XChaCha20Poly1305 - let associated_data = b"associated data"; - let mut buffer = b"secret data".to_vec(); - - key.encrypt_in_place(&nonce, associated_data, &mut buffer) - .unwrap(); - assert_ne!(buffer, b"secret data"); - - let mut buffer = SafeCell::new(buffer); - - key.decrypt_in_place(&nonce, associated_data, &mut buffer) - .unwrap(); - - let buffer = buffer.read(); - assert_eq!(*buffer, b"secret data"); - } -} +use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; +use encryption::v1::{Nonce, Salt}; + +use argon2::{Algorithm, Argon2}; +use chacha20poly1305::{ + AeadInPlace, Key, KeyInit as _, XChaCha20Poly1305, XNonce, + aead::{AeadMut, Error, Payload}, +}; +use rand::{ + Rng as _, SeedableRng as _, + rngs::{StdRng, SysRng}, +}; + +pub mod encryption; +pub mod integrity; + +pub struct KeyCell(pub SafeCell); +impl From> for KeyCell { + fn from(value: SafeCell) -> Self { + Self(value) + } +} +impl TryFrom>> for KeyCell { + type Error = (); + + fn try_from(mut value: SafeCell>) -> Result { + let value = value.read(); + if value.len() != size_of::() { + return Err(()); + } + let cell = SafeCell::new_inline(|cell_write: &mut Key| { + cell_write.copy_from_slice(&value); + }); + Ok(Self(cell)) + } +} + +impl KeyCell { + pub fn new_secure_random() -> Self { + let key = SafeCell::new_inline(|key_buffer: &mut Key| { + let mut rng = StdRng::try_from_rng(&mut SysRng) + .expect("Rng failure is unrecoverable and should panic"); + rng.fill_bytes(key_buffer); + }); + + key.into() + } + + pub fn encrypt_in_place( + &mut self, + nonce: &Nonce, + associated_data: &[u8], + mut buffer: impl AsMut>, + ) -> Result<(), Error> { + let key_reader = self.0.read(); + let cipher = XChaCha20Poly1305::new(&key_reader); + let nonce = XNonce::from_slice(nonce.0.as_ref()); + let buffer = buffer.as_mut(); + cipher.encrypt_in_place(nonce, associated_data, buffer) + } + pub fn decrypt_in_place( + &mut self, + nonce: &Nonce, + associated_data: &[u8], + buffer: &mut SafeCell>, + ) -> Result<(), Error> { + let key_reader = self.0.read(); + let cipher = XChaCha20Poly1305::new(&key_reader); + let nonce = XNonce::from_slice(nonce.0.as_ref()); + let mut buffer = buffer.write(); + let buffer: &mut Vec = buffer.as_mut(); + cipher.decrypt_in_place(nonce, associated_data, buffer) + } + + pub fn encrypt( + &mut self, + nonce: &Nonce, + associated_data: &[u8], + plaintext: impl AsRef<[u8]>, + ) -> Result, Error> { + let key_reader = self.0.read(); + let mut cipher = XChaCha20Poly1305::new(&key_reader); + let nonce = XNonce::from_slice(nonce.0.as_ref()); + + let ciphertext = cipher.encrypt( + nonce, + Payload { + msg: plaintext.as_ref(), + aad: associated_data, + }, + )?; + Ok(ciphertext) + } +} + +/// Derive a fixed-length key from the password using Argon2id, which is designed for password hashing and key derivation. +pub fn derive_key(mut password: SafeCell>, salt: &Salt) -> KeyCell { + let params = { + #[cfg(debug_assertions)] + { + argon2::Params::new(8, 1, 1, None).unwrap() + } + + #[cfg(not(debug_assertions))] + { + argon2::Params::new(262_144, 3, 4, None).unwrap() + } + }; + + let hasher = Argon2::new(Algorithm::Argon2id, argon2::Version::V0x13, params); + let mut key = SafeCell::new(Key::default()); + password.read_inline(|password_source| { + let mut key_buffer = key.write(); + let key_buffer: &mut [u8] = key_buffer.as_mut(); + + hasher + .hash_password_into(password_source, salt, key_buffer) + .expect("Better fail completely than return a weak key"); + }); + + key.into() +} + +#[cfg(test)] +mod tests { + use super::{ + derive_key, + encryption::v1::{Nonce, generate_salt}, + }; + use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; + + #[test] + fn encrypt_decrypt() { + static PASSWORD: &[u8] = b"password"; + let password = SafeCell::new(PASSWORD.to_vec()); + let salt = generate_salt(); + + let mut key = derive_key(password, &salt); + let nonce = Nonce(*b"unique nonce 123 1231233"); // 24 bytes for XChaCha20Poly1305 + let associated_data = b"associated data"; + let mut buffer = b"secret data".to_vec(); + + key.encrypt_in_place(&nonce, associated_data, &mut buffer) + .unwrap(); + assert_ne!(buffer, b"secret data"); + + let mut buffer = SafeCell::new(buffer); + + key.decrypt_in_place(&nonce, associated_data, &mut buffer) + .unwrap(); + + let buffer = buffer.read(); + assert_eq!(*buffer, b"secret data"); + } +} diff --git a/server/crates/arbiter-server/src/db/mod.rs b/server/crates/arbiter-server/src/db/mod.rs index ef7cb56..5a9d2aa 100644 --- a/server/crates/arbiter-server/src/db/mod.rs +++ b/server/crates/arbiter-server/src/db/mod.rs @@ -1,156 +1,156 @@ -use diesel::{Connection as _, SqliteConnection, connection::SimpleConnection as _}; -use diesel_async::{ - AsyncConnection, SimpleAsyncConnection, - pooled_connection::{AsyncDieselConnectionManager, ManagerConfig}, - sync_connection_wrapper::SyncConnectionWrapper, -}; -use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations}; -use thiserror::Error; -use tracing::info; - -pub mod models; -pub mod schema; - -pub type DatabaseConnection = SyncConnectionWrapper; -pub type DatabasePool = diesel_async::pooled_connection::bb8::Pool; -pub type PoolInitError = diesel_async::pooled_connection::PoolError; -pub type PoolError = diesel_async::pooled_connection::bb8::RunError; - -static DB_FILE: &str = "arbiter.sqlite"; - -const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations"); - -#[derive(Error, Debug)] -pub enum DatabaseSetupError { - #[error(transparent)] - ConcurrencySetup(diesel::result::Error), - - #[error(transparent)] - Connection(diesel::ConnectionError), - - #[error("Failed to determine home directory")] - HomeDir(std::io::Error), - - #[error(transparent)] - Migration(Box), - - #[error(transparent)] - Pool(#[from] PoolInitError), -} - -#[derive(Error, Debug)] -pub enum DatabaseError { - #[error("Database query error")] - Connection(#[from] diesel::result::Error), - - #[error("Database connection error")] - Pool(#[from] PoolError), -} - -#[tracing::instrument(level = "info")] -fn database_path() -> Result { - let arbiter_home = arbiter_proto::home_path().map_err(DatabaseSetupError::HomeDir)?; - - let db_path = arbiter_home.join(DB_FILE); - - Ok(db_path) -} - -#[tracing::instrument(level = "info", skip(conn))] -fn db_config(conn: &mut SqliteConnection) -> Result<(), diesel::result::Error> { - // fsync only in critical moments - conn.batch_execute("PRAGMA synchronous = NORMAL;")?; - // write WAL changes back every 1000 pages, for an in average 1MB WAL file. - // May affect readers if number is increased - conn.batch_execute("PRAGMA wal_autocheckpoint = 1000;")?; - // free some space by truncating possibly massive WAL files from the last run - conn.batch_execute("PRAGMA wal_checkpoint(TRUNCATE);")?; - - // sqlite foreign keys are disabled by default, enable them for safety - conn.batch_execute("PRAGMA foreign_keys = ON;")?; - - // better space reclamation - conn.batch_execute("PRAGMA auto_vacuum = FULL;")?; - - // secure delete, overwrite deleted content with zeros to prevent recovery - conn.batch_execute("PRAGMA secure_delete = ON;")?; - - Ok(()) -} - -#[tracing::instrument(level = "info", skip(url))] -fn initialize_database(url: &str) -> Result<(), DatabaseSetupError> { - let mut conn = SqliteConnection::establish(url).map_err(DatabaseSetupError::Connection)?; - - db_config(&mut conn).map_err(DatabaseSetupError::ConcurrencySetup)?; - - conn.run_pending_migrations(MIGRATIONS) - .map_err(DatabaseSetupError::Migration)?; - - info!(%url, "Database initialized successfully"); - - Ok(()) -} - -#[tracing::instrument(level = "info")] -/// Creates a connection pool for the `SQLite` database. -/// -/// # Panics -/// Panics if the database path is not valid UTF-8. -pub async fn create_pool(url: Option<&str>) -> Result { - let database_url = url.map(String::from).unwrap_or( - database_path()? - .to_str() - .expect("database path is not valid UTF-8") - .to_owned(), - ); - - initialize_database(&database_url)?; - - let mut config = ManagerConfig::default(); - config.custom_setup = Box::new(|url| { - Box::pin(async move { - let mut conn = DatabaseConnection::establish(url).await?; - - // see https://fractaledmind.github.io/2023/09/07/enhancing-rails-sqlite-fine-tuning/ - // sleep if the database is busy, this corresponds to up to 9 seconds sleeping time. - conn.batch_execute("PRAGMA busy_timeout = 9000;") - .await - .map_err(diesel::ConnectionError::CouldntSetupConfiguration)?; - // better write-concurrency - conn.batch_execute("PRAGMA journal_mode = WAL;") - .await - .map_err(diesel::ConnectionError::CouldntSetupConfiguration)?; - - Ok(conn) - }) - }); - - let pool = DatabasePool::builder() - .build(AsyncDieselConnectionManager::new_with_config( - database_url, - config, - )) - .await?; - - Ok(pool) -} - -#[mutants::skip] -#[expect(clippy::missing_panics_doc, reason = "Tests oriented function")] -/// Creates a test database pool with a temporary `SQLite` database file. -pub async fn create_test_pool() -> DatabasePool { - use rand::distr::{Alphanumeric, SampleString as _}; - - let tempfile_name = Alphanumeric.sample_string(&mut rand::rng(), 16); - - let file = std::env::temp_dir().join(tempfile_name); - let url = file - .to_str() - .expect("temp file path is not valid UTF-8") - .to_owned(); - - create_pool(Some(&url)) - .await - .expect("Failed to create test database pool") -} +use diesel::{Connection as _, SqliteConnection, connection::SimpleConnection as _}; +use diesel_async::{ + AsyncConnection, SimpleAsyncConnection, + pooled_connection::{AsyncDieselConnectionManager, ManagerConfig}, + sync_connection_wrapper::SyncConnectionWrapper, +}; +use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations}; +use thiserror::Error; +use tracing::info; + +pub mod models; +pub mod schema; + +pub type DatabaseConnection = SyncConnectionWrapper; +pub type DatabasePool = diesel_async::pooled_connection::bb8::Pool; +pub type PoolInitError = diesel_async::pooled_connection::PoolError; +pub type PoolError = diesel_async::pooled_connection::bb8::RunError; + +static DB_FILE: &str = "arbiter.sqlite"; + +const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations"); + +#[derive(Error, Debug)] +pub enum DatabaseSetupError { + #[error(transparent)] + ConcurrencySetup(diesel::result::Error), + + #[error(transparent)] + Connection(diesel::ConnectionError), + + #[error("Failed to determine home directory")] + HomeDir(std::io::Error), + + #[error(transparent)] + Migration(Box), + + #[error(transparent)] + Pool(#[from] PoolInitError), +} + +#[derive(Error, Debug)] +pub enum DatabaseError { + #[error("Database query error")] + Connection(#[from] diesel::result::Error), + + #[error("Database connection error")] + Pool(#[from] PoolError), +} + +#[tracing::instrument(level = "info")] +fn database_path() -> Result { + let arbiter_home = arbiter_proto::home_path().map_err(DatabaseSetupError::HomeDir)?; + + let db_path = arbiter_home.join(DB_FILE); + + Ok(db_path) +} + +#[tracing::instrument(level = "info", skip(conn))] +fn db_config(conn: &mut SqliteConnection) -> Result<(), diesel::result::Error> { + // fsync only in critical moments + conn.batch_execute("PRAGMA synchronous = NORMAL;")?; + // write WAL changes back every 1000 pages, for an in average 1MB WAL file. + // May affect readers if number is increased + conn.batch_execute("PRAGMA wal_autocheckpoint = 1000;")?; + // free some space by truncating possibly massive WAL files from the last run + conn.batch_execute("PRAGMA wal_checkpoint(TRUNCATE);")?; + + // sqlite foreign keys are disabled by default, enable them for safety + conn.batch_execute("PRAGMA foreign_keys = ON;")?; + + // better space reclamation + conn.batch_execute("PRAGMA auto_vacuum = FULL;")?; + + // secure delete, overwrite deleted content with zeros to prevent recovery + conn.batch_execute("PRAGMA secure_delete = ON;")?; + + Ok(()) +} + +#[tracing::instrument(level = "info", skip(url))] +fn initialize_database(url: &str) -> Result<(), DatabaseSetupError> { + let mut conn = SqliteConnection::establish(url).map_err(DatabaseSetupError::Connection)?; + + db_config(&mut conn).map_err(DatabaseSetupError::ConcurrencySetup)?; + + conn.run_pending_migrations(MIGRATIONS) + .map_err(DatabaseSetupError::Migration)?; + + info!(%url, "Database initialized successfully"); + + Ok(()) +} + +#[tracing::instrument(level = "info")] +/// Creates a connection pool for the `SQLite` database. +/// +/// # Panics +/// Panics if the database path is not valid UTF-8. +pub async fn create_pool(url: Option<&str>) -> Result { + let database_url = url.map(String::from).unwrap_or( + database_path()? + .to_str() + .expect("database path is not valid UTF-8") + .to_owned(), + ); + + initialize_database(&database_url)?; + + let mut config = ManagerConfig::default(); + config.custom_setup = Box::new(|url| { + Box::pin(async move { + let mut conn = DatabaseConnection::establish(url).await?; + + // see https://fractaledmind.github.io/2023/09/07/enhancing-rails-sqlite-fine-tuning/ + // sleep if the database is busy, this corresponds to up to 9 seconds sleeping time. + conn.batch_execute("PRAGMA busy_timeout = 9000;") + .await + .map_err(diesel::ConnectionError::CouldntSetupConfiguration)?; + // better write-concurrency + conn.batch_execute("PRAGMA journal_mode = WAL;") + .await + .map_err(diesel::ConnectionError::CouldntSetupConfiguration)?; + + Ok(conn) + }) + }); + + let pool = DatabasePool::builder() + .build(AsyncDieselConnectionManager::new_with_config( + database_url, + config, + )) + .await?; + + Ok(pool) +} + +#[mutants::skip] +#[expect(clippy::missing_panics_doc, reason = "Tests oriented function")] +/// Creates a test database pool with a temporary `SQLite` database file. +pub async fn create_test_pool() -> DatabasePool { + use rand::distr::{Alphanumeric, SampleString as _}; + + let tempfile_name = Alphanumeric.sample_string(&mut rand::rng(), 16); + + let file = std::env::temp_dir().join(tempfile_name); + let url = file + .to_str() + .expect("temp file path is not valid UTF-8") + .to_owned(); + + create_pool(Some(&url)) + .await + .expect("Failed to create test database pool") +} diff --git a/server/crates/arbiter-server/src/db/models.rs b/server/crates/arbiter-server/src/db/models.rs index 94fdc5b..0a4b8af 100644 --- a/server/crates/arbiter-server/src/db/models.rs +++ b/server/crates/arbiter-server/src/db/models.rs @@ -1,406 +1,406 @@ -#![allow( - clippy::duplicated_attributes, - reason = "restructed's #[view] causes false positives" -)] -use crate::db::schema::{ - self, aead_encrypted, arbiter_settings, evm_basic_grant, evm_ether_transfer_grant, - evm_ether_transfer_grant_target, evm_ether_transfer_limit, evm_token_transfer_grant, - evm_token_transfer_log, evm_token_transfer_volume_limit, evm_transaction_log, evm_wallet, - integrity_envelope, root_key_history, tls_history, -}; - -use diesel::{prelude::*, sqlite::Sqlite}; -use restructed::Models; - -pub mod types { - use chrono::{DateTime, Utc}; - use diesel::{ - deserialize::{FromSql, FromSqlRow}, - expression::AsExpression, - serialize::{IsNull, ToSql}, - sql_types::Integer, - sqlite::{Sqlite, SqliteType}, - }; - - #[derive(Debug, FromSqlRow, AsExpression, Clone)] - #[diesel(sql_type = Integer)] - #[repr(transparent)] // hint compiler to optimize the wrapper struct away - pub struct SqliteTimestamp(pub DateTime); - impl SqliteTimestamp { - pub fn now() -> Self { - Self(Utc::now()) - } - } - - impl From> for SqliteTimestamp { - fn from(dt: DateTime) -> Self { - Self(dt) - } - } - impl From for DateTime { - fn from(ts: SqliteTimestamp) -> Self { - ts.0 - } - } - - impl ToSql for SqliteTimestamp { - fn to_sql<'b>( - &'b self, - out: &mut diesel::serialize::Output<'b, '_, Sqlite>, - ) -> diesel::serialize::Result { - #[expect( - clippy::cast_possible_truncation, - clippy::as_conversions, - reason = "fixme! #84; this will break up in 2038 :3" - )] - let unix_timestamp = self.0.timestamp() as i32; - out.set_value(unix_timestamp); - Ok(IsNull::No) - } - } - - impl FromSql for SqliteTimestamp { - fn from_sql( - mut bytes: ::RawValue<'_>, - ) -> diesel::deserialize::Result { - let Some(SqliteType::Long) = bytes.value_type() else { - return Err(format!( - "Expected Integer type for SqliteTimestamp, got {:?}", - bytes.value_type() - ) - .into()); - }; - - let unix_timestamp = bytes.read_long(); - let datetime = - DateTime::from_timestamp(unix_timestamp, 0).ok_or("Timestamp is out of bounds")?; - - Ok(Self(datetime)) - } - } - - #[derive(Debug, FromSqlRow, AsExpression, Clone)] - #[diesel(sql_type = Integer)] - #[repr(transparent)] // hint compiler to optimize the wrapper struct away - pub struct ChainId(pub i32); - - #[expect( - clippy::cast_sign_loss, - clippy::cast_possible_truncation, - clippy::as_conversions, - reason = "safe because chain_id is stored as i32 but is guaranteed to be a valid ChainId by the API when creating grants" - )] - const _: () = { - impl From for alloy::primitives::ChainId { - fn from(chain_id: ChainId) -> Self { - chain_id.0 as Self - } - } - impl From for ChainId { - fn from(chain_id: alloy::primitives::ChainId) -> Self { - Self(chain_id as _) - } - } - }; - - impl FromSql for ChainId { - fn from_sql( - bytes: ::RawValue<'_>, - ) -> diesel::deserialize::Result { - FromSql::::from_sql(bytes).map(Self) - } - } - impl ToSql for ChainId { - fn to_sql<'b>( - &'b self, - out: &mut diesel::serialize::Output<'b, '_, Sqlite>, - ) -> diesel::serialize::Result { - ToSql::::to_sql(&self.0, out) - } - } -} -pub use types::*; - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[view( - NewAeadEncrypted, - derive(Insertable), - omit(id), - attributes_with = "deriveless" -)] -#[diesel(table_name = aead_encrypted, check_for_backend(Sqlite))] -pub struct AeadEncrypted { - pub id: i32, - pub ciphertext: Vec, - pub tag: Vec, - pub current_nonce: Vec, - pub schema_version: i32, - pub associated_root_key_id: i32, // references root_key_history.id - pub created_at: SqliteTimestamp, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = root_key_history, check_for_backend(Sqlite))] -#[view( - NewRootKeyHistory, - derive(Insertable), - omit(id), - attributes_with = "deriveless" -)] -pub struct RootKeyHistory { - pub id: i32, - pub ciphertext: Vec, - pub tag: Vec, - pub root_key_encryption_nonce: Vec, - pub data_encryption_nonce: Vec, - pub schema_version: i32, - pub salt: Vec, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = tls_history, check_for_backend(Sqlite))] -#[view( - NewTlsHistory, - derive(Insertable), - omit(id, created_at), - attributes_with = "deriveless" -)] -pub struct TlsHistory { - pub id: i32, - pub cert: String, - pub cert_key: String, // PEM Encoded private key - pub ca_cert: String, // PEM Encoded certificate for cert signing - pub ca_key: String, // PEM Encoded public key for cert signing - pub created_at: SqliteTimestamp, -} - -#[derive(Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = arbiter_settings, check_for_backend(Sqlite))] -pub struct ArbiterSettings { - pub id: i32, - pub root_key_id: Option, // references root_key_history.id - pub tls_id: Option, // references tls_history.id -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = evm_wallet, check_for_backend(Sqlite))] -#[view( - NewEvmWallet, - derive(Insertable), - omit(id, created_at), - attributes_with = "deriveless" -)] -pub struct EvmWallet { - pub id: i32, - pub address: Vec, - pub aead_encrypted_id: i32, - pub created_at: SqliteTimestamp, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable, Clone)] -#[diesel(table_name = schema::evm_wallet_access, check_for_backend(Sqlite))] -#[view( - NewEvmWalletAccess, - derive(Insertable), - omit(id, created_at), - attributes_with = "deriveless" -)] -#[view( - CoreEvmWalletAccess, - derive(Insertable), - omit(created_at), - attributes_with = "deriveless" -)] -pub struct EvmWalletAccess { - pub id: i32, - pub wallet_id: i32, - pub client_id: i32, - pub created_at: SqliteTimestamp, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = schema::client_metadata, check_for_backend(Sqlite))] -pub struct ProgramClientMetadata { - pub id: i32, - pub name: String, - pub description: Option, - pub version: Option, - pub created_at: SqliteTimestamp, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = schema::client_metadata_history, check_for_backend(Sqlite))] -pub struct ProgramClientMetadataHistory { - pub id: i32, - pub metadata_id: i32, - pub client_id: i32, - pub created_at: SqliteTimestamp, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = schema::program_client, check_for_backend(Sqlite))] -pub struct ProgramClient { - pub id: i32, - pub public_key: Vec, - pub metadata_id: i32, - pub created_at: SqliteTimestamp, - pub updated_at: SqliteTimestamp, -} - -#[derive(Queryable, Debug)] -#[diesel(table_name = schema::operator_client, check_for_backend(Sqlite))] -pub struct OperatorClient { - pub id: i32, - pub public_key: Vec, - pub created_at: SqliteTimestamp, - pub updated_at: SqliteTimestamp, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = evm_ether_transfer_limit, check_for_backend(Sqlite))] -#[view( - NewEvmEtherTransferLimit, - derive(Insertable), - omit(id, created_at), - attributes_with = "deriveless" -)] -pub struct EvmEtherTransferLimit { - pub id: i32, - pub window_secs: i32, - pub max_volume: Vec, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = evm_basic_grant, check_for_backend(Sqlite))] -#[view( - NewEvmBasicGrant, - derive(Insertable), - omit(id, created_at), - attributes_with = "deriveless" -)] -pub struct EvmBasicGrant { - pub id: i32, - pub wallet_access_id: i32, // references evm_wallet_access.id - pub chain_id: ChainId, - pub valid_from: Option, - pub valid_until: Option, - pub max_gas_fee_per_gas: Option>, - pub max_priority_fee_per_gas: Option>, - pub rate_limit_count: Option, - pub rate_limit_window_secs: Option, - pub revoked_at: Option, - pub created_at: SqliteTimestamp, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = evm_transaction_log, check_for_backend(Sqlite))] -#[view( - NewEvmTransactionLog, - derive(Insertable), - omit(id), - attributes_with = "deriveless" -)] -pub struct EvmTransactionLog { - pub id: i32, - pub grant_id: i32, - pub wallet_access_id: i32, - pub chain_id: ChainId, - pub eth_value: Vec, - pub signed_at: SqliteTimestamp, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = evm_ether_transfer_grant, check_for_backend(Sqlite))] -#[view( - NewEvmEtherTransferGrant, - derive(Insertable), - omit(id), - attributes_with = "deriveless" -)] -pub struct EvmEtherTransferGrant { - pub id: i32, - pub basic_grant_id: i32, - pub limit_id: i32, // references evm_ether_transfer_limit.id -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = evm_ether_transfer_grant_target, check_for_backend(Sqlite))] -#[view( - NewEvmEtherTransferGrantTarget, - derive(Insertable), - omit(id), - attributes_with = "deriveless" -)] -pub struct EvmEtherTransferGrantTarget { - pub id: i32, - pub grant_id: i32, - pub address: Vec, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = evm_token_transfer_grant, check_for_backend(Sqlite))] -#[view( - NewEvmTokenTransferGrant, - derive(Insertable), - omit(id), - attributes_with = "deriveless" -)] -pub struct EvmTokenTransferGrant { - pub id: i32, - pub basic_grant_id: i32, - pub token_contract: Vec, - pub receiver: Option>, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = evm_token_transfer_volume_limit, check_for_backend(Sqlite))] -#[view( - NewEvmTokenTransferVolumeLimit, - derive(Insertable), - omit(id), - attributes_with = "deriveless" -)] -pub struct EvmTokenTransferVolumeLimit { - pub id: i32, - pub grant_id: i32, - pub window_secs: i32, - pub max_volume: Vec, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = evm_token_transfer_log, check_for_backend(Sqlite))] -#[view( - NewEvmTokenTransferLog, - derive(Insertable), - omit(id, created_at), - attributes_with = "deriveless" -)] -pub struct EvmTokenTransferLog { - pub id: i32, - pub grant_id: i32, - pub log_id: i32, - pub chain_id: ChainId, - pub token_contract: Vec, - pub recipient_address: Vec, - pub value: Vec, - pub created_at: SqliteTimestamp, -} - -#[derive(Models, Queryable, Debug, Insertable, Selectable)] -#[diesel(table_name = integrity_envelope, check_for_backend(Sqlite))] -#[view( - NewIntegrityEnvelope, - derive(Insertable), - omit(id, signed_at, created_at), - attributes_with = "deriveless" -)] -pub struct IntegrityEnvelope { - pub id: i32, - pub entity_kind: String, - pub entity_id: Vec, - pub payload_version: i32, - pub key_version: i32, - pub mac: Vec, - pub signed_at: SqliteTimestamp, - pub created_at: SqliteTimestamp, -} +#![allow( + clippy::duplicated_attributes, + reason = "restructed's #[view] causes false positives" +)] +use crate::db::schema::{ + self, aead_encrypted, arbiter_settings, evm_basic_grant, evm_ether_transfer_grant, + evm_ether_transfer_grant_target, evm_ether_transfer_limit, evm_token_transfer_grant, + evm_token_transfer_log, evm_token_transfer_volume_limit, evm_transaction_log, evm_wallet, + integrity_envelope, root_key_history, tls_history, +}; + +use diesel::{prelude::*, sqlite::Sqlite}; +use restructed::Models; + +pub mod types { + use chrono::{DateTime, Utc}; + use diesel::{ + deserialize::{FromSql, FromSqlRow}, + expression::AsExpression, + serialize::{IsNull, ToSql}, + sql_types::Integer, + sqlite::{Sqlite, SqliteType}, + }; + + #[derive(Debug, FromSqlRow, AsExpression, Clone)] + #[diesel(sql_type = Integer)] + #[repr(transparent)] // hint compiler to optimize the wrapper struct away + pub struct SqliteTimestamp(pub DateTime); + impl SqliteTimestamp { + pub fn now() -> Self { + Self(Utc::now()) + } + } + + impl From> for SqliteTimestamp { + fn from(dt: DateTime) -> Self { + Self(dt) + } + } + impl From for DateTime { + fn from(ts: SqliteTimestamp) -> Self { + ts.0 + } + } + + impl ToSql for SqliteTimestamp { + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, Sqlite>, + ) -> diesel::serialize::Result { + #[expect( + clippy::cast_possible_truncation, + clippy::as_conversions, + reason = "fixme! #84; this will break up in 2038 :3" + )] + let unix_timestamp = self.0.timestamp() as i32; + out.set_value(unix_timestamp); + Ok(IsNull::No) + } + } + + impl FromSql for SqliteTimestamp { + fn from_sql( + mut bytes: ::RawValue<'_>, + ) -> diesel::deserialize::Result { + let Some(SqliteType::Long) = bytes.value_type() else { + return Err(format!( + "Expected Integer type for SqliteTimestamp, got {:?}", + bytes.value_type() + ) + .into()); + }; + + let unix_timestamp = bytes.read_long(); + let datetime = + DateTime::from_timestamp(unix_timestamp, 0).ok_or("Timestamp is out of bounds")?; + + Ok(Self(datetime)) + } + } + + #[derive(Debug, FromSqlRow, AsExpression, Clone)] + #[diesel(sql_type = Integer)] + #[repr(transparent)] // hint compiler to optimize the wrapper struct away + pub struct ChainId(pub i32); + + #[expect( + clippy::cast_sign_loss, + clippy::cast_possible_truncation, + clippy::as_conversions, + reason = "safe because chain_id is stored as i32 but is guaranteed to be a valid ChainId by the API when creating grants" + )] + const _: () = { + impl From for alloy::primitives::ChainId { + fn from(chain_id: ChainId) -> Self { + chain_id.0 as Self + } + } + impl From for ChainId { + fn from(chain_id: alloy::primitives::ChainId) -> Self { + Self(chain_id as _) + } + } + }; + + impl FromSql for ChainId { + fn from_sql( + bytes: ::RawValue<'_>, + ) -> diesel::deserialize::Result { + FromSql::::from_sql(bytes).map(Self) + } + } + impl ToSql for ChainId { + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, Sqlite>, + ) -> diesel::serialize::Result { + ToSql::::to_sql(&self.0, out) + } + } +} +pub use types::*; + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[view( + NewAeadEncrypted, + derive(Insertable), + omit(id), + attributes_with = "deriveless" +)] +#[diesel(table_name = aead_encrypted, check_for_backend(Sqlite))] +pub struct AeadEncrypted { + pub id: i32, + pub ciphertext: Vec, + pub tag: Vec, + pub current_nonce: Vec, + pub schema_version: i32, + pub associated_root_key_id: i32, // references root_key_history.id + pub created_at: SqliteTimestamp, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = root_key_history, check_for_backend(Sqlite))] +#[view( + NewRootKeyHistory, + derive(Insertable), + omit(id), + attributes_with = "deriveless" +)] +pub struct RootKeyHistory { + pub id: i32, + pub ciphertext: Vec, + pub tag: Vec, + pub root_key_encryption_nonce: Vec, + pub data_encryption_nonce: Vec, + pub schema_version: i32, + pub salt: Vec, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = tls_history, check_for_backend(Sqlite))] +#[view( + NewTlsHistory, + derive(Insertable), + omit(id, created_at), + attributes_with = "deriveless" +)] +pub struct TlsHistory { + pub id: i32, + pub cert: String, + pub cert_key: String, // PEM Encoded private key + pub ca_cert: String, // PEM Encoded certificate for cert signing + pub ca_key: String, // PEM Encoded public key for cert signing + pub created_at: SqliteTimestamp, +} + +#[derive(Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = arbiter_settings, check_for_backend(Sqlite))] +pub struct ArbiterSettings { + pub id: i32, + pub root_key_id: Option, // references root_key_history.id + pub tls_id: Option, // references tls_history.id +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = evm_wallet, check_for_backend(Sqlite))] +#[view( + NewEvmWallet, + derive(Insertable), + omit(id, created_at), + attributes_with = "deriveless" +)] +pub struct EvmWallet { + pub id: i32, + pub address: Vec, + pub aead_encrypted_id: i32, + pub created_at: SqliteTimestamp, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable, Clone)] +#[diesel(table_name = schema::evm_wallet_access, check_for_backend(Sqlite))] +#[view( + NewEvmWalletAccess, + derive(Insertable), + omit(id, created_at), + attributes_with = "deriveless" +)] +#[view( + CoreEvmWalletAccess, + derive(Insertable), + omit(created_at), + attributes_with = "deriveless" +)] +pub struct EvmWalletAccess { + pub id: i32, + pub wallet_id: i32, + pub client_id: i32, + pub created_at: SqliteTimestamp, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = schema::client_metadata, check_for_backend(Sqlite))] +pub struct ProgramClientMetadata { + pub id: i32, + pub name: String, + pub description: Option, + pub version: Option, + pub created_at: SqliteTimestamp, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = schema::client_metadata_history, check_for_backend(Sqlite))] +pub struct ProgramClientMetadataHistory { + pub id: i32, + pub metadata_id: i32, + pub client_id: i32, + pub created_at: SqliteTimestamp, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = schema::program_client, check_for_backend(Sqlite))] +pub struct ProgramClient { + pub id: i32, + pub public_key: Vec, + pub metadata_id: i32, + pub created_at: SqliteTimestamp, + pub updated_at: SqliteTimestamp, +} + +#[derive(Queryable, Debug)] +#[diesel(table_name = schema::operator_client, check_for_backend(Sqlite))] +pub struct OperatorClient { + pub id: i32, + pub public_key: Vec, + pub created_at: SqliteTimestamp, + pub updated_at: SqliteTimestamp, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = evm_ether_transfer_limit, check_for_backend(Sqlite))] +#[view( + NewEvmEtherTransferLimit, + derive(Insertable), + omit(id, created_at), + attributes_with = "deriveless" +)] +pub struct EvmEtherTransferLimit { + pub id: i32, + pub window_secs: i32, + pub max_volume: Vec, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = evm_basic_grant, check_for_backend(Sqlite))] +#[view( + NewEvmBasicGrant, + derive(Insertable), + omit(id, created_at), + attributes_with = "deriveless" +)] +pub struct EvmBasicGrant { + pub id: i32, + pub wallet_access_id: i32, // references evm_wallet_access.id + pub chain_id: ChainId, + pub valid_from: Option, + pub valid_until: Option, + pub max_gas_fee_per_gas: Option>, + pub max_priority_fee_per_gas: Option>, + pub rate_limit_count: Option, + pub rate_limit_window_secs: Option, + pub revoked_at: Option, + pub created_at: SqliteTimestamp, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = evm_transaction_log, check_for_backend(Sqlite))] +#[view( + NewEvmTransactionLog, + derive(Insertable), + omit(id), + attributes_with = "deriveless" +)] +pub struct EvmTransactionLog { + pub id: i32, + pub grant_id: i32, + pub wallet_access_id: i32, + pub chain_id: ChainId, + pub eth_value: Vec, + pub signed_at: SqliteTimestamp, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = evm_ether_transfer_grant, check_for_backend(Sqlite))] +#[view( + NewEvmEtherTransferGrant, + derive(Insertable), + omit(id), + attributes_with = "deriveless" +)] +pub struct EvmEtherTransferGrant { + pub id: i32, + pub basic_grant_id: i32, + pub limit_id: i32, // references evm_ether_transfer_limit.id +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = evm_ether_transfer_grant_target, check_for_backend(Sqlite))] +#[view( + NewEvmEtherTransferGrantTarget, + derive(Insertable), + omit(id), + attributes_with = "deriveless" +)] +pub struct EvmEtherTransferGrantTarget { + pub id: i32, + pub grant_id: i32, + pub address: Vec, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = evm_token_transfer_grant, check_for_backend(Sqlite))] +#[view( + NewEvmTokenTransferGrant, + derive(Insertable), + omit(id), + attributes_with = "deriveless" +)] +pub struct EvmTokenTransferGrant { + pub id: i32, + pub basic_grant_id: i32, + pub token_contract: Vec, + pub receiver: Option>, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = evm_token_transfer_volume_limit, check_for_backend(Sqlite))] +#[view( + NewEvmTokenTransferVolumeLimit, + derive(Insertable), + omit(id), + attributes_with = "deriveless" +)] +pub struct EvmTokenTransferVolumeLimit { + pub id: i32, + pub grant_id: i32, + pub window_secs: i32, + pub max_volume: Vec, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = evm_token_transfer_log, check_for_backend(Sqlite))] +#[view( + NewEvmTokenTransferLog, + derive(Insertable), + omit(id, created_at), + attributes_with = "deriveless" +)] +pub struct EvmTokenTransferLog { + pub id: i32, + pub grant_id: i32, + pub log_id: i32, + pub chain_id: ChainId, + pub token_contract: Vec, + pub recipient_address: Vec, + pub value: Vec, + pub created_at: SqliteTimestamp, +} + +#[derive(Models, Queryable, Debug, Insertable, Selectable)] +#[diesel(table_name = integrity_envelope, check_for_backend(Sqlite))] +#[view( + NewIntegrityEnvelope, + derive(Insertable), + omit(id, signed_at, created_at), + attributes_with = "deriveless" +)] +pub struct IntegrityEnvelope { + pub id: i32, + pub entity_kind: String, + pub entity_id: Vec, + pub payload_version: i32, + pub key_version: i32, + pub mac: Vec, + pub signed_at: SqliteTimestamp, + pub created_at: SqliteTimestamp, +} diff --git a/server/crates/arbiter-server/src/db/schema.rs b/server/crates/arbiter-server/src/db/schema.rs index 79d6126..50d61af 100644 --- a/server/crates/arbiter-server/src/db/schema.rs +++ b/server/crates/arbiter-server/src/db/schema.rs @@ -1,237 +1,237 @@ -// @generated automatically by Diesel CLI. - -diesel::table! { - aead_encrypted (id) { - id -> Integer, - current_nonce -> Binary, - ciphertext -> Binary, - tag -> Binary, - schema_version -> Integer, - associated_root_key_id -> Integer, - created_at -> Integer, - } -} - -diesel::table! { - arbiter_settings (id) { - id -> Integer, - root_key_id -> Nullable, - tls_id -> Nullable, - } -} - -diesel::table! { - client_metadata (id) { - id -> Integer, - name -> Text, - description -> Nullable, - version -> Nullable, - created_at -> Integer, - } -} - -diesel::table! { - client_metadata_history (id) { - id -> Integer, - metadata_id -> Integer, - client_id -> Integer, - created_at -> Integer, - } -} - -diesel::table! { - evm_basic_grant (id) { - id -> Integer, - wallet_access_id -> Integer, - chain_id -> Integer, - valid_from -> Nullable, - valid_until -> Nullable, - max_gas_fee_per_gas -> Nullable, - max_priority_fee_per_gas -> Nullable, - rate_limit_count -> Nullable, - rate_limit_window_secs -> Nullable, - revoked_at -> Nullable, - created_at -> Integer, - } -} - -diesel::table! { - evm_ether_transfer_grant (id) { - id -> Integer, - basic_grant_id -> Integer, - limit_id -> Integer, - } -} - -diesel::table! { - evm_ether_transfer_grant_target (id) { - id -> Integer, - grant_id -> Integer, - address -> Binary, - } -} - -diesel::table! { - evm_ether_transfer_limit (id) { - id -> Integer, - window_secs -> Integer, - max_volume -> Binary, - } -} - -diesel::table! { - evm_token_transfer_grant (id) { - id -> Integer, - basic_grant_id -> Integer, - token_contract -> Binary, - receiver -> Nullable, - } -} - -diesel::table! { - evm_token_transfer_log (id) { - id -> Integer, - grant_id -> Integer, - log_id -> Integer, - chain_id -> Integer, - token_contract -> Binary, - recipient_address -> Binary, - value -> Binary, - created_at -> Integer, - } -} - -diesel::table! { - evm_token_transfer_volume_limit (id) { - id -> Integer, - grant_id -> Integer, - window_secs -> Integer, - max_volume -> Binary, - } -} - -diesel::table! { - evm_transaction_log (id) { - id -> Integer, - wallet_access_id -> Integer, - grant_id -> Integer, - chain_id -> Integer, - eth_value -> Binary, - signed_at -> Integer, - } -} - -diesel::table! { - evm_wallet (id) { - id -> Integer, - address -> Binary, - aead_encrypted_id -> Integer, - created_at -> Integer, - } -} - -diesel::table! { - evm_wallet_access (id) { - id -> Integer, - wallet_id -> Integer, - client_id -> Integer, - created_at -> Integer, - } -} - -diesel::table! { - integrity_envelope (id) { - id -> Integer, - entity_kind -> Text, - entity_id -> Binary, - payload_version -> Integer, - key_version -> Integer, - mac -> Binary, - signed_at -> Integer, - created_at -> Integer, - } -} - -diesel::table! { - program_client (id) { - id -> Integer, - public_key -> Binary, - metadata_id -> Integer, - created_at -> Integer, - updated_at -> Integer, - } -} - -diesel::table! { - root_key_history (id) { - id -> Integer, - root_key_encryption_nonce -> Binary, - data_encryption_nonce -> Binary, - ciphertext -> Binary, - tag -> Binary, - schema_version -> Integer, - salt -> Binary, - } -} - -diesel::table! { - tls_history (id) { - id -> Integer, - cert -> Text, - cert_key -> Text, - ca_cert -> Text, - ca_key -> Text, - created_at -> Integer, - } -} - -diesel::table! { - operator_client (id) { - id -> Integer, - public_key -> Binary, - created_at -> Integer, - updated_at -> Integer, - } -} - -diesel::joinable!(aead_encrypted -> root_key_history (associated_root_key_id)); -diesel::joinable!(arbiter_settings -> root_key_history (root_key_id)); -diesel::joinable!(arbiter_settings -> tls_history (tls_id)); -diesel::joinable!(client_metadata_history -> client_metadata (metadata_id)); -diesel::joinable!(client_metadata_history -> program_client (client_id)); -diesel::joinable!(evm_basic_grant -> evm_wallet_access (wallet_access_id)); -diesel::joinable!(evm_ether_transfer_grant -> evm_basic_grant (basic_grant_id)); -diesel::joinable!(evm_ether_transfer_grant -> evm_ether_transfer_limit (limit_id)); -diesel::joinable!(evm_ether_transfer_grant_target -> evm_ether_transfer_grant (grant_id)); -diesel::joinable!(evm_token_transfer_grant -> evm_basic_grant (basic_grant_id)); -diesel::joinable!(evm_token_transfer_log -> evm_token_transfer_grant (grant_id)); -diesel::joinable!(evm_token_transfer_log -> evm_transaction_log (log_id)); -diesel::joinable!(evm_token_transfer_volume_limit -> evm_token_transfer_grant (grant_id)); -diesel::joinable!(evm_transaction_log -> evm_basic_grant (grant_id)); -diesel::joinable!(evm_transaction_log -> evm_wallet_access (wallet_access_id)); -diesel::joinable!(evm_wallet -> aead_encrypted (aead_encrypted_id)); -diesel::joinable!(evm_wallet_access -> evm_wallet (wallet_id)); -diesel::joinable!(evm_wallet_access -> program_client (client_id)); -diesel::joinable!(program_client -> client_metadata (metadata_id)); - -diesel::allow_tables_to_appear_in_same_query!( - aead_encrypted, - arbiter_settings, - client_metadata, - client_metadata_history, - evm_basic_grant, - evm_ether_transfer_grant, - evm_ether_transfer_grant_target, - evm_ether_transfer_limit, - evm_token_transfer_grant, - evm_token_transfer_log, - evm_token_transfer_volume_limit, - evm_transaction_log, - evm_wallet, - evm_wallet_access, - integrity_envelope, - program_client, - root_key_history, - tls_history, - operator_client, -); +// @generated automatically by Diesel CLI. + +diesel::table! { + aead_encrypted (id) { + id -> Integer, + current_nonce -> Binary, + ciphertext -> Binary, + tag -> Binary, + schema_version -> Integer, + associated_root_key_id -> Integer, + created_at -> Integer, + } +} + +diesel::table! { + arbiter_settings (id) { + id -> Integer, + root_key_id -> Nullable, + tls_id -> Nullable, + } +} + +diesel::table! { + client_metadata (id) { + id -> Integer, + name -> Text, + description -> Nullable, + version -> Nullable, + created_at -> Integer, + } +} + +diesel::table! { + client_metadata_history (id) { + id -> Integer, + metadata_id -> Integer, + client_id -> Integer, + created_at -> Integer, + } +} + +diesel::table! { + evm_basic_grant (id) { + id -> Integer, + wallet_access_id -> Integer, + chain_id -> Integer, + valid_from -> Nullable, + valid_until -> Nullable, + max_gas_fee_per_gas -> Nullable, + max_priority_fee_per_gas -> Nullable, + rate_limit_count -> Nullable, + rate_limit_window_secs -> Nullable, + revoked_at -> Nullable, + created_at -> Integer, + } +} + +diesel::table! { + evm_ether_transfer_grant (id) { + id -> Integer, + basic_grant_id -> Integer, + limit_id -> Integer, + } +} + +diesel::table! { + evm_ether_transfer_grant_target (id) { + id -> Integer, + grant_id -> Integer, + address -> Binary, + } +} + +diesel::table! { + evm_ether_transfer_limit (id) { + id -> Integer, + window_secs -> Integer, + max_volume -> Binary, + } +} + +diesel::table! { + evm_token_transfer_grant (id) { + id -> Integer, + basic_grant_id -> Integer, + token_contract -> Binary, + receiver -> Nullable, + } +} + +diesel::table! { + evm_token_transfer_log (id) { + id -> Integer, + grant_id -> Integer, + log_id -> Integer, + chain_id -> Integer, + token_contract -> Binary, + recipient_address -> Binary, + value -> Binary, + created_at -> Integer, + } +} + +diesel::table! { + evm_token_transfer_volume_limit (id) { + id -> Integer, + grant_id -> Integer, + window_secs -> Integer, + max_volume -> Binary, + } +} + +diesel::table! { + evm_transaction_log (id) { + id -> Integer, + wallet_access_id -> Integer, + grant_id -> Integer, + chain_id -> Integer, + eth_value -> Binary, + signed_at -> Integer, + } +} + +diesel::table! { + evm_wallet (id) { + id -> Integer, + address -> Binary, + aead_encrypted_id -> Integer, + created_at -> Integer, + } +} + +diesel::table! { + evm_wallet_access (id) { + id -> Integer, + wallet_id -> Integer, + client_id -> Integer, + created_at -> Integer, + } +} + +diesel::table! { + integrity_envelope (id) { + id -> Integer, + entity_kind -> Text, + entity_id -> Binary, + payload_version -> Integer, + key_version -> Integer, + mac -> Binary, + signed_at -> Integer, + created_at -> Integer, + } +} + +diesel::table! { + program_client (id) { + id -> Integer, + public_key -> Binary, + metadata_id -> Integer, + created_at -> Integer, + updated_at -> Integer, + } +} + +diesel::table! { + root_key_history (id) { + id -> Integer, + root_key_encryption_nonce -> Binary, + data_encryption_nonce -> Binary, + ciphertext -> Binary, + tag -> Binary, + schema_version -> Integer, + salt -> Binary, + } +} + +diesel::table! { + tls_history (id) { + id -> Integer, + cert -> Text, + cert_key -> Text, + ca_cert -> Text, + ca_key -> Text, + created_at -> Integer, + } +} + +diesel::table! { + operator_client (id) { + id -> Integer, + public_key -> Binary, + created_at -> Integer, + updated_at -> Integer, + } +} + +diesel::joinable!(aead_encrypted -> root_key_history (associated_root_key_id)); +diesel::joinable!(arbiter_settings -> root_key_history (root_key_id)); +diesel::joinable!(arbiter_settings -> tls_history (tls_id)); +diesel::joinable!(client_metadata_history -> client_metadata (metadata_id)); +diesel::joinable!(client_metadata_history -> program_client (client_id)); +diesel::joinable!(evm_basic_grant -> evm_wallet_access (wallet_access_id)); +diesel::joinable!(evm_ether_transfer_grant -> evm_basic_grant (basic_grant_id)); +diesel::joinable!(evm_ether_transfer_grant -> evm_ether_transfer_limit (limit_id)); +diesel::joinable!(evm_ether_transfer_grant_target -> evm_ether_transfer_grant (grant_id)); +diesel::joinable!(evm_token_transfer_grant -> evm_basic_grant (basic_grant_id)); +diesel::joinable!(evm_token_transfer_log -> evm_token_transfer_grant (grant_id)); +diesel::joinable!(evm_token_transfer_log -> evm_transaction_log (log_id)); +diesel::joinable!(evm_token_transfer_volume_limit -> evm_token_transfer_grant (grant_id)); +diesel::joinable!(evm_transaction_log -> evm_basic_grant (grant_id)); +diesel::joinable!(evm_transaction_log -> evm_wallet_access (wallet_access_id)); +diesel::joinable!(evm_wallet -> aead_encrypted (aead_encrypted_id)); +diesel::joinable!(evm_wallet_access -> evm_wallet (wallet_id)); +diesel::joinable!(evm_wallet_access -> program_client (client_id)); +diesel::joinable!(program_client -> client_metadata (metadata_id)); + +diesel::allow_tables_to_appear_in_same_query!( + aead_encrypted, + arbiter_settings, + client_metadata, + client_metadata_history, + evm_basic_grant, + evm_ether_transfer_grant, + evm_ether_transfer_grant_target, + evm_ether_transfer_limit, + evm_token_transfer_grant, + evm_token_transfer_log, + evm_token_transfer_volume_limit, + evm_transaction_log, + evm_wallet, + evm_wallet_access, + integrity_envelope, + program_client, + root_key_history, + tls_history, + operator_client, +); diff --git a/server/crates/arbiter-server/src/evm/abi.rs b/server/crates/arbiter-server/src/evm/abi.rs index 561ce34..b04309d 100644 --- a/server/crates/arbiter-server/src/evm/abi.rs +++ b/server/crates/arbiter-server/src/evm/abi.rs @@ -1,84 +1,84 @@ -use alloy::sol; - -sol! { - interface IERC20 { - event Transfer(address indexed from, address indexed to, uint256 value); - event Approval(address indexed owner, address indexed spender, uint256 value); - - function totalSupply() external view returns (uint256); - function balanceOf(address account) external view returns (uint256); - function transfer(address to, uint256 value) external returns (bool); - function allowance(address owner, address spender) external view returns (uint256); - function approve(address spender, uint256 value) external returns (bool); - function transferFrom(address from, address to, uint256 value) external returns (bool); - } -} - -sol! { - /// ERC-721: Non-Fungible Token Standard. - #[derive(Debug)] - interface IERC721 { - event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); - event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); - event ApprovalForAll(address indexed owner, address indexed operator, bool approved); - - function balanceOf(address owner) external view returns (uint256 balance); - function ownerOf(uint256 tokenId) external view returns (address owner); - function safeTransferFrom(address from, address to, uint256 tokenId) external; - function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; - function transferFrom(address from, address to, uint256 tokenId) external; - function approve(address to, uint256 tokenId) external; - function setApprovalForAll(address operator, bool approved) external; - function getApproved(uint256 tokenId) external view returns (address operator); - function isApprovedForAll(address owner, address operator) external view returns (bool); - } -} - -sol! { - /// Wrapped Ether — the only functions beyond ERC-20 that matter. - #[derive(Debug)] - interface IWETH { - function deposit() external payable; - function withdraw(uint256 wad) external; - } -} - -sol! { - /// Permit2 — Uniswap's canonical token approval manager. - /// Replaces per-contract ERC-20 `approve()` with a single approval hub. - #[derive(Debug)] - interface IPermit2 { - struct TokenPermissions { - address token; - uint256 amount; - } - - struct PermitSingle { - TokenPermissions details; - address spender; - uint256 sigDeadline; - } - - struct PermitBatch { - TokenPermissions[] details; - address spender; - uint256 sigDeadline; - } - - struct AllowanceTransferDetails { - address from; - address to; - uint160 amount; - address token; - } - - function approve(address token, address spender, uint160 amount, uint48 expiration) external; - function permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature) external; - function permit(address owner, PermitBatch calldata permitBatch, bytes calldata signature) external; - function transferFrom(address from, address to, uint160 amount, address token) external; - function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external; - - function allowance(address user, address token, address spender) - external view returns (uint160 amount, uint48 expiration, uint48 nonce); - } -} +use alloy::sol; + +sol! { + interface IERC20 { + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); + + function totalSupply() external view returns (uint256); + function balanceOf(address account) external view returns (uint256); + function transfer(address to, uint256 value) external returns (bool); + function allowance(address owner, address spender) external view returns (uint256); + function approve(address spender, uint256 value) external returns (bool); + function transferFrom(address from, address to, uint256 value) external returns (bool); + } +} + +sol! { + /// ERC-721: Non-Fungible Token Standard. + #[derive(Debug)] + interface IERC721 { + event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); + event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); + event ApprovalForAll(address indexed owner, address indexed operator, bool approved); + + function balanceOf(address owner) external view returns (uint256 balance); + function ownerOf(uint256 tokenId) external view returns (address owner); + function safeTransferFrom(address from, address to, uint256 tokenId) external; + function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; + function transferFrom(address from, address to, uint256 tokenId) external; + function approve(address to, uint256 tokenId) external; + function setApprovalForAll(address operator, bool approved) external; + function getApproved(uint256 tokenId) external view returns (address operator); + function isApprovedForAll(address owner, address operator) external view returns (bool); + } +} + +sol! { + /// Wrapped Ether — the only functions beyond ERC-20 that matter. + #[derive(Debug)] + interface IWETH { + function deposit() external payable; + function withdraw(uint256 wad) external; + } +} + +sol! { + /// Permit2 — Uniswap's canonical token approval manager. + /// Replaces per-contract ERC-20 `approve()` with a single approval hub. + #[derive(Debug)] + interface IPermit2 { + struct TokenPermissions { + address token; + uint256 amount; + } + + struct PermitSingle { + TokenPermissions details; + address spender; + uint256 sigDeadline; + } + + struct PermitBatch { + TokenPermissions[] details; + address spender; + uint256 sigDeadline; + } + + struct AllowanceTransferDetails { + address from; + address to; + uint160 amount; + address token; + } + + function approve(address token, address spender, uint160 amount, uint48 expiration) external; + function permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature) external; + function permit(address owner, PermitBatch calldata permitBatch, bytes calldata signature) external; + function transferFrom(address from, address to, uint160 amount, address token) external; + function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external; + + function allowance(address user, address token, address spender) + external view returns (uint160 amount, uint48 expiration, uint48 nonce); + } +} diff --git a/server/crates/arbiter-server/src/evm/mod.rs b/server/crates/arbiter-server/src/evm/mod.rs index 75d189d..fb503c3 100644 --- a/server/crates/arbiter-server/src/evm/mod.rs +++ b/server/crates/arbiter-server/src/evm/mod.rs @@ -1,876 +1,876 @@ -use diesel_async::{AsyncConnection, RunQueryDsl}; -use kameo::actor::ActorRef; - -use crate::{ - actors::vault::Vault, - crypto::integrity, - db::{ - self, DatabaseError, - models::{ - EvmBasicGrant, EvmEtherTransferGrant, EvmEtherTransferGrantTarget, - EvmEtherTransferLimit, EvmTokenTransferGrant, EvmTokenTransferVolumeLimit, - EvmWalletAccess, NewEvmBasicGrant, NewEvmTransactionLog, SqliteTimestamp, - }, - schema::{self, evm_transaction_log}, - }, - evm::policies::{ - CombinedSettings, DatabaseID, EvalContext, EvalViolation, Grant, Policy, - SharedGrantSettings, SpecificGrant, SpecificMeaning, VolumeRateLimit, - ether_transfer::EtherTransfer, token_transfers::TokenTransfer, - }, -}; - -use alloy::{ - consensus::TxEip1559, - primitives::{Address, TxKind, U256}, -}; -use chrono::Utc; -use diesel::{ - ExpressionMethods as _, OptionalExtension, QueryDsl as _, QueryResult, SelectableHelper, - insert_into, sqlite::Sqlite, update, -}; - -pub mod abi; -pub mod safe_signer; - -pub mod policies; -mod utils; - -/// Errors that can only occur once the transaction meaning is known (during policy evaluation) -#[derive(Debug, thiserror::Error)] -pub enum PolicyError { - #[error("Database error")] - Database(#[from] DatabaseError), - #[error("Transaction violates policy: {0:?}")] - Violations(Vec), - #[error("No matching grant found")] - NoMatchingGrant, - - #[error("Integrity error: {0}")] - Integrity(#[from] integrity::Error), -} - -#[derive(Debug, thiserror::Error)] -pub enum VetError { - #[error("Contract creation transactions are not supported")] - ContractCreationNotSupported, - #[error("Engine can't classify this transaction")] - UnsupportedTransactionType, - #[error("Policy evaluation failed: {1}")] - Evaluated(SpecificMeaning, #[source] PolicyError), -} - -#[derive(Debug, thiserror::Error)] -pub enum AnalyzeError { - #[error("Engine doesn't support granting permissions for contract creation")] - ContractCreationNotSupported, - - #[error("Unsupported transaction type")] - UnsupportedTransactionType, -} - -#[derive(Debug, thiserror::Error)] -pub enum ListError { - #[error("Database error")] - Database(#[from] DatabaseError), - - #[error("Integrity verification failed for grant")] - Integrity(#[from] integrity::Error), -} - -/// Controls whether a transaction should be executed or only validated -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum RunKind { - /// Validate and record the transaction - Execution, - /// Validate only, do not record - CheckOnly, -} - -async fn check_shared_constraints( - context: &EvalContext, - shared: &SharedGrantSettings, - shared_grant_id: DatabaseID, - conn: &mut impl AsyncConnection, -) -> QueryResult> { - let mut violations = Vec::new(); - let now = Utc::now(); - - if shared.chain != context.chain { - violations.push(EvalViolation::MismatchingChainId { - expected: shared.chain, - actual: context.chain, - }); - return Ok(violations); - } - - // Validity window - if shared.valid_from.is_some_and(|t| now < t) || shared.valid_until.is_some_and(|t| now > t) { - violations.push(EvalViolation::InvalidTime); - } - - // Gas fee caps - let fee_exceeded = shared - .max_gas_fee_per_gas - .is_some_and(|cap| U256::from(context.max_fee_per_gas) > cap); - let priority_exceeded = shared - .max_priority_fee_per_gas - .is_some_and(|cap| U256::from(context.max_priority_fee_per_gas) > cap); - if fee_exceeded || priority_exceeded { - violations.push(EvalViolation::GasLimitExceeded { - max_gas_fee_per_gas: shared.max_gas_fee_per_gas, - max_priority_fee_per_gas: shared.max_priority_fee_per_gas, - }); - } - - // Transaction count rate limit - if let Some(rate_limit) = &shared.rate_limit { - let window_start = SqliteTimestamp(now - rate_limit.window); - let count: i64 = evm_transaction_log::table - .filter(evm_transaction_log::grant_id.eq(shared_grant_id)) - .filter(evm_transaction_log::signed_at.ge(window_start)) - .count() - .get_result(conn) - .await?; - - if count >= rate_limit.count.into() { - violations.push(EvalViolation::RateLimitExceeded); - } - } - - Ok(violations) -} - -// Supporting only EIP-1559 transactions for now, but we can easily extend this to support legacy transactions if needed -pub struct Engine { - db: db::DatabasePool, - vault: ActorRef, -} - -impl Engine { - async fn vet_transaction( - &self, - context: EvalContext, - meaning: &P::Meaning, - run_kind: RunKind, - ) -> Result<(), PolicyError> - where - P::Settings: Clone, - { - let mut conn = self.db.get().await.map_err(DatabaseError::from)?; - - let grant = P::try_find_grant(&context, &mut conn) - .await - .map_err(DatabaseError::from)? - .ok_or(PolicyError::NoMatchingGrant)?; - - integrity::verify_entity(&mut conn, &self.vault, &grant.settings, grant.id).await?; - - let mut violations = check_shared_constraints( - &context, - &grant.settings.shared, - grant.common_settings_id, - &mut conn, - ) - .await - .map_err(DatabaseError::from)?; - violations.extend( - P::evaluate(&context, meaning, &grant, &mut conn) - .await - .map_err(DatabaseError::from)?, - ); - - if !violations.is_empty() { - return Err(PolicyError::Violations(violations)); - } - - if run_kind == RunKind::Execution { - conn.transaction(async |conn| { - let log_id: i32 = insert_into(evm_transaction_log::table) - .values(&NewEvmTransactionLog { - grant_id: grant.common_settings_id, - wallet_access_id: context.target.id, - chain_id: context.chain.into(), - eth_value: utils::u256_to_bytes(context.value).to_vec(), - signed_at: Utc::now().into(), - }) - .returning(evm_transaction_log::id) - .get_result(&mut *conn) - .await?; - - P::record_transaction(&context, meaning, log_id, &grant, &mut *conn).await?; - - QueryResult::Ok(()) - }) - .await - .map_err(DatabaseError::from)?; - } - - Ok(()) - } -} - -impl Engine { - pub const fn new(db: db::DatabasePool, vault: ActorRef) -> Self { - Self { db, vault } - } - - pub async fn create_grant( - &self, - full_grant: CombinedSettings, - ) -> Result - where - P::Settings: Clone, - { - let mut conn = self.db.get().await?; - let vault = self.vault.clone(); - - let id = conn - .transaction(async |conn| { - use schema::evm_basic_grant; - - #[expect( - clippy::cast_possible_truncation, - clippy::cast_possible_wrap, - clippy::as_conversions, - reason = "fixme! #86" - )] - let basic_grant: EvmBasicGrant = insert_into(evm_basic_grant::table) - .values(&NewEvmBasicGrant { - chain_id: full_grant.shared.chain.into(), - wallet_access_id: full_grant.shared.wallet_access_id, - valid_from: full_grant.shared.valid_from.map(SqliteTimestamp), - valid_until: full_grant.shared.valid_until.map(SqliteTimestamp), - max_gas_fee_per_gas: full_grant - .shared - .max_gas_fee_per_gas - .map(|fee| utils::u256_to_bytes(fee).to_vec()), - max_priority_fee_per_gas: full_grant - .shared - .max_priority_fee_per_gas - .map(|fee| utils::u256_to_bytes(fee).to_vec()), - rate_limit_count: full_grant - .shared - .rate_limit - .as_ref() - .map(|rl| rl.count as i32), - rate_limit_window_secs: full_grant - .shared - .rate_limit - .as_ref() - .map(|rl| rl.window.num_seconds() as i32), - revoked_at: None, - }) - .returning(evm_basic_grant::all_columns) - .get_result(&mut *conn) - .await?; - - P::create_grant(&basic_grant, &full_grant.specific, &mut *conn).await?; - - integrity::sign_entity(&mut *conn, &vault, &full_grant, basic_grant.id) - .await - .map_err(|_| diesel::result::Error::RollbackTransaction)?; - - QueryResult::Ok(basic_grant.id) - }) - .await?; - - Ok(id) - } - - pub async fn revoke_grant( - &self, - basic_grant_id: i32, - ) -> Result<(), DatabaseError> { - let mut conn = self.db.get().await.map_err(DatabaseError::from)?; - let vault = self.vault.clone(); - - conn.transaction(async move |conn| { - use crate::db::schema::{ - evm_basic_grant, evm_ether_transfer_grant, evm_ether_transfer_grant_target, - evm_ether_transfer_limit, evm_token_transfer_grant, - evm_token_transfer_volume_limit, - }; - - update(evm_basic_grant::table) - .filter(evm_basic_grant::id.eq(basic_grant_id)) - .set(evm_basic_grant::revoked_at.eq(SqliteTimestamp(Utc::now()))) - .execute(&mut *conn) - .await?; - - let basic_grant: EvmBasicGrant = evm_basic_grant::table - .filter(evm_basic_grant::id.eq(basic_grant_id)) - .select(EvmBasicGrant::as_select()) - .first(&mut *conn) - .await?; - - let shared = SharedGrantSettings::try_from_model(basic_grant)?; - - if let Some(ether_grant) = evm_ether_transfer_grant::table - .filter(evm_ether_transfer_grant::basic_grant_id.eq(basic_grant_id)) - .select(EvmEtherTransferGrant::as_select()) - .first(&mut *conn) - .await - .optional()? - { - let target_rows: Vec = - evm_ether_transfer_grant_target::table - .filter(evm_ether_transfer_grant_target::grant_id.eq(ether_grant.id)) - .select(EvmEtherTransferGrantTarget::as_select()) - .load(&mut *conn) - .await?; - let targets: Vec
= target_rows - .into_iter() - .filter_map(|target| { - let arr: [u8; 20] = target.address.try_into().ok()?; - Some(Address::from(arr)) - }) - .collect(); - - let limit: EvmEtherTransferLimit = evm_ether_transfer_limit::table - .filter(evm_ether_transfer_limit::id.eq(ether_grant.limit_id)) - .select(EvmEtherTransferLimit::as_select()) - .first(&mut *conn) - .await?; - - let settings = CombinedSettings { - shared: shared.clone(), - specific: policies::ether_transfer::Settings { - target: targets, - limit: VolumeRateLimit { - max_volume: utils::try_bytes_to_u256(&limit.max_volume).map_err( - |err| { - diesel::result::Error::DeserializationError(Box::new(err)) - }, - )?, - window: chrono::Duration::seconds(limit.window_secs.into()), - }, - }, - }; - - integrity::sign_entity(&mut *conn, &vault, &settings, basic_grant_id) - .await - .map_err(|_| diesel::result::Error::RollbackTransaction)?; - - return QueryResult::Ok(()); - } - - if let Some(token_grant) = evm_token_transfer_grant::table - .filter(evm_token_transfer_grant::basic_grant_id.eq(basic_grant_id)) - .select(EvmTokenTransferGrant::as_select()) - .first(&mut *conn) - .await - .optional()? - { - let volume_limit_rows: Vec = - evm_token_transfer_volume_limit::table - .filter(evm_token_transfer_volume_limit::grant_id.eq(token_grant.id)) - .select(EvmTokenTransferVolumeLimit::as_select()) - .load(&mut *conn) - .await?; - let volume_limits: Vec = volume_limit_rows - .into_iter() - .map(|row| { - Ok(VolumeRateLimit { - max_volume: utils::try_bytes_to_u256(&row.max_volume).map_err( - |err| { - diesel::result::Error::DeserializationError(Box::new(err)) - }, - )?, - window: chrono::Duration::seconds(row.window_secs.into()), - }) - }) - .collect::>>()?; - - let target: Option
= match token_grant.receiver { - None => None, - Some(bytes) => { - let arr: [u8; 20] = bytes.try_into().map_err(|_| { - diesel::result::Error::DeserializationError( - "Invalid receiver address length".into(), - ) - })?; - Some(Address::from(arr)) - } - }; - - let token_contract: [u8; 20] = - token_grant.token_contract.clone().try_into().map_err(|_| { - diesel::result::Error::DeserializationError( - "Invalid token contract address length".into(), - ) - })?; - - let settings = CombinedSettings { - shared, - specific: policies::token_transfers::Settings { - token_contract: Address::from(token_contract), - target, - volume_limits, - }, - }; - - integrity::sign_entity(&mut *conn, &vault, &settings, basic_grant_id) - .await - .map_err(|_| diesel::result::Error::RollbackTransaction)?; - - return QueryResult::Ok(()); - } - - Err(diesel::result::Error::NotFound) - }) - .await - .map_err(DatabaseError::from) - } - - async fn list_one_kind( - &self, - conn: &mut impl AsyncConnection, - ) -> Result>, ListError> - where - Y: From, - { - let all_grants = Kind::find_all_grants(conn) - .await - .map_err(DatabaseError::from)?; - - // Verify integrity of all grants before returning any results - for grant in &all_grants { - integrity::verify_entity(conn, &self.vault, &grant.settings, grant.id).await?; - } - - Ok(all_grants.into_iter().map(|g| Grant { - id: g.id, - common_settings_id: g.common_settings_id, - settings: g.settings.generalize(), - })) - } - - pub async fn list_all_grants(&self) -> Result>, ListError> { - let mut conn = self.db.get().await.map_err(DatabaseError::from)?; - - let mut grants: Vec> = Vec::new(); - - grants.extend(self.list_one_kind::(&mut conn).await?); - grants.extend(self.list_one_kind::(&mut conn).await?); - - Ok(grants) - } - - pub async fn evaluate_transaction( - &self, - target: EvmWalletAccess, - transaction: TxEip1559, - run_kind: RunKind, - ) -> Result { - let TxKind::Call(to) = transaction.to else { - return Err(VetError::ContractCreationNotSupported); - }; - let context = EvalContext { - target, - chain: transaction.chain_id, - to, - value: transaction.value, - calldata: transaction.input.clone(), - max_fee_per_gas: transaction.max_fee_per_gas, - max_priority_fee_per_gas: transaction.max_priority_fee_per_gas, - }; - - if let Some(meaning) = EtherTransfer::analyze(&context) { - return match self - .vet_transaction::(context, &meaning, run_kind) - .await - { - Ok(()) => Ok(meaning.into()), - Err(e) => Err(VetError::Evaluated(meaning.into(), e)), - }; - } - if let Some(meaning) = TokenTransfer::analyze(&context) { - return match self - .vet_transaction::(context, &meaning, run_kind) - .await - { - Ok(()) => Ok(meaning.into()), - Err(e) => Err(VetError::Evaluated(meaning.into(), e)), - }; - } - - Err(VetError::UnsupportedTransactionType) - } -} - -#[cfg(test)] -mod tests { - use alloy::primitives::{Address, Bytes, U256, address}; - use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; - use chrono::{Duration, Utc}; - use diesel::{SelectableHelper, insert_into}; - use diesel_async::RunQueryDsl; - use kameo::{actor::ActorRef, prelude::Spawn}; - use rstest::rstest; - - use crate::actors::{GlobalActors, vault::{Bootstrap, Vault}}; - use crate::crypto::integrity; - use crate::db::{ - self, DatabaseConnection, - models::{ - EvmBasicGrant, EvmWalletAccess, NewEvmBasicGrant, NewEvmTransactionLog, SqliteTimestamp, - }, - schema::{evm_basic_grant, evm_transaction_log}, - }; - use crate::evm::policies::ether_transfer::EtherTransfer; - use crate::evm::policies::{ - CombinedSettings, EvalContext, EvalViolation, Policy, SharedGrantSettings, - TransactionRateLimit, VolumeRateLimit, - }; - - use super::check_shared_constraints; - - const WALLET_ACCESS_ID: i32 = 1; - const CHAIN_ID: u64 = 1; - const RECIPIENT: Address = address!("1111111111111111111111111111111111111111"); - - fn context() -> EvalContext { - EvalContext { - target: EvmWalletAccess { - id: WALLET_ACCESS_ID, - wallet_id: 10, - client_id: 20, - created_at: SqliteTimestamp(Utc::now()), - }, - chain: CHAIN_ID, - to: RECIPIENT, - value: U256::ZERO, - calldata: Bytes::new(), - max_fee_per_gas: 100, - max_priority_fee_per_gas: 10, - } - } - - fn shared_settings() -> SharedGrantSettings { - SharedGrantSettings { - wallet_access_id: WALLET_ACCESS_ID, - chain: CHAIN_ID, - valid_from: None, - valid_until: None, - revoked_at: None, - max_gas_fee_per_gas: None, - max_priority_fee_per_gas: None, - rate_limit: None, - } - } - - async fn insert_basic_grant( - conn: &mut DatabaseConnection, - shared: &SharedGrantSettings, - ) -> EvmBasicGrant { - #[expect( - clippy::cast_possible_truncation, - clippy::cast_possible_wrap, - clippy::as_conversions, - reason = "fixme! #86" - )] - insert_into(evm_basic_grant::table) - .values(NewEvmBasicGrant { - wallet_access_id: shared.wallet_access_id, - chain_id: shared.chain.into(), - valid_from: shared.valid_from.map(SqliteTimestamp), - valid_until: shared.valid_until.map(SqliteTimestamp), - max_gas_fee_per_gas: shared - .max_gas_fee_per_gas - .map(|fee| super::utils::u256_to_bytes(fee).to_vec()), - max_priority_fee_per_gas: shared - .max_priority_fee_per_gas - .map(|fee| super::utils::u256_to_bytes(fee).to_vec()), - rate_limit_count: shared.rate_limit.as_ref().map(|limit| limit.count as i32), - rate_limit_window_secs: shared - .rate_limit - .as_ref() - .map(|limit| limit.window.num_seconds() as i32), - revoked_at: None, - }) - .returning(EvmBasicGrant::as_select()) - .get_result(conn) - .await - .unwrap() - } - - #[rstest] - #[case::matching_chain(CHAIN_ID, false)] - #[case::mismatching_chain(CHAIN_ID + 1, true)] - #[tokio::test] - async fn check_shared_constraints_enforces_chain_id( - #[case] context_chain: u64, - #[case] expect_mismatch: bool, - ) { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let context = EvalContext { - chain: context_chain, - ..context() - }; - - let violations = check_shared_constraints(&context, &shared_settings(), 999, &mut *conn) - .await - .unwrap(); - - assert_eq!( - violations - .iter() - .any(|violation| matches!(violation, EvalViolation::MismatchingChainId { .. })), - expect_mismatch - ); - - if expect_mismatch { - assert_eq!(violations.len(), 1); - } else { - assert!(violations.is_empty()); - } - } - - #[rstest] - #[case::valid_from_in_bounds(Some(Utc::now() - Duration::hours(1)), None, false)] - #[case::valid_from_out_of_bounds(Some(Utc::now() + Duration::hours(1)), None, true)] - #[case::valid_until_in_bounds(None, Some(Utc::now() + Duration::hours(1)), false)] - #[case::valid_until_out_of_bounds(None, Some(Utc::now() - Duration::hours(1)), true)] - #[tokio::test] - async fn check_shared_constraints_enforces_validity_window( - #[case] valid_from: Option>, - #[case] valid_until: Option>, - #[case] expect_invalid_time: bool, - ) { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let shared = SharedGrantSettings { - valid_from, - valid_until, - ..shared_settings() - }; - - let violations = check_shared_constraints(&context(), &shared, 999, &mut *conn) - .await - .unwrap(); - - assert_eq!( - violations - .iter() - .any(|violation| matches!(violation, EvalViolation::InvalidTime)), - expect_invalid_time - ); - - if expect_invalid_time { - assert_eq!(violations.len(), 1); - } else { - assert!(violations.is_empty()); - } - } - - #[rstest] - #[case::max_fee_within_limit(Some(U256::from(100u64)), None, 100, 10, false)] - #[case::max_fee_exceeded(Some(U256::from(99u64)), None, 100, 10, true)] - #[case::priority_fee_within_limit(None, Some(U256::from(10u64)), 100, 10, false)] - #[case::priority_fee_exceeded(None, Some(U256::from(9u64)), 100, 10, true)] - #[tokio::test] - async fn check_shared_constraints_enforces_gas_fee_caps( - #[case] max_gas_fee_per_gas: Option, - #[case] max_priority_fee_per_gas: Option, - #[case] actual_max_fee_per_gas: u128, - #[case] actual_max_priority_fee_per_gas: u128, - #[case] expect_gas_limit_violation: bool, - ) { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let context = EvalContext { - max_fee_per_gas: actual_max_fee_per_gas, - max_priority_fee_per_gas: actual_max_priority_fee_per_gas, - ..context() - }; - - let shared = SharedGrantSettings { - max_gas_fee_per_gas, - max_priority_fee_per_gas, - ..shared_settings() - }; - let violations = check_shared_constraints(&context, &shared, 999, &mut *conn) - .await - .unwrap(); - - assert_eq!( - violations - .iter() - .any(|violation| matches!(violation, EvalViolation::GasLimitExceeded { .. })), - expect_gas_limit_violation - ); - - if expect_gas_limit_violation { - assert_eq!(violations.len(), 1); - } else { - assert!(violations.is_empty()); - } - } - - #[rstest] - #[case::under_rate_limit(2, false)] - #[case::at_rate_limit(1, true)] - #[tokio::test] - async fn check_shared_constraints_enforces_rate_limit( - #[case] rate_limit_count: u32, - #[case] expect_rate_limit_violation: bool, - ) { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let shared = SharedGrantSettings { - rate_limit: Some(TransactionRateLimit { - count: rate_limit_count, - window: Duration::hours(1), - }), - ..shared_settings() - }; - - let basic_grant = insert_basic_grant(&mut conn, &shared).await; - - insert_into(evm_transaction_log::table) - .values(NewEvmTransactionLog { - grant_id: basic_grant.id, - wallet_access_id: WALLET_ACCESS_ID, - chain_id: CHAIN_ID.into(), - eth_value: super::utils::u256_to_bytes(U256::ZERO).to_vec(), - signed_at: SqliteTimestamp(Utc::now()), - }) - .execute(&mut *conn) - .await - .unwrap(); - - let violations = check_shared_constraints(&context(), &shared, basic_grant.id, &mut *conn) - .await - .unwrap(); - - assert_eq!( - violations - .iter() - .any(|violation| matches!(violation, EvalViolation::RateLimitExceeded)), - expect_rate_limit_violation - ); - - if expect_rate_limit_violation { - assert_eq!(violations.len(), 1); - } else { - assert!(violations.is_empty()); - } - } - - async fn bootstrapped_vault(db: &db::DatabasePool) -> ActorRef { - let actor = Vault::spawn( - Vault::new(db.clone(), GlobalActors::spawn_message_bus()) - .await - .unwrap(), - ); - actor - .ask(Bootstrap { - seal_key_raw: SafeCell::new(b"integrity-test-seal-key".to_vec()), - }) - .await - .unwrap(); - actor - } - - #[tokio::test] - async fn revoke_grant_preserves_revoked_integrity() { - use crate::db::schema::evm_basic_grant; - use diesel::ExpressionMethods as _; - - let db = db::create_test_pool().await; - let vault = bootstrapped_vault(&db).await; - let engine = super::Engine::new(db.clone(), vault.clone()); - - let full_grant = CombinedSettings { - shared: SharedGrantSettings { - wallet_access_id: WALLET_ACCESS_ID, - chain: CHAIN_ID, - valid_from: None, - valid_until: None, - revoked_at: None, - max_gas_fee_per_gas: None, - max_priority_fee_per_gas: None, - rate_limit: None, - }, - specific: super::policies::ether_transfer::Settings { - target: vec![RECIPIENT], - limit: VolumeRateLimit { - max_volume: U256::from(100u64), - window: Duration::hours(1), - }, - }, - }; - - let grant_id = engine - .create_grant::(full_grant) - .await - .unwrap(); - - engine.revoke_grant(grant_id).await.unwrap(); - - let mut conn = db.get().await.unwrap(); - diesel::update(evm_basic_grant::table) - .filter(evm_basic_grant::id.eq(grant_id)) - .set(evm_basic_grant::revoked_at.eq::>(None)) - .execute(&mut conn) - .await - .unwrap(); - - let wallet_access = EvmWalletAccess { - id: WALLET_ACCESS_ID, - wallet_id: 10, - client_id: 20, - created_at: SqliteTimestamp(Utc::now()), - }; - let context = EvalContext { - target: wallet_access, - chain: CHAIN_ID, - to: RECIPIENT, - value: U256::ONE, - calldata: Bytes::new(), - max_fee_per_gas: 1, - max_priority_fee_per_gas: 1, - }; - - let grant = EtherTransfer::try_find_grant( - &context, &mut conn, - ) - .await - .unwrap() - .unwrap(); - - let result = - integrity::verify_entity(&mut conn, &vault, &grant.settings, grant.id).await; - - assert!(matches!( - result, - Err(integrity::Error::MacMismatch { .. }) - )); - } - - #[test] - fn shared_settings_hash_changes_when_revoked_at_changes() { - use arbiter_crypto::hashing::Hashable; - use sha2::Digest; - - let active = shared_settings(); - let revoked = SharedGrantSettings { - revoked_at: Some(Utc::now()), - ..shared_settings() - }; - - let mut active_hash = sha2::Sha256::new(); - active.hash(&mut active_hash); - - let mut revoked_hash = sha2::Sha256::new(); - revoked.hash(&mut revoked_hash); - - assert_ne!(active_hash.finalize(), revoked_hash.finalize()); - } -} +use diesel_async::{AsyncConnection, RunQueryDsl}; +use kameo::actor::ActorRef; + +use crate::{ + actors::vault::Vault, + crypto::integrity, + db::{ + self, DatabaseError, + models::{ + EvmBasicGrant, EvmEtherTransferGrant, EvmEtherTransferGrantTarget, + EvmEtherTransferLimit, EvmTokenTransferGrant, EvmTokenTransferVolumeLimit, + EvmWalletAccess, NewEvmBasicGrant, NewEvmTransactionLog, SqliteTimestamp, + }, + schema::{self, evm_transaction_log}, + }, + evm::policies::{ + CombinedSettings, DatabaseID, EvalContext, EvalViolation, Grant, Policy, + SharedGrantSettings, SpecificGrant, SpecificMeaning, VolumeRateLimit, + ether_transfer::EtherTransfer, token_transfers::TokenTransfer, + }, +}; + +use alloy::{ + consensus::TxEip1559, + primitives::{Address, TxKind, U256}, +}; +use chrono::Utc; +use diesel::{ + ExpressionMethods as _, OptionalExtension, QueryDsl as _, QueryResult, SelectableHelper, + insert_into, sqlite::Sqlite, update, +}; + +pub mod abi; +pub mod safe_signer; + +pub mod policies; +mod utils; + +/// Errors that can only occur once the transaction meaning is known (during policy evaluation) +#[derive(Debug, thiserror::Error)] +pub enum PolicyError { + #[error("Database error")] + Database(#[from] DatabaseError), + #[error("Transaction violates policy: {0:?}")] + Violations(Vec), + #[error("No matching grant found")] + NoMatchingGrant, + + #[error("Integrity error: {0}")] + Integrity(#[from] integrity::Error), +} + +#[derive(Debug, thiserror::Error)] +pub enum VetError { + #[error("Contract creation transactions are not supported")] + ContractCreationNotSupported, + #[error("Engine can't classify this transaction")] + UnsupportedTransactionType, + #[error("Policy evaluation failed: {1}")] + Evaluated(SpecificMeaning, #[source] PolicyError), +} + +#[derive(Debug, thiserror::Error)] +pub enum AnalyzeError { + #[error("Engine doesn't support granting permissions for contract creation")] + ContractCreationNotSupported, + + #[error("Unsupported transaction type")] + UnsupportedTransactionType, +} + +#[derive(Debug, thiserror::Error)] +pub enum ListError { + #[error("Database error")] + Database(#[from] DatabaseError), + + #[error("Integrity verification failed for grant")] + Integrity(#[from] integrity::Error), +} + +/// Controls whether a transaction should be executed or only validated +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum RunKind { + /// Validate and record the transaction + Execution, + /// Validate only, do not record + CheckOnly, +} + +async fn check_shared_constraints( + context: &EvalContext, + shared: &SharedGrantSettings, + shared_grant_id: DatabaseID, + conn: &mut impl AsyncConnection, +) -> QueryResult> { + let mut violations = Vec::new(); + let now = Utc::now(); + + if shared.chain != context.chain { + violations.push(EvalViolation::MismatchingChainId { + expected: shared.chain, + actual: context.chain, + }); + return Ok(violations); + } + + // Validity window + if shared.valid_from.is_some_and(|t| now < t) || shared.valid_until.is_some_and(|t| now > t) { + violations.push(EvalViolation::InvalidTime); + } + + // Gas fee caps + let fee_exceeded = shared + .max_gas_fee_per_gas + .is_some_and(|cap| U256::from(context.max_fee_per_gas) > cap); + let priority_exceeded = shared + .max_priority_fee_per_gas + .is_some_and(|cap| U256::from(context.max_priority_fee_per_gas) > cap); + if fee_exceeded || priority_exceeded { + violations.push(EvalViolation::GasLimitExceeded { + max_gas_fee_per_gas: shared.max_gas_fee_per_gas, + max_priority_fee_per_gas: shared.max_priority_fee_per_gas, + }); + } + + // Transaction count rate limit + if let Some(rate_limit) = &shared.rate_limit { + let window_start = SqliteTimestamp(now - rate_limit.window); + let count: i64 = evm_transaction_log::table + .filter(evm_transaction_log::grant_id.eq(shared_grant_id)) + .filter(evm_transaction_log::signed_at.ge(window_start)) + .count() + .get_result(conn) + .await?; + + if count >= rate_limit.count.into() { + violations.push(EvalViolation::RateLimitExceeded); + } + } + + Ok(violations) +} + +// Supporting only EIP-1559 transactions for now, but we can easily extend this to support legacy transactions if needed +pub struct Engine { + db: db::DatabasePool, + vault: ActorRef, +} + +impl Engine { + async fn vet_transaction( + &self, + context: EvalContext, + meaning: &P::Meaning, + run_kind: RunKind, + ) -> Result<(), PolicyError> + where + P::Settings: Clone, + { + let mut conn = self.db.get().await.map_err(DatabaseError::from)?; + + let grant = P::try_find_grant(&context, &mut conn) + .await + .map_err(DatabaseError::from)? + .ok_or(PolicyError::NoMatchingGrant)?; + + integrity::verify_entity(&mut conn, &self.vault, &grant.settings, grant.id).await?; + + let mut violations = check_shared_constraints( + &context, + &grant.settings.shared, + grant.common_settings_id, + &mut conn, + ) + .await + .map_err(DatabaseError::from)?; + violations.extend( + P::evaluate(&context, meaning, &grant, &mut conn) + .await + .map_err(DatabaseError::from)?, + ); + + if !violations.is_empty() { + return Err(PolicyError::Violations(violations)); + } + + if run_kind == RunKind::Execution { + conn.transaction(async |conn| { + let log_id: i32 = insert_into(evm_transaction_log::table) + .values(&NewEvmTransactionLog { + grant_id: grant.common_settings_id, + wallet_access_id: context.target.id, + chain_id: context.chain.into(), + eth_value: utils::u256_to_bytes(context.value).to_vec(), + signed_at: Utc::now().into(), + }) + .returning(evm_transaction_log::id) + .get_result(&mut *conn) + .await?; + + P::record_transaction(&context, meaning, log_id, &grant, &mut *conn).await?; + + QueryResult::Ok(()) + }) + .await + .map_err(DatabaseError::from)?; + } + + Ok(()) + } +} + +impl Engine { + pub const fn new(db: db::DatabasePool, vault: ActorRef) -> Self { + Self { db, vault } + } + + pub async fn create_grant( + &self, + full_grant: CombinedSettings, + ) -> Result + where + P::Settings: Clone, + { + let mut conn = self.db.get().await?; + let vault = self.vault.clone(); + + let id = conn + .transaction(async |conn| { + use schema::evm_basic_grant; + + #[expect( + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::as_conversions, + reason = "fixme! #86" + )] + let basic_grant: EvmBasicGrant = insert_into(evm_basic_grant::table) + .values(&NewEvmBasicGrant { + chain_id: full_grant.shared.chain.into(), + wallet_access_id: full_grant.shared.wallet_access_id, + valid_from: full_grant.shared.valid_from.map(SqliteTimestamp), + valid_until: full_grant.shared.valid_until.map(SqliteTimestamp), + max_gas_fee_per_gas: full_grant + .shared + .max_gas_fee_per_gas + .map(|fee| utils::u256_to_bytes(fee).to_vec()), + max_priority_fee_per_gas: full_grant + .shared + .max_priority_fee_per_gas + .map(|fee| utils::u256_to_bytes(fee).to_vec()), + rate_limit_count: full_grant + .shared + .rate_limit + .as_ref() + .map(|rl| rl.count as i32), + rate_limit_window_secs: full_grant + .shared + .rate_limit + .as_ref() + .map(|rl| rl.window.num_seconds() as i32), + revoked_at: None, + }) + .returning(evm_basic_grant::all_columns) + .get_result(&mut *conn) + .await?; + + P::create_grant(&basic_grant, &full_grant.specific, &mut *conn).await?; + + integrity::sign_entity(&mut *conn, &vault, &full_grant, basic_grant.id) + .await + .map_err(|_| diesel::result::Error::RollbackTransaction)?; + + QueryResult::Ok(basic_grant.id) + }) + .await?; + + Ok(id) + } + + pub async fn revoke_grant( + &self, + basic_grant_id: i32, + ) -> Result<(), DatabaseError> { + let mut conn = self.db.get().await.map_err(DatabaseError::from)?; + let vault = self.vault.clone(); + + conn.transaction(async move |conn| { + use crate::db::schema::{ + evm_basic_grant, evm_ether_transfer_grant, evm_ether_transfer_grant_target, + evm_ether_transfer_limit, evm_token_transfer_grant, + evm_token_transfer_volume_limit, + }; + + update(evm_basic_grant::table) + .filter(evm_basic_grant::id.eq(basic_grant_id)) + .set(evm_basic_grant::revoked_at.eq(SqliteTimestamp(Utc::now()))) + .execute(&mut *conn) + .await?; + + let basic_grant: EvmBasicGrant = evm_basic_grant::table + .filter(evm_basic_grant::id.eq(basic_grant_id)) + .select(EvmBasicGrant::as_select()) + .first(&mut *conn) + .await?; + + let shared = SharedGrantSettings::try_from_model(basic_grant)?; + + if let Some(ether_grant) = evm_ether_transfer_grant::table + .filter(evm_ether_transfer_grant::basic_grant_id.eq(basic_grant_id)) + .select(EvmEtherTransferGrant::as_select()) + .first(&mut *conn) + .await + .optional()? + { + let target_rows: Vec = + evm_ether_transfer_grant_target::table + .filter(evm_ether_transfer_grant_target::grant_id.eq(ether_grant.id)) + .select(EvmEtherTransferGrantTarget::as_select()) + .load(&mut *conn) + .await?; + let targets: Vec
= target_rows + .into_iter() + .filter_map(|target| { + let arr: [u8; 20] = target.address.try_into().ok()?; + Some(Address::from(arr)) + }) + .collect(); + + let limit: EvmEtherTransferLimit = evm_ether_transfer_limit::table + .filter(evm_ether_transfer_limit::id.eq(ether_grant.limit_id)) + .select(EvmEtherTransferLimit::as_select()) + .first(&mut *conn) + .await?; + + let settings = CombinedSettings { + shared: shared.clone(), + specific: policies::ether_transfer::Settings { + target: targets, + limit: VolumeRateLimit { + max_volume: utils::try_bytes_to_u256(&limit.max_volume).map_err( + |err| { + diesel::result::Error::DeserializationError(Box::new(err)) + }, + )?, + window: chrono::Duration::seconds(limit.window_secs.into()), + }, + }, + }; + + integrity::sign_entity(&mut *conn, &vault, &settings, basic_grant_id) + .await + .map_err(|_| diesel::result::Error::RollbackTransaction)?; + + return QueryResult::Ok(()); + } + + if let Some(token_grant) = evm_token_transfer_grant::table + .filter(evm_token_transfer_grant::basic_grant_id.eq(basic_grant_id)) + .select(EvmTokenTransferGrant::as_select()) + .first(&mut *conn) + .await + .optional()? + { + let volume_limit_rows: Vec = + evm_token_transfer_volume_limit::table + .filter(evm_token_transfer_volume_limit::grant_id.eq(token_grant.id)) + .select(EvmTokenTransferVolumeLimit::as_select()) + .load(&mut *conn) + .await?; + let volume_limits: Vec = volume_limit_rows + .into_iter() + .map(|row| { + Ok(VolumeRateLimit { + max_volume: utils::try_bytes_to_u256(&row.max_volume).map_err( + |err| { + diesel::result::Error::DeserializationError(Box::new(err)) + }, + )?, + window: chrono::Duration::seconds(row.window_secs.into()), + }) + }) + .collect::>>()?; + + let target: Option
= match token_grant.receiver { + None => None, + Some(bytes) => { + let arr: [u8; 20] = bytes.try_into().map_err(|_| { + diesel::result::Error::DeserializationError( + "Invalid receiver address length".into(), + ) + })?; + Some(Address::from(arr)) + } + }; + + let token_contract: [u8; 20] = + token_grant.token_contract.clone().try_into().map_err(|_| { + diesel::result::Error::DeserializationError( + "Invalid token contract address length".into(), + ) + })?; + + let settings = CombinedSettings { + shared, + specific: policies::token_transfers::Settings { + token_contract: Address::from(token_contract), + target, + volume_limits, + }, + }; + + integrity::sign_entity(&mut *conn, &vault, &settings, basic_grant_id) + .await + .map_err(|_| diesel::result::Error::RollbackTransaction)?; + + return QueryResult::Ok(()); + } + + Err(diesel::result::Error::NotFound) + }) + .await + .map_err(DatabaseError::from) + } + + async fn list_one_kind( + &self, + conn: &mut impl AsyncConnection, + ) -> Result>, ListError> + where + Y: From, + { + let all_grants = Kind::find_all_grants(conn) + .await + .map_err(DatabaseError::from)?; + + // Verify integrity of all grants before returning any results + for grant in &all_grants { + integrity::verify_entity(conn, &self.vault, &grant.settings, grant.id).await?; + } + + Ok(all_grants.into_iter().map(|g| Grant { + id: g.id, + common_settings_id: g.common_settings_id, + settings: g.settings.generalize(), + })) + } + + pub async fn list_all_grants(&self) -> Result>, ListError> { + let mut conn = self.db.get().await.map_err(DatabaseError::from)?; + + let mut grants: Vec> = Vec::new(); + + grants.extend(self.list_one_kind::(&mut conn).await?); + grants.extend(self.list_one_kind::(&mut conn).await?); + + Ok(grants) + } + + pub async fn evaluate_transaction( + &self, + target: EvmWalletAccess, + transaction: TxEip1559, + run_kind: RunKind, + ) -> Result { + let TxKind::Call(to) = transaction.to else { + return Err(VetError::ContractCreationNotSupported); + }; + let context = EvalContext { + target, + chain: transaction.chain_id, + to, + value: transaction.value, + calldata: transaction.input.clone(), + max_fee_per_gas: transaction.max_fee_per_gas, + max_priority_fee_per_gas: transaction.max_priority_fee_per_gas, + }; + + if let Some(meaning) = EtherTransfer::analyze(&context) { + return match self + .vet_transaction::(context, &meaning, run_kind) + .await + { + Ok(()) => Ok(meaning.into()), + Err(e) => Err(VetError::Evaluated(meaning.into(), e)), + }; + } + if let Some(meaning) = TokenTransfer::analyze(&context) { + return match self + .vet_transaction::(context, &meaning, run_kind) + .await + { + Ok(()) => Ok(meaning.into()), + Err(e) => Err(VetError::Evaluated(meaning.into(), e)), + }; + } + + Err(VetError::UnsupportedTransactionType) + } +} + +#[cfg(test)] +mod tests { + use alloy::primitives::{Address, Bytes, U256, address}; + use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; + use chrono::{Duration, Utc}; + use diesel::{SelectableHelper, insert_into}; + use diesel_async::RunQueryDsl; + use kameo::{actor::ActorRef, prelude::Spawn}; + use rstest::rstest; + + use crate::actors::{GlobalActors, vault::{Bootstrap, Vault}}; + use crate::crypto::integrity; + use crate::db::{ + self, DatabaseConnection, + models::{ + EvmBasicGrant, EvmWalletAccess, NewEvmBasicGrant, NewEvmTransactionLog, SqliteTimestamp, + }, + schema::{evm_basic_grant, evm_transaction_log}, + }; + use crate::evm::policies::ether_transfer::EtherTransfer; + use crate::evm::policies::{ + CombinedSettings, EvalContext, EvalViolation, Policy, SharedGrantSettings, + TransactionRateLimit, VolumeRateLimit, + }; + + use super::check_shared_constraints; + + const WALLET_ACCESS_ID: i32 = 1; + const CHAIN_ID: u64 = 1; + const RECIPIENT: Address = address!("1111111111111111111111111111111111111111"); + + fn context() -> EvalContext { + EvalContext { + target: EvmWalletAccess { + id: WALLET_ACCESS_ID, + wallet_id: 10, + client_id: 20, + created_at: SqliteTimestamp(Utc::now()), + }, + chain: CHAIN_ID, + to: RECIPIENT, + value: U256::ZERO, + calldata: Bytes::new(), + max_fee_per_gas: 100, + max_priority_fee_per_gas: 10, + } + } + + fn shared_settings() -> SharedGrantSettings { + SharedGrantSettings { + wallet_access_id: WALLET_ACCESS_ID, + chain: CHAIN_ID, + valid_from: None, + valid_until: None, + revoked_at: None, + max_gas_fee_per_gas: None, + max_priority_fee_per_gas: None, + rate_limit: None, + } + } + + async fn insert_basic_grant( + conn: &mut DatabaseConnection, + shared: &SharedGrantSettings, + ) -> EvmBasicGrant { + #[expect( + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::as_conversions, + reason = "fixme! #86" + )] + insert_into(evm_basic_grant::table) + .values(NewEvmBasicGrant { + wallet_access_id: shared.wallet_access_id, + chain_id: shared.chain.into(), + valid_from: shared.valid_from.map(SqliteTimestamp), + valid_until: shared.valid_until.map(SqliteTimestamp), + max_gas_fee_per_gas: shared + .max_gas_fee_per_gas + .map(|fee| super::utils::u256_to_bytes(fee).to_vec()), + max_priority_fee_per_gas: shared + .max_priority_fee_per_gas + .map(|fee| super::utils::u256_to_bytes(fee).to_vec()), + rate_limit_count: shared.rate_limit.as_ref().map(|limit| limit.count as i32), + rate_limit_window_secs: shared + .rate_limit + .as_ref() + .map(|limit| limit.window.num_seconds() as i32), + revoked_at: None, + }) + .returning(EvmBasicGrant::as_select()) + .get_result(conn) + .await + .unwrap() + } + + #[rstest] + #[case::matching_chain(CHAIN_ID, false)] + #[case::mismatching_chain(CHAIN_ID + 1, true)] + #[tokio::test] + async fn check_shared_constraints_enforces_chain_id( + #[case] context_chain: u64, + #[case] expect_mismatch: bool, + ) { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let context = EvalContext { + chain: context_chain, + ..context() + }; + + let violations = check_shared_constraints(&context, &shared_settings(), 999, &mut *conn) + .await + .unwrap(); + + assert_eq!( + violations + .iter() + .any(|violation| matches!(violation, EvalViolation::MismatchingChainId { .. })), + expect_mismatch + ); + + if expect_mismatch { + assert_eq!(violations.len(), 1); + } else { + assert!(violations.is_empty()); + } + } + + #[rstest] + #[case::valid_from_in_bounds(Some(Utc::now() - Duration::hours(1)), None, false)] + #[case::valid_from_out_of_bounds(Some(Utc::now() + Duration::hours(1)), None, true)] + #[case::valid_until_in_bounds(None, Some(Utc::now() + Duration::hours(1)), false)] + #[case::valid_until_out_of_bounds(None, Some(Utc::now() - Duration::hours(1)), true)] + #[tokio::test] + async fn check_shared_constraints_enforces_validity_window( + #[case] valid_from: Option>, + #[case] valid_until: Option>, + #[case] expect_invalid_time: bool, + ) { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let shared = SharedGrantSettings { + valid_from, + valid_until, + ..shared_settings() + }; + + let violations = check_shared_constraints(&context(), &shared, 999, &mut *conn) + .await + .unwrap(); + + assert_eq!( + violations + .iter() + .any(|violation| matches!(violation, EvalViolation::InvalidTime)), + expect_invalid_time + ); + + if expect_invalid_time { + assert_eq!(violations.len(), 1); + } else { + assert!(violations.is_empty()); + } + } + + #[rstest] + #[case::max_fee_within_limit(Some(U256::from(100u64)), None, 100, 10, false)] + #[case::max_fee_exceeded(Some(U256::from(99u64)), None, 100, 10, true)] + #[case::priority_fee_within_limit(None, Some(U256::from(10u64)), 100, 10, false)] + #[case::priority_fee_exceeded(None, Some(U256::from(9u64)), 100, 10, true)] + #[tokio::test] + async fn check_shared_constraints_enforces_gas_fee_caps( + #[case] max_gas_fee_per_gas: Option, + #[case] max_priority_fee_per_gas: Option, + #[case] actual_max_fee_per_gas: u128, + #[case] actual_max_priority_fee_per_gas: u128, + #[case] expect_gas_limit_violation: bool, + ) { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let context = EvalContext { + max_fee_per_gas: actual_max_fee_per_gas, + max_priority_fee_per_gas: actual_max_priority_fee_per_gas, + ..context() + }; + + let shared = SharedGrantSettings { + max_gas_fee_per_gas, + max_priority_fee_per_gas, + ..shared_settings() + }; + let violations = check_shared_constraints(&context, &shared, 999, &mut *conn) + .await + .unwrap(); + + assert_eq!( + violations + .iter() + .any(|violation| matches!(violation, EvalViolation::GasLimitExceeded { .. })), + expect_gas_limit_violation + ); + + if expect_gas_limit_violation { + assert_eq!(violations.len(), 1); + } else { + assert!(violations.is_empty()); + } + } + + #[rstest] + #[case::under_rate_limit(2, false)] + #[case::at_rate_limit(1, true)] + #[tokio::test] + async fn check_shared_constraints_enforces_rate_limit( + #[case] rate_limit_count: u32, + #[case] expect_rate_limit_violation: bool, + ) { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let shared = SharedGrantSettings { + rate_limit: Some(TransactionRateLimit { + count: rate_limit_count, + window: Duration::hours(1), + }), + ..shared_settings() + }; + + let basic_grant = insert_basic_grant(&mut conn, &shared).await; + + insert_into(evm_transaction_log::table) + .values(NewEvmTransactionLog { + grant_id: basic_grant.id, + wallet_access_id: WALLET_ACCESS_ID, + chain_id: CHAIN_ID.into(), + eth_value: super::utils::u256_to_bytes(U256::ZERO).to_vec(), + signed_at: SqliteTimestamp(Utc::now()), + }) + .execute(&mut *conn) + .await + .unwrap(); + + let violations = check_shared_constraints(&context(), &shared, basic_grant.id, &mut *conn) + .await + .unwrap(); + + assert_eq!( + violations + .iter() + .any(|violation| matches!(violation, EvalViolation::RateLimitExceeded)), + expect_rate_limit_violation + ); + + if expect_rate_limit_violation { + assert_eq!(violations.len(), 1); + } else { + assert!(violations.is_empty()); + } + } + + async fn bootstrapped_vault(db: &db::DatabasePool) -> ActorRef { + let actor = Vault::spawn( + Vault::new(db.clone(), GlobalActors::spawn_message_bus()) + .await + .unwrap(), + ); + actor + .ask(Bootstrap { + seal_key_raw: SafeCell::new(b"integrity-test-seal-key".to_vec()), + }) + .await + .unwrap(); + actor + } + + #[tokio::test] + async fn revoke_grant_preserves_revoked_integrity() { + use crate::db::schema::evm_basic_grant; + use diesel::ExpressionMethods as _; + + let db = db::create_test_pool().await; + let vault = bootstrapped_vault(&db).await; + let engine = super::Engine::new(db.clone(), vault.clone()); + + let full_grant = CombinedSettings { + shared: SharedGrantSettings { + wallet_access_id: WALLET_ACCESS_ID, + chain: CHAIN_ID, + valid_from: None, + valid_until: None, + revoked_at: None, + max_gas_fee_per_gas: None, + max_priority_fee_per_gas: None, + rate_limit: None, + }, + specific: super::policies::ether_transfer::Settings { + target: vec![RECIPIENT], + limit: VolumeRateLimit { + max_volume: U256::from(100u64), + window: Duration::hours(1), + }, + }, + }; + + let grant_id = engine + .create_grant::(full_grant) + .await + .unwrap(); + + engine.revoke_grant(grant_id).await.unwrap(); + + let mut conn = db.get().await.unwrap(); + diesel::update(evm_basic_grant::table) + .filter(evm_basic_grant::id.eq(grant_id)) + .set(evm_basic_grant::revoked_at.eq::>(None)) + .execute(&mut conn) + .await + .unwrap(); + + let wallet_access = EvmWalletAccess { + id: WALLET_ACCESS_ID, + wallet_id: 10, + client_id: 20, + created_at: SqliteTimestamp(Utc::now()), + }; + let context = EvalContext { + target: wallet_access, + chain: CHAIN_ID, + to: RECIPIENT, + value: U256::ONE, + calldata: Bytes::new(), + max_fee_per_gas: 1, + max_priority_fee_per_gas: 1, + }; + + let grant = EtherTransfer::try_find_grant( + &context, &mut conn, + ) + .await + .unwrap() + .unwrap(); + + let result = + integrity::verify_entity(&mut conn, &vault, &grant.settings, grant.id).await; + + assert!(matches!( + result, + Err(integrity::Error::MacMismatch { .. }) + )); + } + + #[test] + fn shared_settings_hash_changes_when_revoked_at_changes() { + use arbiter_crypto::hashing::Hashable; + use sha2::Digest; + + let active = shared_settings(); + let revoked = SharedGrantSettings { + revoked_at: Some(Utc::now()), + ..shared_settings() + }; + + let mut active_hash = sha2::Sha256::new(); + active.hash(&mut active_hash); + + let mut revoked_hash = sha2::Sha256::new(); + revoked.hash(&mut revoked_hash); + + assert_ne!(active_hash.finalize(), revoked_hash.finalize()); + } +} diff --git a/server/crates/arbiter-server/src/evm/policies.rs b/server/crates/arbiter-server/src/evm/policies.rs index 9433e29..db4bea3 100644 --- a/server/crates/arbiter-server/src/evm/policies.rs +++ b/server/crates/arbiter-server/src/evm/policies.rs @@ -1,222 +1,222 @@ -use crate::{ - crypto::integrity::v1::Integrable, - db::models::{EvmBasicGrant, EvmWalletAccess}, - evm::utils, -}; - -use alloy::primitives::{Address, Bytes, ChainId, U256}; -use chrono::{DateTime, Duration, Utc}; -use diesel::{ - ExpressionMethods as _, QueryDsl, SelectableHelper, result::QueryResult, sqlite::Sqlite, -}; -use diesel_async::{AsyncConnection, RunQueryDsl}; -use std::fmt::Display; -use thiserror::Error; - -pub mod ether_transfer; -pub mod token_transfers; - -#[derive(Debug, Clone)] -pub struct EvalContext { - // Which wallet is this transaction for and who requested it - pub target: EvmWalletAccess, - - // The transaction data - pub chain: ChainId, - pub to: Address, - pub value: U256, - pub calldata: Bytes, - - // Gas pricing (EIP-1559) - pub max_fee_per_gas: u128, - pub max_priority_fee_per_gas: u128, -} - -#[derive(Debug, Error)] -pub enum EvalViolation { - #[error("This grant doesn't allow transactions to the target address {target}")] - InvalidTarget { target: Address }, - - #[error("Gas limit exceeded for this grant")] - GasLimitExceeded { - max_gas_fee_per_gas: Option, - max_priority_fee_per_gas: Option, - }, - - #[error("Rate limit exceeded for this grant")] - RateLimitExceeded, - - #[error("Transaction exceeds volumetric limits of the grant")] - VolumetricLimitExceeded, - - #[error("Transaction is outside of the grant's validity period")] - InvalidTime, - - #[error("Transaction type is not allowed by this grant")] - InvalidTransactionType, - - #[error("Mismatching chain ID")] - MismatchingChainId { expected: ChainId, actual: ChainId }, -} - -pub type DatabaseID = i32; - -#[derive(Debug)] -pub struct Grant { - pub id: DatabaseID, - pub common_settings_id: DatabaseID, // ID of the basic grant for shared-logic checks like rate limits and validity periods - pub settings: CombinedSettings, -} - -pub trait Policy: Sized { - type Settings: Send + Sync + 'static + Into + Integrable; - type Meaning: Display + std::fmt::Debug + Send + Sync + 'static + Into; - - fn analyze(context: &EvalContext) -> Option; - - // Evaluate whether a transaction with the given meaning complies with the provided grant, and return any violations if not - // Empty vector means transaction is compliant with the grant - fn evaluate( - context: &EvalContext, - meaning: &Self::Meaning, - grant: &Grant, - db: &mut impl AsyncConnection, - ) -> impl Future>> + Send; - - // Create a new grant in the database based on the provided grant details, and return its ID - fn create_grant( - basic: &EvmBasicGrant, - grant: &Self::Settings, - conn: &mut impl AsyncConnection, - ) -> impl Future> + Send; - - // Try to find an existing grant that matches the transaction context, and return its details if found - // Additionally, return ID of basic grant for shared-logic checks like rate limits and validity periods - fn try_find_grant( - context: &EvalContext, - conn: &mut impl AsyncConnection, - ) -> impl Future>>> + Send; - - // Return all non-revoked grants, eagerly loading policy-specific settings - fn find_all_grants( - conn: &mut impl AsyncConnection, - ) -> impl Future>>> + Send; - - // Records, updates or deletes rate limits - // In other words, records grant-specific things after transaction is executed - fn record_transaction( - context: &EvalContext, - meaning: &Self::Meaning, - log_id: i32, - grant: &Grant, - conn: &mut impl AsyncConnection, - ) -> impl Future> + Send; -} - -pub enum ReceiverTarget { - Specific(Vec
), // only allow transfers to these addresses - Any, // allow transfers to any address -} - -// Classification of what transaction does -#[derive(Debug)] -pub enum SpecificMeaning { - EtherTransfer(ether_transfer::Meaning), - TokenTransfer(token_transfers::Meaning), -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, arbiter_macros::Hashable)] -pub struct TransactionRateLimit { - pub count: u32, - pub window: Duration, -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, arbiter_macros::Hashable)] -pub struct VolumeRateLimit { - pub max_volume: U256, - pub window: Duration, -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, arbiter_macros::Hashable)] -pub struct SharedGrantSettings { - pub wallet_access_id: i32, - pub chain: ChainId, - - pub valid_from: Option>, - pub valid_until: Option>, - pub revoked_at: Option>, - - pub max_gas_fee_per_gas: Option, - pub max_priority_fee_per_gas: Option, - - pub rate_limit: Option, -} - -impl SharedGrantSettings { - pub(crate) fn try_from_model(model: EvmBasicGrant) -> QueryResult { - Ok(Self { - wallet_access_id: model.wallet_access_id, - chain: model.chain_id.into(), - valid_from: model.valid_from.map(Into::into), - valid_until: model.valid_until.map(Into::into), - revoked_at: model.revoked_at.map(Into::into), - max_gas_fee_per_gas: model - .max_gas_fee_per_gas - .map(|b| utils::try_bytes_to_u256(&b)) - .transpose()?, - max_priority_fee_per_gas: model - .max_priority_fee_per_gas - .map(|b| utils::try_bytes_to_u256(&b)) - .transpose()?, - #[expect(clippy::cast_sign_loss, clippy::as_conversions, reason = "fixme! #86")] - rate_limit: match (model.rate_limit_count, model.rate_limit_window_secs) { - (Some(count), Some(window_secs)) => Some(TransactionRateLimit { - count: count as u32, - window: Duration::seconds(window_secs.into()), - }), - _ => None, - }, - }) - } - - pub async fn query_by_id( - conn: &mut impl AsyncConnection, - id: i32, - ) -> QueryResult { - use crate::db::schema::evm_basic_grant; - - let basic_grant: EvmBasicGrant = evm_basic_grant::table - .select(EvmBasicGrant::as_select()) - .filter(evm_basic_grant::id.eq(id)) - .first::(conn) - .await?; - - Self::try_from_model(basic_grant) - } -} - -#[derive(Debug, Clone)] -pub enum SpecificGrant { - EtherTransfer(ether_transfer::Settings), - TokenTransfer(token_transfers::Settings), -} - -#[derive(Debug, arbiter_macros::Hashable)] -pub struct CombinedSettings { - pub shared: SharedGrantSettings, - pub specific: PolicyGrant, -} - -impl

CombinedSettings

{ - pub fn generalize>(self) -> CombinedSettings { - CombinedSettings { - shared: self.shared, - specific: self.specific.into(), - } - } -} - -impl Integrable for CombinedSettings

{ - const KIND: &'static str = P::KIND; - const VERSION: i32 = P::VERSION; -} +use crate::{ + crypto::integrity::v1::Integrable, + db::models::{EvmBasicGrant, EvmWalletAccess}, + evm::utils, +}; + +use alloy::primitives::{Address, Bytes, ChainId, U256}; +use chrono::{DateTime, Duration, Utc}; +use diesel::{ + ExpressionMethods as _, QueryDsl, SelectableHelper, result::QueryResult, sqlite::Sqlite, +}; +use diesel_async::{AsyncConnection, RunQueryDsl}; +use std::fmt::Display; +use thiserror::Error; + +pub mod ether_transfer; +pub mod token_transfers; + +#[derive(Debug, Clone)] +pub struct EvalContext { + // Which wallet is this transaction for and who requested it + pub target: EvmWalletAccess, + + // The transaction data + pub chain: ChainId, + pub to: Address, + pub value: U256, + pub calldata: Bytes, + + // Gas pricing (EIP-1559) + pub max_fee_per_gas: u128, + pub max_priority_fee_per_gas: u128, +} + +#[derive(Debug, Error)] +pub enum EvalViolation { + #[error("This grant doesn't allow transactions to the target address {target}")] + InvalidTarget { target: Address }, + + #[error("Gas limit exceeded for this grant")] + GasLimitExceeded { + max_gas_fee_per_gas: Option, + max_priority_fee_per_gas: Option, + }, + + #[error("Rate limit exceeded for this grant")] + RateLimitExceeded, + + #[error("Transaction exceeds volumetric limits of the grant")] + VolumetricLimitExceeded, + + #[error("Transaction is outside of the grant's validity period")] + InvalidTime, + + #[error("Transaction type is not allowed by this grant")] + InvalidTransactionType, + + #[error("Mismatching chain ID")] + MismatchingChainId { expected: ChainId, actual: ChainId }, +} + +pub type DatabaseID = i32; + +#[derive(Debug)] +pub struct Grant { + pub id: DatabaseID, + pub common_settings_id: DatabaseID, // ID of the basic grant for shared-logic checks like rate limits and validity periods + pub settings: CombinedSettings, +} + +pub trait Policy: Sized { + type Settings: Send + Sync + 'static + Into + Integrable; + type Meaning: Display + std::fmt::Debug + Send + Sync + 'static + Into; + + fn analyze(context: &EvalContext) -> Option; + + // Evaluate whether a transaction with the given meaning complies with the provided grant, and return any violations if not + // Empty vector means transaction is compliant with the grant + fn evaluate( + context: &EvalContext, + meaning: &Self::Meaning, + grant: &Grant, + db: &mut impl AsyncConnection, + ) -> impl Future>> + Send; + + // Create a new grant in the database based on the provided grant details, and return its ID + fn create_grant( + basic: &EvmBasicGrant, + grant: &Self::Settings, + conn: &mut impl AsyncConnection, + ) -> impl Future> + Send; + + // Try to find an existing grant that matches the transaction context, and return its details if found + // Additionally, return ID of basic grant for shared-logic checks like rate limits and validity periods + fn try_find_grant( + context: &EvalContext, + conn: &mut impl AsyncConnection, + ) -> impl Future>>> + Send; + + // Return all non-revoked grants, eagerly loading policy-specific settings + fn find_all_grants( + conn: &mut impl AsyncConnection, + ) -> impl Future>>> + Send; + + // Records, updates or deletes rate limits + // In other words, records grant-specific things after transaction is executed + fn record_transaction( + context: &EvalContext, + meaning: &Self::Meaning, + log_id: i32, + grant: &Grant, + conn: &mut impl AsyncConnection, + ) -> impl Future> + Send; +} + +pub enum ReceiverTarget { + Specific(Vec

), // only allow transfers to these addresses + Any, // allow transfers to any address +} + +// Classification of what transaction does +#[derive(Debug)] +pub enum SpecificMeaning { + EtherTransfer(ether_transfer::Meaning), + TokenTransfer(token_transfers::Meaning), +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, arbiter_macros::Hashable)] +pub struct TransactionRateLimit { + pub count: u32, + pub window: Duration, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, arbiter_macros::Hashable)] +pub struct VolumeRateLimit { + pub max_volume: U256, + pub window: Duration, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, arbiter_macros::Hashable)] +pub struct SharedGrantSettings { + pub wallet_access_id: i32, + pub chain: ChainId, + + pub valid_from: Option>, + pub valid_until: Option>, + pub revoked_at: Option>, + + pub max_gas_fee_per_gas: Option, + pub max_priority_fee_per_gas: Option, + + pub rate_limit: Option, +} + +impl SharedGrantSettings { + pub(crate) fn try_from_model(model: EvmBasicGrant) -> QueryResult { + Ok(Self { + wallet_access_id: model.wallet_access_id, + chain: model.chain_id.into(), + valid_from: model.valid_from.map(Into::into), + valid_until: model.valid_until.map(Into::into), + revoked_at: model.revoked_at.map(Into::into), + max_gas_fee_per_gas: model + .max_gas_fee_per_gas + .map(|b| utils::try_bytes_to_u256(&b)) + .transpose()?, + max_priority_fee_per_gas: model + .max_priority_fee_per_gas + .map(|b| utils::try_bytes_to_u256(&b)) + .transpose()?, + #[expect(clippy::cast_sign_loss, clippy::as_conversions, reason = "fixme! #86")] + rate_limit: match (model.rate_limit_count, model.rate_limit_window_secs) { + (Some(count), Some(window_secs)) => Some(TransactionRateLimit { + count: count as u32, + window: Duration::seconds(window_secs.into()), + }), + _ => None, + }, + }) + } + + pub async fn query_by_id( + conn: &mut impl AsyncConnection, + id: i32, + ) -> QueryResult { + use crate::db::schema::evm_basic_grant; + + let basic_grant: EvmBasicGrant = evm_basic_grant::table + .select(EvmBasicGrant::as_select()) + .filter(evm_basic_grant::id.eq(id)) + .first::(conn) + .await?; + + Self::try_from_model(basic_grant) + } +} + +#[derive(Debug, Clone)] +pub enum SpecificGrant { + EtherTransfer(ether_transfer::Settings), + TokenTransfer(token_transfers::Settings), +} + +#[derive(Debug, arbiter_macros::Hashable)] +pub struct CombinedSettings { + pub shared: SharedGrantSettings, + pub specific: PolicyGrant, +} + +impl

CombinedSettings

{ + pub fn generalize>(self) -> CombinedSettings { + CombinedSettings { + shared: self.shared, + specific: self.specific.into(), + } + } +} + +impl Integrable for CombinedSettings

{ + const KIND: &'static str = P::KIND; + const VERSION: i32 = P::VERSION; +} diff --git a/server/crates/arbiter-server/src/evm/policies/ether_transfer/mod.rs b/server/crates/arbiter-server/src/evm/policies/ether_transfer/mod.rs index bff34a0..db46207 100644 --- a/server/crates/arbiter-server/src/evm/policies/ether_transfer/mod.rs +++ b/server/crates/arbiter-server/src/evm/policies/ether_transfer/mod.rs @@ -1,359 +1,359 @@ -use super::{DatabaseID, EvalContext, EvalViolation}; -use crate::{ - crypto::integrity::v1::Integrable, - db::models::{ - EvmBasicGrant, EvmEtherTransferGrant, EvmEtherTransferGrantTarget, EvmEtherTransferLimit, - NewEvmEtherTransferLimit, SqliteTimestamp, - }, - db::schema::{evm_basic_grant, evm_ether_transfer_limit, evm_transaction_log}, - db::{ - models::{NewEvmEtherTransferGrant, NewEvmEtherTransferGrantTarget}, - schema::{evm_ether_transfer_grant, evm_ether_transfer_grant_target}, - }, - evm::policies::{ - CombinedSettings, Grant, SharedGrantSettings, SpecificGrant, SpecificMeaning, - VolumeRateLimit, - }, - evm::{policies::Policy, utils}, -}; - -use alloy::primitives::{Address, U256}; -use chrono::{DateTime, Duration, Utc}; -use diesel::{ - dsl::{auto_type, insert_into}, - prelude::*, - sqlite::Sqlite, -}; -use diesel_async::{AsyncConnection, RunQueryDsl}; -use std::{collections::HashMap, fmt::Display}; - -#[auto_type] -fn grant_join() -> _ { - evm_ether_transfer_grant::table.inner_join( - evm_basic_grant::table.on(evm_ether_transfer_grant::basic_grant_id.eq(evm_basic_grant::id)), - ) -} - -// Plain ether transfer -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Meaning { - pub(crate) to: Address, - pub(crate) value: U256, -} -impl Display for Meaning { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Ether transfer of {} to {}", self.value, self.to) - } -} -impl From for SpecificMeaning { - fn from(val: Meaning) -> Self { - Self::EtherTransfer(val) - } -} - -// A grant for ether transfers, which can be scoped to specific target addresses and volume limits -#[derive(Debug, Clone, arbiter_macros::Hashable)] -pub struct Settings { - pub target: Vec

, - pub limit: VolumeRateLimit, -} -impl Integrable for Settings { - const KIND: &'static str = "EtherTransfer"; -} - -impl From for SpecificGrant { - fn from(val: Settings) -> Self { - Self::EtherTransfer(val) - } -} - -async fn query_relevant_past_transaction( - grant_id: i32, - longest_window: Duration, - db: &mut impl AsyncConnection, -) -> QueryResult)>> { - let past_transactions: Vec<(Vec, SqliteTimestamp)> = evm_transaction_log::table - .filter(evm_transaction_log::grant_id.eq(grant_id)) - .filter(evm_transaction_log::signed_at.ge(SqliteTimestamp(Utc::now() - longest_window))) - .select(( - evm_transaction_log::eth_value, - evm_transaction_log::signed_at, - )) - .load(db) - .await?; - let past_transaction: Vec<(U256, DateTime)> = past_transactions - .into_iter() - .filter_map(|(value_bytes, timestamp)| { - let value = utils::bytes_to_u256(&value_bytes)?; - Some((value, timestamp.0)) - }) - .collect(); - Ok(past_transaction) -} - -async fn check_rate_limits( - grant: &Grant, - current_transfer_value: U256, - db: &mut impl AsyncConnection, -) -> QueryResult> { - let mut violations = Vec::new(); - let window = grant.settings.specific.limit.window; - - let past_transaction = query_relevant_past_transaction(grant.id, window, db).await?; - - let window_start = Utc::now() - grant.settings.specific.limit.window; - let prospective_cumulative_volume: U256 = past_transaction - .iter() - .filter(|(_, timestamp)| timestamp >= &window_start) - .fold(current_transfer_value, |acc, (value, _)| acc + *value); - - if prospective_cumulative_volume > grant.settings.specific.limit.max_volume { - violations.push(EvalViolation::VolumetricLimitExceeded); - } - - Ok(violations) -} - -pub struct EtherTransfer; -impl Policy for EtherTransfer { - type Settings = Settings; - - type Meaning = Meaning; - - fn analyze(context: &EvalContext) -> Option { - if !context.calldata.is_empty() { - return None; - } - - Some(Meaning { - to: context.to, - value: context.value, - }) - } - - async fn evaluate( - _: &EvalContext, - meaning: &Self::Meaning, - grant: &Grant, - db: &mut impl AsyncConnection, - ) -> QueryResult> { - let mut violations = Vec::new(); - - // Check if the target address is within the grant's allowed targets - if !grant.settings.specific.target.contains(&meaning.to) { - violations.push(EvalViolation::InvalidTarget { target: meaning.to }); - } - - let rate_violations = check_rate_limits(grant, meaning.value, db).await?; - violations.extend(rate_violations); - - Ok(violations) - } - - async fn create_grant( - basic: &EvmBasicGrant, - grant: &Self::Settings, - conn: &mut impl AsyncConnection, - ) -> QueryResult { - #[expect( - clippy::cast_possible_truncation, - clippy::as_conversions, - reason = "fixme! #86" - )] - let limit_id: i32 = insert_into(evm_ether_transfer_limit::table) - .values(NewEvmEtherTransferLimit { - window_secs: grant.limit.window.num_seconds() as i32, - max_volume: utils::u256_to_bytes(grant.limit.max_volume).to_vec(), - }) - .returning(evm_ether_transfer_limit::id) - .get_result(conn) - .await?; - - let grant_id: i32 = insert_into(evm_ether_transfer_grant::table) - .values(&NewEvmEtherTransferGrant { - basic_grant_id: basic.id, - limit_id, - }) - .returning(evm_ether_transfer_grant::id) - .get_result(conn) - .await?; - - for target in &grant.target { - insert_into(evm_ether_transfer_grant_target::table) - .values(NewEvmEtherTransferGrantTarget { - grant_id, - address: target.to_vec(), - }) - .execute(conn) - .await?; - } - - Ok(grant_id) - } - - async fn try_find_grant( - context: &EvalContext, - conn: &mut impl AsyncConnection, - ) -> QueryResult>> { - let target_bytes = context.to.to_vec(); - - // Find a grant where: - // 1. The basic grant's wallet_id and client_id match the context - // 2. Any of the grant's targets match the context's `to` address - let grant: Option<(EvmBasicGrant, EvmEtherTransferGrant)> = evm_ether_transfer_grant::table - .inner_join(evm_basic_grant::table) - .inner_join(evm_ether_transfer_grant_target::table) - .filter( - evm_basic_grant::wallet_access_id - .eq(context.target.id) - .and(evm_basic_grant::revoked_at.is_null()) - .and(evm_ether_transfer_grant_target::address.eq(&target_bytes)), - ) - .select(( - EvmBasicGrant::as_select(), - EvmEtherTransferGrant::as_select(), - )) - .first(conn) - .await - .optional()?; - - let Some((basic_grant, grant)) = grant else { - return Ok(None); - }; - - let target_bytes: Vec = evm_ether_transfer_grant_target::table - .select(EvmEtherTransferGrantTarget::as_select()) - .filter(evm_ether_transfer_grant_target::grant_id.eq(grant.id)) - .load(conn) - .await?; - - let limit: EvmEtherTransferLimit = evm_ether_transfer_limit::table - .filter(evm_ether_transfer_limit::id.eq(grant.limit_id)) - .select(EvmEtherTransferLimit::as_select()) - .first::(conn) - .await?; - - // Convert bytes back to Address - let targets: Vec
= target_bytes - .into_iter() - .filter_map(|target| { - // TODO: Handle invalid addresses more gracefully - let arr: [u8; 20] = target.address.try_into().ok()?; - Some(Address::from(arr)) - }) - .collect(); - - let settings = Settings { - target: targets, - limit: VolumeRateLimit { - max_volume: utils::try_bytes_to_u256(&limit.max_volume) - .map_err(|err| diesel::result::Error::DeserializationError(Box::new(err)))?, - window: Duration::seconds(limit.window_secs.into()), - }, - }; - - Ok(Some(Grant { - id: grant.id, - common_settings_id: grant.basic_grant_id, - settings: CombinedSettings { - shared: SharedGrantSettings::try_from_model(basic_grant)?, - specific: settings, - }, - })) - } - - async fn record_transaction( - _context: &EvalContext, - _: &Self::Meaning, - _log_id: i32, - _grant: &Grant, - _conn: &mut impl AsyncConnection, - ) -> QueryResult<()> { - // Basic log is sufficient - - Ok(()) - } - - async fn find_all_grants( - conn: &mut impl AsyncConnection, - ) -> QueryResult>> { - let grants: Vec<(EvmBasicGrant, EvmEtherTransferGrant)> = grant_join() - .filter(evm_basic_grant::revoked_at.is_null()) - .select(( - EvmBasicGrant::as_select(), - EvmEtherTransferGrant::as_select(), - )) - .load(conn) - .await?; - - if grants.is_empty() { - return Ok(Vec::new()); - } - - let grant_ids: Vec = grants.iter().map(|(_, g)| g.id).collect(); - let limit_ids: Vec = grants.iter().map(|(_, g)| g.limit_id).collect(); - - let all_targets: Vec = evm_ether_transfer_grant_target::table - .filter(evm_ether_transfer_grant_target::grant_id.eq_any(&grant_ids)) - .select(EvmEtherTransferGrantTarget::as_select()) - .load(conn) - .await?; - - let all_limits: Vec = evm_ether_transfer_limit::table - .filter(evm_ether_transfer_limit::id.eq_any(&limit_ids)) - .select(EvmEtherTransferLimit::as_select()) - .load(conn) - .await?; - - let mut targets_by_grant: HashMap> = HashMap::new(); - for target in all_targets { - targets_by_grant - .entry(target.grant_id) - .or_default() - .push(target); - } - - let limits_by_id: HashMap = - all_limits.into_iter().map(|l| (l.id, l)).collect(); - - grants - .into_iter() - .map(|(basic, specific)| { - let targets: Vec
= targets_by_grant - .get(&specific.id) - .map(Vec::as_slice) - .unwrap_or_default() - .iter() - .filter_map(|t| { - let arr: [u8; 20] = t.address.clone().try_into().ok()?; - Some(Address::from(arr)) - }) - .collect(); - - let limit = limits_by_id - .get(&specific.limit_id) - .ok_or(diesel::result::Error::NotFound)?; - - Ok(Grant { - id: specific.id, - common_settings_id: specific.basic_grant_id, - settings: CombinedSettings { - shared: SharedGrantSettings::try_from_model(basic)?, - specific: Settings { - target: targets, - limit: VolumeRateLimit { - max_volume: utils::try_bytes_to_u256(&limit.max_volume).map_err( - |e| diesel::result::Error::DeserializationError(Box::new(e)), - )?, - window: Duration::seconds(limit.window_secs.into()), - }, - }, - }, - }) - }) - .collect() - } -} - -#[cfg(test)] -mod tests; +use super::{DatabaseID, EvalContext, EvalViolation}; +use crate::{ + crypto::integrity::v1::Integrable, + db::models::{ + EvmBasicGrant, EvmEtherTransferGrant, EvmEtherTransferGrantTarget, EvmEtherTransferLimit, + NewEvmEtherTransferLimit, SqliteTimestamp, + }, + db::schema::{evm_basic_grant, evm_ether_transfer_limit, evm_transaction_log}, + db::{ + models::{NewEvmEtherTransferGrant, NewEvmEtherTransferGrantTarget}, + schema::{evm_ether_transfer_grant, evm_ether_transfer_grant_target}, + }, + evm::policies::{ + CombinedSettings, Grant, SharedGrantSettings, SpecificGrant, SpecificMeaning, + VolumeRateLimit, + }, + evm::{policies::Policy, utils}, +}; + +use alloy::primitives::{Address, U256}; +use chrono::{DateTime, Duration, Utc}; +use diesel::{ + dsl::{auto_type, insert_into}, + prelude::*, + sqlite::Sqlite, +}; +use diesel_async::{AsyncConnection, RunQueryDsl}; +use std::{collections::HashMap, fmt::Display}; + +#[auto_type] +fn grant_join() -> _ { + evm_ether_transfer_grant::table.inner_join( + evm_basic_grant::table.on(evm_ether_transfer_grant::basic_grant_id.eq(evm_basic_grant::id)), + ) +} + +// Plain ether transfer +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Meaning { + pub(crate) to: Address, + pub(crate) value: U256, +} +impl Display for Meaning { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Ether transfer of {} to {}", self.value, self.to) + } +} +impl From for SpecificMeaning { + fn from(val: Meaning) -> Self { + Self::EtherTransfer(val) + } +} + +// A grant for ether transfers, which can be scoped to specific target addresses and volume limits +#[derive(Debug, Clone, arbiter_macros::Hashable)] +pub struct Settings { + pub target: Vec
, + pub limit: VolumeRateLimit, +} +impl Integrable for Settings { + const KIND: &'static str = "EtherTransfer"; +} + +impl From for SpecificGrant { + fn from(val: Settings) -> Self { + Self::EtherTransfer(val) + } +} + +async fn query_relevant_past_transaction( + grant_id: i32, + longest_window: Duration, + db: &mut impl AsyncConnection, +) -> QueryResult)>> { + let past_transactions: Vec<(Vec, SqliteTimestamp)> = evm_transaction_log::table + .filter(evm_transaction_log::grant_id.eq(grant_id)) + .filter(evm_transaction_log::signed_at.ge(SqliteTimestamp(Utc::now() - longest_window))) + .select(( + evm_transaction_log::eth_value, + evm_transaction_log::signed_at, + )) + .load(db) + .await?; + let past_transaction: Vec<(U256, DateTime)> = past_transactions + .into_iter() + .filter_map(|(value_bytes, timestamp)| { + let value = utils::bytes_to_u256(&value_bytes)?; + Some((value, timestamp.0)) + }) + .collect(); + Ok(past_transaction) +} + +async fn check_rate_limits( + grant: &Grant, + current_transfer_value: U256, + db: &mut impl AsyncConnection, +) -> QueryResult> { + let mut violations = Vec::new(); + let window = grant.settings.specific.limit.window; + + let past_transaction = query_relevant_past_transaction(grant.id, window, db).await?; + + let window_start = Utc::now() - grant.settings.specific.limit.window; + let prospective_cumulative_volume: U256 = past_transaction + .iter() + .filter(|(_, timestamp)| timestamp >= &window_start) + .fold(current_transfer_value, |acc, (value, _)| acc + *value); + + if prospective_cumulative_volume > grant.settings.specific.limit.max_volume { + violations.push(EvalViolation::VolumetricLimitExceeded); + } + + Ok(violations) +} + +pub struct EtherTransfer; +impl Policy for EtherTransfer { + type Settings = Settings; + + type Meaning = Meaning; + + fn analyze(context: &EvalContext) -> Option { + if !context.calldata.is_empty() { + return None; + } + + Some(Meaning { + to: context.to, + value: context.value, + }) + } + + async fn evaluate( + _: &EvalContext, + meaning: &Self::Meaning, + grant: &Grant, + db: &mut impl AsyncConnection, + ) -> QueryResult> { + let mut violations = Vec::new(); + + // Check if the target address is within the grant's allowed targets + if !grant.settings.specific.target.contains(&meaning.to) { + violations.push(EvalViolation::InvalidTarget { target: meaning.to }); + } + + let rate_violations = check_rate_limits(grant, meaning.value, db).await?; + violations.extend(rate_violations); + + Ok(violations) + } + + async fn create_grant( + basic: &EvmBasicGrant, + grant: &Self::Settings, + conn: &mut impl AsyncConnection, + ) -> QueryResult { + #[expect( + clippy::cast_possible_truncation, + clippy::as_conversions, + reason = "fixme! #86" + )] + let limit_id: i32 = insert_into(evm_ether_transfer_limit::table) + .values(NewEvmEtherTransferLimit { + window_secs: grant.limit.window.num_seconds() as i32, + max_volume: utils::u256_to_bytes(grant.limit.max_volume).to_vec(), + }) + .returning(evm_ether_transfer_limit::id) + .get_result(conn) + .await?; + + let grant_id: i32 = insert_into(evm_ether_transfer_grant::table) + .values(&NewEvmEtherTransferGrant { + basic_grant_id: basic.id, + limit_id, + }) + .returning(evm_ether_transfer_grant::id) + .get_result(conn) + .await?; + + for target in &grant.target { + insert_into(evm_ether_transfer_grant_target::table) + .values(NewEvmEtherTransferGrantTarget { + grant_id, + address: target.to_vec(), + }) + .execute(conn) + .await?; + } + + Ok(grant_id) + } + + async fn try_find_grant( + context: &EvalContext, + conn: &mut impl AsyncConnection, + ) -> QueryResult>> { + let target_bytes = context.to.to_vec(); + + // Find a grant where: + // 1. The basic grant's wallet_id and client_id match the context + // 2. Any of the grant's targets match the context's `to` address + let grant: Option<(EvmBasicGrant, EvmEtherTransferGrant)> = evm_ether_transfer_grant::table + .inner_join(evm_basic_grant::table) + .inner_join(evm_ether_transfer_grant_target::table) + .filter( + evm_basic_grant::wallet_access_id + .eq(context.target.id) + .and(evm_basic_grant::revoked_at.is_null()) + .and(evm_ether_transfer_grant_target::address.eq(&target_bytes)), + ) + .select(( + EvmBasicGrant::as_select(), + EvmEtherTransferGrant::as_select(), + )) + .first(conn) + .await + .optional()?; + + let Some((basic_grant, grant)) = grant else { + return Ok(None); + }; + + let target_bytes: Vec = evm_ether_transfer_grant_target::table + .select(EvmEtherTransferGrantTarget::as_select()) + .filter(evm_ether_transfer_grant_target::grant_id.eq(grant.id)) + .load(conn) + .await?; + + let limit: EvmEtherTransferLimit = evm_ether_transfer_limit::table + .filter(evm_ether_transfer_limit::id.eq(grant.limit_id)) + .select(EvmEtherTransferLimit::as_select()) + .first::(conn) + .await?; + + // Convert bytes back to Address + let targets: Vec
= target_bytes + .into_iter() + .filter_map(|target| { + // TODO: Handle invalid addresses more gracefully + let arr: [u8; 20] = target.address.try_into().ok()?; + Some(Address::from(arr)) + }) + .collect(); + + let settings = Settings { + target: targets, + limit: VolumeRateLimit { + max_volume: utils::try_bytes_to_u256(&limit.max_volume) + .map_err(|err| diesel::result::Error::DeserializationError(Box::new(err)))?, + window: Duration::seconds(limit.window_secs.into()), + }, + }; + + Ok(Some(Grant { + id: grant.id, + common_settings_id: grant.basic_grant_id, + settings: CombinedSettings { + shared: SharedGrantSettings::try_from_model(basic_grant)?, + specific: settings, + }, + })) + } + + async fn record_transaction( + _context: &EvalContext, + _: &Self::Meaning, + _log_id: i32, + _grant: &Grant, + _conn: &mut impl AsyncConnection, + ) -> QueryResult<()> { + // Basic log is sufficient + + Ok(()) + } + + async fn find_all_grants( + conn: &mut impl AsyncConnection, + ) -> QueryResult>> { + let grants: Vec<(EvmBasicGrant, EvmEtherTransferGrant)> = grant_join() + .filter(evm_basic_grant::revoked_at.is_null()) + .select(( + EvmBasicGrant::as_select(), + EvmEtherTransferGrant::as_select(), + )) + .load(conn) + .await?; + + if grants.is_empty() { + return Ok(Vec::new()); + } + + let grant_ids: Vec = grants.iter().map(|(_, g)| g.id).collect(); + let limit_ids: Vec = grants.iter().map(|(_, g)| g.limit_id).collect(); + + let all_targets: Vec = evm_ether_transfer_grant_target::table + .filter(evm_ether_transfer_grant_target::grant_id.eq_any(&grant_ids)) + .select(EvmEtherTransferGrantTarget::as_select()) + .load(conn) + .await?; + + let all_limits: Vec = evm_ether_transfer_limit::table + .filter(evm_ether_transfer_limit::id.eq_any(&limit_ids)) + .select(EvmEtherTransferLimit::as_select()) + .load(conn) + .await?; + + let mut targets_by_grant: HashMap> = HashMap::new(); + for target in all_targets { + targets_by_grant + .entry(target.grant_id) + .or_default() + .push(target); + } + + let limits_by_id: HashMap = + all_limits.into_iter().map(|l| (l.id, l)).collect(); + + grants + .into_iter() + .map(|(basic, specific)| { + let targets: Vec
= targets_by_grant + .get(&specific.id) + .map(Vec::as_slice) + .unwrap_or_default() + .iter() + .filter_map(|t| { + let arr: [u8; 20] = t.address.clone().try_into().ok()?; + Some(Address::from(arr)) + }) + .collect(); + + let limit = limits_by_id + .get(&specific.limit_id) + .ok_or(diesel::result::Error::NotFound)?; + + Ok(Grant { + id: specific.id, + common_settings_id: specific.basic_grant_id, + settings: CombinedSettings { + shared: SharedGrantSettings::try_from_model(basic)?, + specific: Settings { + target: targets, + limit: VolumeRateLimit { + max_volume: utils::try_bytes_to_u256(&limit.max_volume).map_err( + |e| diesel::result::Error::DeserializationError(Box::new(e)), + )?, + window: Duration::seconds(limit.window_secs.into()), + }, + }, + }, + }) + }) + .collect() + } +} + +#[cfg(test)] +mod tests; diff --git a/server/crates/arbiter-server/src/evm/policies/ether_transfer/tests.rs b/server/crates/arbiter-server/src/evm/policies/ether_transfer/tests.rs index 82d98a9..167e098 100644 --- a/server/crates/arbiter-server/src/evm/policies/ether_transfer/tests.rs +++ b/server/crates/arbiter-server/src/evm/policies/ether_transfer/tests.rs @@ -1,430 +1,430 @@ -use super::{EtherTransfer, Settings}; -use crate::{ - db::{ - self, DatabaseConnection, - models::{ - EvmBasicGrant, EvmWalletAccess, NewEvmBasicGrant, NewEvmTransactionLog, SqliteTimestamp, - }, - schema::{evm_basic_grant, evm_transaction_log}, - }, - evm::{ - policies::{ - CombinedSettings, EvalContext, EvalViolation, Grant, Policy, SharedGrantSettings, - VolumeRateLimit, - }, - utils, - }, -}; - -use alloy::primitives::{Address, Bytes, U256, address}; -use chrono::{Duration, Utc}; -use diesel::{SelectableHelper, insert_into}; -use diesel_async::RunQueryDsl; - -const WALLET_ACCESS_ID: i32 = 1; -const CHAIN_ID: alloy::primitives::ChainId = 1; - -const ALLOWED: Address = address!("1111111111111111111111111111111111111111"); -const OTHER: Address = address!("2222222222222222222222222222222222222222"); - -fn ctx(to: Address, value: U256) -> EvalContext { - EvalContext { - target: EvmWalletAccess { - id: WALLET_ACCESS_ID, - wallet_id: 10, - client_id: 20, - created_at: SqliteTimestamp(Utc::now()), - }, - chain: CHAIN_ID, - to, - value, - calldata: Bytes::new(), - max_fee_per_gas: 0, - max_priority_fee_per_gas: 0, - } -} - -async fn insert_basic(conn: &mut DatabaseConnection, revoked: bool) -> EvmBasicGrant { - insert_into(evm_basic_grant::table) - .values(NewEvmBasicGrant { - wallet_access_id: WALLET_ACCESS_ID, - chain_id: CHAIN_ID.into(), - valid_from: None, - valid_until: None, - max_gas_fee_per_gas: None, - max_priority_fee_per_gas: None, - rate_limit_count: None, - rate_limit_window_secs: None, - revoked_at: revoked.then(|| SqliteTimestamp(Utc::now())), - }) - .returning(EvmBasicGrant::as_select()) - .get_result(conn) - .await - .unwrap() -} - -fn make_settings(targets: Vec
, max_volume: u64) -> Settings { - Settings { - target: targets, - limit: VolumeRateLimit { - max_volume: U256::from(max_volume), - window: Duration::hours(1), - }, - } -} - -fn shared() -> SharedGrantSettings { - SharedGrantSettings { - wallet_access_id: WALLET_ACCESS_ID, - chain: CHAIN_ID, - valid_from: None, - valid_until: None, - revoked_at: None, - max_gas_fee_per_gas: None, - max_priority_fee_per_gas: None, - rate_limit: None, - } -} - -#[test] -fn analyze_matches_empty_calldata() { - let m = EtherTransfer::analyze(&ctx(ALLOWED, U256::from(1_000u64))).unwrap(); - assert_eq!(m.to, ALLOWED); - assert_eq!(m.value, U256::from(1_000u64)); -} - -#[test] -fn analyze_rejects_nonempty_calldata() { - let context = EvalContext { - calldata: Bytes::from(vec![0xde, 0xad, 0xbe, 0xef]), - ..ctx(ALLOWED, U256::from(1u64)) - }; - assert!(EtherTransfer::analyze(&context).is_none()); -} - -#[tokio::test] -async fn evaluate_passes_for_allowed_target() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let grant = Grant { - id: 999, - common_settings_id: 999, - settings: CombinedSettings { - shared: shared(), - specific: make_settings(vec![ALLOWED], 1_000_000), - }, - }; - let context = ctx(ALLOWED, U256::from(100u64)); - let m = EtherTransfer::analyze(&context).unwrap(); - let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!(v.is_empty()); -} - -#[tokio::test] -async fn evaluate_rejects_disallowed_target() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let grant = Grant { - id: 999, - common_settings_id: 999, - settings: CombinedSettings { - shared: shared(), - specific: make_settings(vec![ALLOWED], 1_000_000), - }, - }; - let context = ctx(OTHER, U256::from(100u64)); - let m = EtherTransfer::analyze(&context).unwrap(); - let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!( - v.iter() - .any(|e| matches!(e, EvalViolation::InvalidTarget { .. })) - ); -} - -#[tokio::test] -async fn evaluate_passes_when_volume_within_limit() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(vec![ALLOWED], 1_000); - let grant_id = EtherTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - insert_into(evm_transaction_log::table) - .values(NewEvmTransactionLog { - grant_id, - wallet_access_id: WALLET_ACCESS_ID, - chain_id: CHAIN_ID.into(), - eth_value: utils::u256_to_bytes(U256::from(500u64)).to_vec(), - signed_at: SqliteTimestamp(Utc::now()), - }) - .execute(&mut *conn) - .await - .unwrap(); - - let grant = Grant { - id: grant_id, - common_settings_id: basic.id, - settings: CombinedSettings { - shared: shared(), - specific: settings, - }, - }; - let context = ctx(ALLOWED, U256::from(100u64)); - let m = EtherTransfer::analyze(&context).unwrap(); - let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!( - !v.iter() - .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) - ); -} - -#[tokio::test] -async fn evaluate_rejects_volume_over_limit() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(vec![ALLOWED], 1_000); - let grant_id = EtherTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - insert_into(evm_transaction_log::table) - .values(NewEvmTransactionLog { - grant_id, - wallet_access_id: WALLET_ACCESS_ID, - chain_id: CHAIN_ID.into(), - eth_value: utils::u256_to_bytes(U256::from(1_000u64)).to_vec(), - signed_at: SqliteTimestamp(Utc::now()), - }) - .execute(&mut *conn) - .await - .unwrap(); - - let grant = Grant { - id: grant_id, - common_settings_id: basic.id, - settings: CombinedSettings { - shared: shared(), - specific: settings, - }, - }; - let context = ctx(ALLOWED, U256::from(1u64)); - let m = EtherTransfer::analyze(&context).unwrap(); - let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!( - v.iter() - .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) - ); -} - -#[tokio::test] -async fn evaluate_passes_at_exactly_volume_limit() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(vec![ALLOWED], 1_000); - let grant_id = EtherTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - // Exactly at the limit including current transfer — check is `>`, so this should not violate - insert_into(evm_transaction_log::table) - .values(NewEvmTransactionLog { - grant_id, - wallet_access_id: WALLET_ACCESS_ID, - chain_id: CHAIN_ID.into(), - eth_value: utils::u256_to_bytes(U256::from(900u64)).to_vec(), - signed_at: SqliteTimestamp(Utc::now()), - }) - .execute(&mut *conn) - .await - .unwrap(); - - let grant = Grant { - id: grant_id, - common_settings_id: basic.id, - settings: CombinedSettings { - shared: shared(), - specific: settings, - }, - }; - let context = ctx(ALLOWED, U256::from(100u64)); - let m = EtherTransfer::analyze(&context).unwrap(); - let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!( - !v.iter() - .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) - ); -} - -#[tokio::test] -async fn try_find_grant_roundtrip() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(vec![ALLOWED], 1_000_000); - EtherTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - let found = EtherTransfer::try_find_grant(&ctx(ALLOWED, U256::from(1u64)), &mut *conn) - .await - .unwrap(); - - assert!(found.is_some()); - let g = found.unwrap(); - assert_eq!(g.settings.specific.target, vec![ALLOWED]); - assert_eq!( - g.settings.specific.limit.max_volume, - U256::from(1_000_000u64) - ); -} - -#[tokio::test] -async fn try_find_grant_revoked_returns_none() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, true).await; - let settings = make_settings(vec![ALLOWED], 1_000_000); - EtherTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - let found = EtherTransfer::try_find_grant(&ctx(ALLOWED, U256::from(1u64)), &mut *conn) - .await - .unwrap(); - assert!(found.is_none()); -} - -#[tokio::test] -async fn try_find_grant_wrong_target_returns_none() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(vec![ALLOWED], 1_000_000); - EtherTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - let found = EtherTransfer::try_find_grant(&ctx(OTHER, U256::from(1u64)), &mut *conn) - .await - .unwrap(); - assert!(found.is_none()); -} - -proptest::proptest! { - #[test] - fn target_order_does_not_affect_hash( - raw_addrs in proptest::collection::vec(proptest::prelude::any::<[u8; 20]>(), 0..8), - seed in proptest::prelude::any::(), - max_volume in proptest::prelude::any::(), - window_secs in 1i64..=86400, - ) { - use rand::{SeedableRng, seq::SliceRandom}; - use sha2::Digest; - use arbiter_crypto::hashing::Hashable; - - let addrs: Vec
= raw_addrs.iter().map(|b| Address::from(*b)).collect(); - let mut shuffled = addrs.clone(); - shuffled.shuffle(&mut rand::rngs::StdRng::seed_from_u64(seed)); - - let limit = VolumeRateLimit { - max_volume: U256::from(max_volume), - window: Duration::seconds(window_secs), - }; - - let mut h1 = sha2::Sha256::new(); - Settings { target: addrs, limit: limit.clone() }.hash(&mut h1); - - let mut h2 = sha2::Sha256::new(); - Settings { target: shuffled, limit }.hash(&mut h2); - - proptest::prop_assert_eq!(h1.finalize(), h2.finalize()); - } -} - -#[tokio::test] -async fn find_all_grants_empty_db() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - let all = EtherTransfer::find_all_grants(&mut *conn).await.unwrap(); - assert!(all.is_empty()); -} - -#[tokio::test] -async fn find_all_grants_excludes_revoked() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let settings = make_settings(vec![ALLOWED], 1_000_000); - let active = insert_basic(&mut conn, false).await; - EtherTransfer::create_grant(&active, &settings, &mut *conn) - .await - .unwrap(); - let revoked = insert_basic(&mut conn, true).await; - EtherTransfer::create_grant(&revoked, &settings, &mut *conn) - .await - .unwrap(); - - let all = EtherTransfer::find_all_grants(&mut *conn).await.unwrap(); - assert_eq!(all.len(), 1); - assert_eq!(all[0].settings.specific.target, vec![ALLOWED]); -} - -#[tokio::test] -async fn find_all_grants_multiple_targets() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(vec![ALLOWED, OTHER], 1_000_000); - EtherTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - let all = EtherTransfer::find_all_grants(&mut *conn).await.unwrap(); - assert_eq!(all.len(), 1); - assert_eq!(all[0].settings.specific.target.len(), 2); - assert_eq!( - all[0].settings.specific.limit.max_volume, - U256::from(1_000_000u64) - ); -} - -#[tokio::test] -async fn find_all_grants_multiple_grants() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic1 = insert_basic(&mut conn, false).await; - EtherTransfer::create_grant(&basic1, &make_settings(vec![ALLOWED], 500), &mut *conn) - .await - .unwrap(); - let basic2 = insert_basic(&mut conn, false).await; - EtherTransfer::create_grant(&basic2, &make_settings(vec![OTHER], 1_000), &mut *conn) - .await - .unwrap(); - - let all = EtherTransfer::find_all_grants(&mut *conn).await.unwrap(); - assert_eq!(all.len(), 2); -} +use super::{EtherTransfer, Settings}; +use crate::{ + db::{ + self, DatabaseConnection, + models::{ + EvmBasicGrant, EvmWalletAccess, NewEvmBasicGrant, NewEvmTransactionLog, SqliteTimestamp, + }, + schema::{evm_basic_grant, evm_transaction_log}, + }, + evm::{ + policies::{ + CombinedSettings, EvalContext, EvalViolation, Grant, Policy, SharedGrantSettings, + VolumeRateLimit, + }, + utils, + }, +}; + +use alloy::primitives::{Address, Bytes, U256, address}; +use chrono::{Duration, Utc}; +use diesel::{SelectableHelper, insert_into}; +use diesel_async::RunQueryDsl; + +const WALLET_ACCESS_ID: i32 = 1; +const CHAIN_ID: alloy::primitives::ChainId = 1; + +const ALLOWED: Address = address!("1111111111111111111111111111111111111111"); +const OTHER: Address = address!("2222222222222222222222222222222222222222"); + +fn ctx(to: Address, value: U256) -> EvalContext { + EvalContext { + target: EvmWalletAccess { + id: WALLET_ACCESS_ID, + wallet_id: 10, + client_id: 20, + created_at: SqliteTimestamp(Utc::now()), + }, + chain: CHAIN_ID, + to, + value, + calldata: Bytes::new(), + max_fee_per_gas: 0, + max_priority_fee_per_gas: 0, + } +} + +async fn insert_basic(conn: &mut DatabaseConnection, revoked: bool) -> EvmBasicGrant { + insert_into(evm_basic_grant::table) + .values(NewEvmBasicGrant { + wallet_access_id: WALLET_ACCESS_ID, + chain_id: CHAIN_ID.into(), + valid_from: None, + valid_until: None, + max_gas_fee_per_gas: None, + max_priority_fee_per_gas: None, + rate_limit_count: None, + rate_limit_window_secs: None, + revoked_at: revoked.then(|| SqliteTimestamp(Utc::now())), + }) + .returning(EvmBasicGrant::as_select()) + .get_result(conn) + .await + .unwrap() +} + +fn make_settings(targets: Vec
, max_volume: u64) -> Settings { + Settings { + target: targets, + limit: VolumeRateLimit { + max_volume: U256::from(max_volume), + window: Duration::hours(1), + }, + } +} + +fn shared() -> SharedGrantSettings { + SharedGrantSettings { + wallet_access_id: WALLET_ACCESS_ID, + chain: CHAIN_ID, + valid_from: None, + valid_until: None, + revoked_at: None, + max_gas_fee_per_gas: None, + max_priority_fee_per_gas: None, + rate_limit: None, + } +} + +#[test] +fn analyze_matches_empty_calldata() { + let m = EtherTransfer::analyze(&ctx(ALLOWED, U256::from(1_000u64))).unwrap(); + assert_eq!(m.to, ALLOWED); + assert_eq!(m.value, U256::from(1_000u64)); +} + +#[test] +fn analyze_rejects_nonempty_calldata() { + let context = EvalContext { + calldata: Bytes::from(vec![0xde, 0xad, 0xbe, 0xef]), + ..ctx(ALLOWED, U256::from(1u64)) + }; + assert!(EtherTransfer::analyze(&context).is_none()); +} + +#[tokio::test] +async fn evaluate_passes_for_allowed_target() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let grant = Grant { + id: 999, + common_settings_id: 999, + settings: CombinedSettings { + shared: shared(), + specific: make_settings(vec![ALLOWED], 1_000_000), + }, + }; + let context = ctx(ALLOWED, U256::from(100u64)); + let m = EtherTransfer::analyze(&context).unwrap(); + let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!(v.is_empty()); +} + +#[tokio::test] +async fn evaluate_rejects_disallowed_target() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let grant = Grant { + id: 999, + common_settings_id: 999, + settings: CombinedSettings { + shared: shared(), + specific: make_settings(vec![ALLOWED], 1_000_000), + }, + }; + let context = ctx(OTHER, U256::from(100u64)); + let m = EtherTransfer::analyze(&context).unwrap(); + let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!( + v.iter() + .any(|e| matches!(e, EvalViolation::InvalidTarget { .. })) + ); +} + +#[tokio::test] +async fn evaluate_passes_when_volume_within_limit() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(vec![ALLOWED], 1_000); + let grant_id = EtherTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + insert_into(evm_transaction_log::table) + .values(NewEvmTransactionLog { + grant_id, + wallet_access_id: WALLET_ACCESS_ID, + chain_id: CHAIN_ID.into(), + eth_value: utils::u256_to_bytes(U256::from(500u64)).to_vec(), + signed_at: SqliteTimestamp(Utc::now()), + }) + .execute(&mut *conn) + .await + .unwrap(); + + let grant = Grant { + id: grant_id, + common_settings_id: basic.id, + settings: CombinedSettings { + shared: shared(), + specific: settings, + }, + }; + let context = ctx(ALLOWED, U256::from(100u64)); + let m = EtherTransfer::analyze(&context).unwrap(); + let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!( + !v.iter() + .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) + ); +} + +#[tokio::test] +async fn evaluate_rejects_volume_over_limit() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(vec![ALLOWED], 1_000); + let grant_id = EtherTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + insert_into(evm_transaction_log::table) + .values(NewEvmTransactionLog { + grant_id, + wallet_access_id: WALLET_ACCESS_ID, + chain_id: CHAIN_ID.into(), + eth_value: utils::u256_to_bytes(U256::from(1_000u64)).to_vec(), + signed_at: SqliteTimestamp(Utc::now()), + }) + .execute(&mut *conn) + .await + .unwrap(); + + let grant = Grant { + id: grant_id, + common_settings_id: basic.id, + settings: CombinedSettings { + shared: shared(), + specific: settings, + }, + }; + let context = ctx(ALLOWED, U256::from(1u64)); + let m = EtherTransfer::analyze(&context).unwrap(); + let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!( + v.iter() + .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) + ); +} + +#[tokio::test] +async fn evaluate_passes_at_exactly_volume_limit() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(vec![ALLOWED], 1_000); + let grant_id = EtherTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + // Exactly at the limit including current transfer — check is `>`, so this should not violate + insert_into(evm_transaction_log::table) + .values(NewEvmTransactionLog { + grant_id, + wallet_access_id: WALLET_ACCESS_ID, + chain_id: CHAIN_ID.into(), + eth_value: utils::u256_to_bytes(U256::from(900u64)).to_vec(), + signed_at: SqliteTimestamp(Utc::now()), + }) + .execute(&mut *conn) + .await + .unwrap(); + + let grant = Grant { + id: grant_id, + common_settings_id: basic.id, + settings: CombinedSettings { + shared: shared(), + specific: settings, + }, + }; + let context = ctx(ALLOWED, U256::from(100u64)); + let m = EtherTransfer::analyze(&context).unwrap(); + let v = EtherTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!( + !v.iter() + .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) + ); +} + +#[tokio::test] +async fn try_find_grant_roundtrip() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(vec![ALLOWED], 1_000_000); + EtherTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + let found = EtherTransfer::try_find_grant(&ctx(ALLOWED, U256::from(1u64)), &mut *conn) + .await + .unwrap(); + + assert!(found.is_some()); + let g = found.unwrap(); + assert_eq!(g.settings.specific.target, vec![ALLOWED]); + assert_eq!( + g.settings.specific.limit.max_volume, + U256::from(1_000_000u64) + ); +} + +#[tokio::test] +async fn try_find_grant_revoked_returns_none() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, true).await; + let settings = make_settings(vec![ALLOWED], 1_000_000); + EtherTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + let found = EtherTransfer::try_find_grant(&ctx(ALLOWED, U256::from(1u64)), &mut *conn) + .await + .unwrap(); + assert!(found.is_none()); +} + +#[tokio::test] +async fn try_find_grant_wrong_target_returns_none() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(vec![ALLOWED], 1_000_000); + EtherTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + let found = EtherTransfer::try_find_grant(&ctx(OTHER, U256::from(1u64)), &mut *conn) + .await + .unwrap(); + assert!(found.is_none()); +} + +proptest::proptest! { + #[test] + fn target_order_does_not_affect_hash( + raw_addrs in proptest::collection::vec(proptest::prelude::any::<[u8; 20]>(), 0..8), + seed in proptest::prelude::any::(), + max_volume in proptest::prelude::any::(), + window_secs in 1i64..=86400, + ) { + use rand::{SeedableRng, seq::SliceRandom}; + use sha2::Digest; + use arbiter_crypto::hashing::Hashable; + + let addrs: Vec
= raw_addrs.iter().map(|b| Address::from(*b)).collect(); + let mut shuffled = addrs.clone(); + shuffled.shuffle(&mut rand::rngs::StdRng::seed_from_u64(seed)); + + let limit = VolumeRateLimit { + max_volume: U256::from(max_volume), + window: Duration::seconds(window_secs), + }; + + let mut h1 = sha2::Sha256::new(); + Settings { target: addrs, limit: limit.clone() }.hash(&mut h1); + + let mut h2 = sha2::Sha256::new(); + Settings { target: shuffled, limit }.hash(&mut h2); + + proptest::prop_assert_eq!(h1.finalize(), h2.finalize()); + } +} + +#[tokio::test] +async fn find_all_grants_empty_db() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + let all = EtherTransfer::find_all_grants(&mut *conn).await.unwrap(); + assert!(all.is_empty()); +} + +#[tokio::test] +async fn find_all_grants_excludes_revoked() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let settings = make_settings(vec![ALLOWED], 1_000_000); + let active = insert_basic(&mut conn, false).await; + EtherTransfer::create_grant(&active, &settings, &mut *conn) + .await + .unwrap(); + let revoked = insert_basic(&mut conn, true).await; + EtherTransfer::create_grant(&revoked, &settings, &mut *conn) + .await + .unwrap(); + + let all = EtherTransfer::find_all_grants(&mut *conn).await.unwrap(); + assert_eq!(all.len(), 1); + assert_eq!(all[0].settings.specific.target, vec![ALLOWED]); +} + +#[tokio::test] +async fn find_all_grants_multiple_targets() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(vec![ALLOWED, OTHER], 1_000_000); + EtherTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + let all = EtherTransfer::find_all_grants(&mut *conn).await.unwrap(); + assert_eq!(all.len(), 1); + assert_eq!(all[0].settings.specific.target.len(), 2); + assert_eq!( + all[0].settings.specific.limit.max_volume, + U256::from(1_000_000u64) + ); +} + +#[tokio::test] +async fn find_all_grants_multiple_grants() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic1 = insert_basic(&mut conn, false).await; + EtherTransfer::create_grant(&basic1, &make_settings(vec![ALLOWED], 500), &mut *conn) + .await + .unwrap(); + let basic2 = insert_basic(&mut conn, false).await; + EtherTransfer::create_grant(&basic2, &make_settings(vec![OTHER], 1_000), &mut *conn) + .await + .unwrap(); + + let all = EtherTransfer::find_all_grants(&mut *conn).await.unwrap(); + assert_eq!(all.len(), 2); +} diff --git a/server/crates/arbiter-server/src/evm/policies/token_transfers/mod.rs b/server/crates/arbiter-server/src/evm/policies/token_transfers/mod.rs index d91b942..ddec24a 100644 --- a/server/crates/arbiter-server/src/evm/policies/token_transfers/mod.rs +++ b/server/crates/arbiter-server/src/evm/policies/token_transfers/mod.rs @@ -1,408 +1,408 @@ -use super::{DatabaseID, EvalContext, EvalViolation}; -use crate::{ - crypto::integrity::Integrable, - db::models::{ - EvmBasicGrant, EvmTokenTransferGrant, EvmTokenTransferVolumeLimit, - NewEvmTokenTransferGrant, NewEvmTokenTransferLog, NewEvmTokenTransferVolumeLimit, - SqliteTimestamp, - }, - db::schema::{ - evm_basic_grant, evm_token_transfer_grant, evm_token_transfer_log, - evm_token_transfer_volume_limit, - }, - evm::policies::CombinedSettings, - evm::{ - abi::IERC20::transferCall, - policies::{ - Grant, Policy, SharedGrantSettings, SpecificGrant, SpecificMeaning, VolumeRateLimit, - }, - utils, - }, -}; -use arbiter_tokens_registry::evm::nonfungible::{self, TokenInfo}; - -use alloy::{ - primitives::{Address, U256}, - sol_types::SolCall, -}; -use chrono::{DateTime, Duration, Utc}; -use diesel::{ - dsl::{auto_type, insert_into}, - prelude::*, - sqlite::Sqlite, -}; -use diesel_async::{AsyncConnection, RunQueryDsl}; -use std::collections::HashMap; - -#[auto_type] -fn grant_join() -> _ { - evm_token_transfer_grant::table.inner_join( - evm_basic_grant::table.on(evm_token_transfer_grant::basic_grant_id.eq(evm_basic_grant::id)), - ) -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Meaning { - pub token: &'static TokenInfo, - pub to: Address, - pub value: U256, -} -impl std::fmt::Display for Meaning { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "Transfer of {} {} to {}", - self.value, self.token.symbol, self.to - ) - } -} -impl From for SpecificMeaning { - fn from(val: Meaning) -> Self { - Self::TokenTransfer(val) - } -} - -// A grant for token transfers, which can be scoped to specific target addresses and volume limits -#[derive(Debug, Clone, arbiter_macros::Hashable)] -pub struct Settings { - pub token_contract: Address, - pub target: Option
, - pub volume_limits: Vec, -} -impl Integrable for Settings { - const KIND: &'static str = "TokenTransfer"; -} - -impl From for SpecificGrant { - fn from(val: Settings) -> Self { - Self::TokenTransfer(val) - } -} - -async fn query_relevant_past_transfers( - grant_id: i32, - longest_window: Duration, - db: &mut impl AsyncConnection, -) -> QueryResult)>> { - let past_logs: Vec<(Vec, SqliteTimestamp)> = evm_token_transfer_log::table - .filter(evm_token_transfer_log::grant_id.eq(grant_id)) - .filter(evm_token_transfer_log::created_at.ge(SqliteTimestamp(Utc::now() - longest_window))) - .select(( - evm_token_transfer_log::value, - evm_token_transfer_log::created_at, - )) - .load(db) - .await?; - - let past_transfers: Vec<(U256, DateTime)> = past_logs - .into_iter() - .filter_map(|(value_bytes, timestamp)| { - let value = utils::bytes_to_u256(&value_bytes)?; - Some((value, timestamp.0)) - }) - .collect(); - - Ok(past_transfers) -} - -async fn check_volume_rate_limits( - grant: &Grant, - current_transfer_value: U256, - db: &mut impl AsyncConnection, -) -> QueryResult> { - let mut violations = Vec::new(); - - let Some(longest_window) = grant - .settings - .specific - .volume_limits - .iter() - .map(|l| l.window) - .max() - else { - return Ok(violations); - }; - - let past_transfers = query_relevant_past_transfers(grant.id, longest_window, db).await?; - - for limit in &grant.settings.specific.volume_limits { - let window_start = Utc::now() - limit.window; - let prospective_cumulative_volume: U256 = past_transfers - .iter() - .filter(|(_, timestamp)| timestamp >= &window_start) - .fold(current_transfer_value, |acc, (value, _)| acc + *value); - - if prospective_cumulative_volume > limit.max_volume { - violations.push(EvalViolation::VolumetricLimitExceeded); - break; - } - } - - Ok(violations) -} - -pub struct TokenTransfer; -impl Policy for TokenTransfer { - type Settings = Settings; - type Meaning = Meaning; - - fn analyze(context: &EvalContext) -> Option { - let token = nonfungible::get_token(context.chain, context.to)?; - let decoded = transferCall::abi_decode_raw_validate(&context.calldata).ok()?; - - Some(Meaning { - token, - to: decoded.to, - value: decoded.value, - }) - } - - async fn evaluate( - context: &EvalContext, - meaning: &Self::Meaning, - grant: &Grant, - db: &mut impl AsyncConnection, - ) -> QueryResult> { - let mut violations = Vec::new(); - - // erc20 transfer shouldn't carry eth value - if !context.value.is_zero() { - violations.push(EvalViolation::InvalidTransactionType); - return Ok(violations); - } - - if let Some(allowed) = grant.settings.specific.target - && allowed != meaning.to - { - violations.push(EvalViolation::InvalidTarget { target: meaning.to }); - } - - let rate_violations = check_volume_rate_limits(grant, meaning.value, db).await?; - violations.extend(rate_violations); - - Ok(violations) - } - - async fn create_grant( - basic: &EvmBasicGrant, - grant: &Self::Settings, - conn: &mut impl AsyncConnection, - ) -> QueryResult { - // Store the specific receiver as bytes (None means any receiver is allowed) - let receiver: Option> = grant.target.map(|addr| addr.to_vec()); - - let grant_id: i32 = insert_into(evm_token_transfer_grant::table) - .values(NewEvmTokenTransferGrant { - basic_grant_id: basic.id, - token_contract: grant.token_contract.to_vec(), - receiver, - }) - .returning(evm_token_transfer_grant::id) - .get_result(conn) - .await?; - - for limit in &grant.volume_limits { - #[expect( - clippy::cast_possible_truncation, - clippy::as_conversions, - reason = "fixme! #86" - )] - insert_into(evm_token_transfer_volume_limit::table) - .values(NewEvmTokenTransferVolumeLimit { - grant_id, - window_secs: limit.window.num_seconds() as i32, - max_volume: utils::u256_to_bytes(limit.max_volume).to_vec(), - }) - .execute(conn) - .await?; - } - - Ok(grant_id) - } - - async fn try_find_grant( - context: &EvalContext, - conn: &mut impl AsyncConnection, - ) -> QueryResult>> { - let token_contract_bytes = context.to.to_vec(); - - let grant: Option<(EvmBasicGrant, EvmTokenTransferGrant)> = grant_join() - .filter(evm_basic_grant::revoked_at.is_null()) - .filter(evm_basic_grant::wallet_access_id.eq(context.target.id)) - .filter(evm_token_transfer_grant::token_contract.eq(&token_contract_bytes)) - .select(( - EvmBasicGrant::as_select(), - EvmTokenTransferGrant::as_select(), - )) - .first(conn) - .await - .optional()?; - - let Some((basic_grant, token_grant)) = grant else { - return Ok(None); - }; - - let volume_limits_db: Vec = - evm_token_transfer_volume_limit::table - .filter(evm_token_transfer_volume_limit::grant_id.eq(token_grant.id)) - .select(EvmTokenTransferVolumeLimit::as_select()) - .load(conn) - .await?; - - let volume_limits: Vec = volume_limits_db - .into_iter() - .map(|row| { - Ok(VolumeRateLimit { - max_volume: utils::try_bytes_to_u256(&row.max_volume).map_err(|err| { - diesel::result::Error::DeserializationError(Box::new(err)) - })?, - window: Duration::seconds(row.window_secs.into()), - }) - }) - .collect::>>()?; - - let token_contract: [u8; 20] = token_grant.token_contract.try_into().map_err(|_| { - diesel::result::Error::DeserializationError( - "Invalid token contract address length".into(), - ) - })?; - - let target: Option
= match token_grant.receiver { - None => None, - Some(bytes) => { - let arr: [u8; 20] = bytes.try_into().map_err(|_| { - diesel::result::Error::DeserializationError( - "Invalid receiver address length".into(), - ) - })?; - Some(Address::from(arr)) - } - }; - - let settings = Settings { - token_contract: Address::from(token_contract), - target, - volume_limits, - }; - - Ok(Some(Grant { - id: token_grant.id, - common_settings_id: token_grant.basic_grant_id, - settings: CombinedSettings { - shared: SharedGrantSettings::try_from_model(basic_grant)?, - specific: settings, - }, - })) - } - - async fn record_transaction( - context: &EvalContext, - meaning: &Self::Meaning, - log_id: i32, - grant: &Grant, - conn: &mut impl AsyncConnection, - ) -> QueryResult<()> { - insert_into(evm_token_transfer_log::table) - .values(NewEvmTokenTransferLog { - grant_id: grant.id, - log_id, - chain_id: context.chain.into(), - token_contract: context.to.to_vec(), - recipient_address: meaning.to.to_vec(), - value: utils::u256_to_bytes(meaning.value).to_vec(), - }) - .execute(conn) - .await?; - - Ok(()) - } - - async fn find_all_grants( - conn: &mut impl AsyncConnection, - ) -> QueryResult>> { - let grants: Vec<(EvmBasicGrant, EvmTokenTransferGrant)> = grant_join() - .filter(evm_basic_grant::revoked_at.is_null()) - .select(( - EvmBasicGrant::as_select(), - EvmTokenTransferGrant::as_select(), - )) - .load(conn) - .await?; - - if grants.is_empty() { - return Ok(Vec::new()); - } - - let grant_ids: Vec = grants.iter().map(|(_, g)| g.id).collect(); - - let all_volume_limits: Vec = - evm_token_transfer_volume_limit::table - .filter(evm_token_transfer_volume_limit::grant_id.eq_any(&grant_ids)) - .select(EvmTokenTransferVolumeLimit::as_select()) - .load(conn) - .await?; - - let mut limits_by_grant: HashMap> = HashMap::new(); - for limit in all_volume_limits { - limits_by_grant - .entry(limit.grant_id) - .or_default() - .push(limit); - } - - grants - .into_iter() - .map(|(basic, specific)| { - let volume_limits: Vec = limits_by_grant - .get(&specific.id) - .map(Vec::as_slice) - .unwrap_or_default() - .iter() - .map(|row| { - Ok(VolumeRateLimit { - max_volume: utils::try_bytes_to_u256(&row.max_volume).map_err(|e| { - diesel::result::Error::DeserializationError(Box::new(e)) - })?, - window: Duration::seconds(row.window_secs.into()), - }) - }) - .collect::>>()?; - - let token_contract: [u8; 20] = - specific.token_contract.clone().try_into().map_err(|_| { - diesel::result::Error::DeserializationError( - "Invalid token contract address length".into(), - ) - })?; - - let target: Option
= match &specific.receiver { - None => None, - Some(bytes) => { - let arr: [u8; 20] = bytes.clone().try_into().map_err(|_| { - diesel::result::Error::DeserializationError( - "Invalid receiver address length".into(), - ) - })?; - Some(Address::from(arr)) - } - }; - - Ok(Grant { - id: specific.id, - common_settings_id: specific.basic_grant_id, - settings: CombinedSettings { - shared: SharedGrantSettings::try_from_model(basic)?, - specific: Settings { - token_contract: Address::from(token_contract), - target, - volume_limits, - }, - }, - }) - }) - .collect() - } -} - -#[cfg(test)] -mod tests; +use super::{DatabaseID, EvalContext, EvalViolation}; +use crate::{ + crypto::integrity::Integrable, + db::models::{ + EvmBasicGrant, EvmTokenTransferGrant, EvmTokenTransferVolumeLimit, + NewEvmTokenTransferGrant, NewEvmTokenTransferLog, NewEvmTokenTransferVolumeLimit, + SqliteTimestamp, + }, + db::schema::{ + evm_basic_grant, evm_token_transfer_grant, evm_token_transfer_log, + evm_token_transfer_volume_limit, + }, + evm::policies::CombinedSettings, + evm::{ + abi::IERC20::transferCall, + policies::{ + Grant, Policy, SharedGrantSettings, SpecificGrant, SpecificMeaning, VolumeRateLimit, + }, + utils, + }, +}; +use arbiter_tokens_registry::evm::nonfungible::{self, TokenInfo}; + +use alloy::{ + primitives::{Address, U256}, + sol_types::SolCall, +}; +use chrono::{DateTime, Duration, Utc}; +use diesel::{ + dsl::{auto_type, insert_into}, + prelude::*, + sqlite::Sqlite, +}; +use diesel_async::{AsyncConnection, RunQueryDsl}; +use std::collections::HashMap; + +#[auto_type] +fn grant_join() -> _ { + evm_token_transfer_grant::table.inner_join( + evm_basic_grant::table.on(evm_token_transfer_grant::basic_grant_id.eq(evm_basic_grant::id)), + ) +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Meaning { + pub token: &'static TokenInfo, + pub to: Address, + pub value: U256, +} +impl std::fmt::Display for Meaning { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "Transfer of {} {} to {}", + self.value, self.token.symbol, self.to + ) + } +} +impl From for SpecificMeaning { + fn from(val: Meaning) -> Self { + Self::TokenTransfer(val) + } +} + +// A grant for token transfers, which can be scoped to specific target addresses and volume limits +#[derive(Debug, Clone, arbiter_macros::Hashable)] +pub struct Settings { + pub token_contract: Address, + pub target: Option
, + pub volume_limits: Vec, +} +impl Integrable for Settings { + const KIND: &'static str = "TokenTransfer"; +} + +impl From for SpecificGrant { + fn from(val: Settings) -> Self { + Self::TokenTransfer(val) + } +} + +async fn query_relevant_past_transfers( + grant_id: i32, + longest_window: Duration, + db: &mut impl AsyncConnection, +) -> QueryResult)>> { + let past_logs: Vec<(Vec, SqliteTimestamp)> = evm_token_transfer_log::table + .filter(evm_token_transfer_log::grant_id.eq(grant_id)) + .filter(evm_token_transfer_log::created_at.ge(SqliteTimestamp(Utc::now() - longest_window))) + .select(( + evm_token_transfer_log::value, + evm_token_transfer_log::created_at, + )) + .load(db) + .await?; + + let past_transfers: Vec<(U256, DateTime)> = past_logs + .into_iter() + .filter_map(|(value_bytes, timestamp)| { + let value = utils::bytes_to_u256(&value_bytes)?; + Some((value, timestamp.0)) + }) + .collect(); + + Ok(past_transfers) +} + +async fn check_volume_rate_limits( + grant: &Grant, + current_transfer_value: U256, + db: &mut impl AsyncConnection, +) -> QueryResult> { + let mut violations = Vec::new(); + + let Some(longest_window) = grant + .settings + .specific + .volume_limits + .iter() + .map(|l| l.window) + .max() + else { + return Ok(violations); + }; + + let past_transfers = query_relevant_past_transfers(grant.id, longest_window, db).await?; + + for limit in &grant.settings.specific.volume_limits { + let window_start = Utc::now() - limit.window; + let prospective_cumulative_volume: U256 = past_transfers + .iter() + .filter(|(_, timestamp)| timestamp >= &window_start) + .fold(current_transfer_value, |acc, (value, _)| acc + *value); + + if prospective_cumulative_volume > limit.max_volume { + violations.push(EvalViolation::VolumetricLimitExceeded); + break; + } + } + + Ok(violations) +} + +pub struct TokenTransfer; +impl Policy for TokenTransfer { + type Settings = Settings; + type Meaning = Meaning; + + fn analyze(context: &EvalContext) -> Option { + let token = nonfungible::get_token(context.chain, context.to)?; + let decoded = transferCall::abi_decode_raw_validate(&context.calldata).ok()?; + + Some(Meaning { + token, + to: decoded.to, + value: decoded.value, + }) + } + + async fn evaluate( + context: &EvalContext, + meaning: &Self::Meaning, + grant: &Grant, + db: &mut impl AsyncConnection, + ) -> QueryResult> { + let mut violations = Vec::new(); + + // erc20 transfer shouldn't carry eth value + if !context.value.is_zero() { + violations.push(EvalViolation::InvalidTransactionType); + return Ok(violations); + } + + if let Some(allowed) = grant.settings.specific.target + && allowed != meaning.to + { + violations.push(EvalViolation::InvalidTarget { target: meaning.to }); + } + + let rate_violations = check_volume_rate_limits(grant, meaning.value, db).await?; + violations.extend(rate_violations); + + Ok(violations) + } + + async fn create_grant( + basic: &EvmBasicGrant, + grant: &Self::Settings, + conn: &mut impl AsyncConnection, + ) -> QueryResult { + // Store the specific receiver as bytes (None means any receiver is allowed) + let receiver: Option> = grant.target.map(|addr| addr.to_vec()); + + let grant_id: i32 = insert_into(evm_token_transfer_grant::table) + .values(NewEvmTokenTransferGrant { + basic_grant_id: basic.id, + token_contract: grant.token_contract.to_vec(), + receiver, + }) + .returning(evm_token_transfer_grant::id) + .get_result(conn) + .await?; + + for limit in &grant.volume_limits { + #[expect( + clippy::cast_possible_truncation, + clippy::as_conversions, + reason = "fixme! #86" + )] + insert_into(evm_token_transfer_volume_limit::table) + .values(NewEvmTokenTransferVolumeLimit { + grant_id, + window_secs: limit.window.num_seconds() as i32, + max_volume: utils::u256_to_bytes(limit.max_volume).to_vec(), + }) + .execute(conn) + .await?; + } + + Ok(grant_id) + } + + async fn try_find_grant( + context: &EvalContext, + conn: &mut impl AsyncConnection, + ) -> QueryResult>> { + let token_contract_bytes = context.to.to_vec(); + + let grant: Option<(EvmBasicGrant, EvmTokenTransferGrant)> = grant_join() + .filter(evm_basic_grant::revoked_at.is_null()) + .filter(evm_basic_grant::wallet_access_id.eq(context.target.id)) + .filter(evm_token_transfer_grant::token_contract.eq(&token_contract_bytes)) + .select(( + EvmBasicGrant::as_select(), + EvmTokenTransferGrant::as_select(), + )) + .first(conn) + .await + .optional()?; + + let Some((basic_grant, token_grant)) = grant else { + return Ok(None); + }; + + let volume_limits_db: Vec = + evm_token_transfer_volume_limit::table + .filter(evm_token_transfer_volume_limit::grant_id.eq(token_grant.id)) + .select(EvmTokenTransferVolumeLimit::as_select()) + .load(conn) + .await?; + + let volume_limits: Vec = volume_limits_db + .into_iter() + .map(|row| { + Ok(VolumeRateLimit { + max_volume: utils::try_bytes_to_u256(&row.max_volume).map_err(|err| { + diesel::result::Error::DeserializationError(Box::new(err)) + })?, + window: Duration::seconds(row.window_secs.into()), + }) + }) + .collect::>>()?; + + let token_contract: [u8; 20] = token_grant.token_contract.try_into().map_err(|_| { + diesel::result::Error::DeserializationError( + "Invalid token contract address length".into(), + ) + })?; + + let target: Option
= match token_grant.receiver { + None => None, + Some(bytes) => { + let arr: [u8; 20] = bytes.try_into().map_err(|_| { + diesel::result::Error::DeserializationError( + "Invalid receiver address length".into(), + ) + })?; + Some(Address::from(arr)) + } + }; + + let settings = Settings { + token_contract: Address::from(token_contract), + target, + volume_limits, + }; + + Ok(Some(Grant { + id: token_grant.id, + common_settings_id: token_grant.basic_grant_id, + settings: CombinedSettings { + shared: SharedGrantSettings::try_from_model(basic_grant)?, + specific: settings, + }, + })) + } + + async fn record_transaction( + context: &EvalContext, + meaning: &Self::Meaning, + log_id: i32, + grant: &Grant, + conn: &mut impl AsyncConnection, + ) -> QueryResult<()> { + insert_into(evm_token_transfer_log::table) + .values(NewEvmTokenTransferLog { + grant_id: grant.id, + log_id, + chain_id: context.chain.into(), + token_contract: context.to.to_vec(), + recipient_address: meaning.to.to_vec(), + value: utils::u256_to_bytes(meaning.value).to_vec(), + }) + .execute(conn) + .await?; + + Ok(()) + } + + async fn find_all_grants( + conn: &mut impl AsyncConnection, + ) -> QueryResult>> { + let grants: Vec<(EvmBasicGrant, EvmTokenTransferGrant)> = grant_join() + .filter(evm_basic_grant::revoked_at.is_null()) + .select(( + EvmBasicGrant::as_select(), + EvmTokenTransferGrant::as_select(), + )) + .load(conn) + .await?; + + if grants.is_empty() { + return Ok(Vec::new()); + } + + let grant_ids: Vec = grants.iter().map(|(_, g)| g.id).collect(); + + let all_volume_limits: Vec = + evm_token_transfer_volume_limit::table + .filter(evm_token_transfer_volume_limit::grant_id.eq_any(&grant_ids)) + .select(EvmTokenTransferVolumeLimit::as_select()) + .load(conn) + .await?; + + let mut limits_by_grant: HashMap> = HashMap::new(); + for limit in all_volume_limits { + limits_by_grant + .entry(limit.grant_id) + .or_default() + .push(limit); + } + + grants + .into_iter() + .map(|(basic, specific)| { + let volume_limits: Vec = limits_by_grant + .get(&specific.id) + .map(Vec::as_slice) + .unwrap_or_default() + .iter() + .map(|row| { + Ok(VolumeRateLimit { + max_volume: utils::try_bytes_to_u256(&row.max_volume).map_err(|e| { + diesel::result::Error::DeserializationError(Box::new(e)) + })?, + window: Duration::seconds(row.window_secs.into()), + }) + }) + .collect::>>()?; + + let token_contract: [u8; 20] = + specific.token_contract.clone().try_into().map_err(|_| { + diesel::result::Error::DeserializationError( + "Invalid token contract address length".into(), + ) + })?; + + let target: Option
= match &specific.receiver { + None => None, + Some(bytes) => { + let arr: [u8; 20] = bytes.clone().try_into().map_err(|_| { + diesel::result::Error::DeserializationError( + "Invalid receiver address length".into(), + ) + })?; + Some(Address::from(arr)) + } + }; + + Ok(Grant { + id: specific.id, + common_settings_id: specific.basic_grant_id, + settings: CombinedSettings { + shared: SharedGrantSettings::try_from_model(basic)?, + specific: Settings { + token_contract: Address::from(token_contract), + target, + volume_limits, + }, + }, + }) + }) + .collect() + } +} + +#[cfg(test)] +mod tests; diff --git a/server/crates/arbiter-server/src/evm/policies/token_transfers/tests.rs b/server/crates/arbiter-server/src/evm/policies/token_transfers/tests.rs index ecf79df..7a2f04f 100644 --- a/server/crates/arbiter-server/src/evm/policies/token_transfers/tests.rs +++ b/server/crates/arbiter-server/src/evm/policies/token_transfers/tests.rs @@ -1,514 +1,514 @@ -use super::{Settings, TokenTransfer}; -use crate::{ - db::{ - self, DatabaseConnection, - models::{EvmBasicGrant, EvmWalletAccess, NewEvmBasicGrant, SqliteTimestamp}, - schema::evm_basic_grant, - }, - evm::{ - abi::IERC20::transferCall, - policies::{ - CombinedSettings, EvalContext, EvalViolation, Grant, Policy, SharedGrantSettings, - VolumeRateLimit, - }, - utils, - }, -}; - -use alloy::{ - primitives::{Address, Bytes, U256, address}, - sol_types::SolCall, -}; -use chrono::{Duration, Utc}; -use diesel::{SelectableHelper, insert_into}; -use diesel_async::RunQueryDsl; - -// DAI on Ethereum mainnet — present in the static token registry -const CHAIN_ID: u64 = 1; -const DAI: Address = address!("6B175474E89094C44Da98b954EedeAC495271d0F"); - -const WALLET_ACCESS_ID: i32 = 1; - -const RECIPIENT: Address = address!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); -const OTHER: Address = address!("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); -const UNKNOWN_TOKEN: Address = address!("cccccccccccccccccccccccccccccccccccccccc"); - -/// Encode `transfer(to, value)` raw params (no 4-byte selector). -/// `abi_decode_raw_validate` expects exactly this format. -fn transfer_calldata(to: Address, value: U256) -> Bytes { - let mut raw = Vec::new(); - transferCall { to, value }.abi_encode_raw(&mut raw); - Bytes::from(raw) -} - -fn ctx(to: Address, calldata: Bytes) -> EvalContext { - EvalContext { - target: EvmWalletAccess { - id: WALLET_ACCESS_ID, - wallet_id: 10, - client_id: 20, - created_at: SqliteTimestamp(Utc::now()), - }, - chain: CHAIN_ID, - to, - value: U256::ZERO, - calldata, - max_fee_per_gas: 0, - max_priority_fee_per_gas: 0, - } -} - -async fn insert_basic(conn: &mut DatabaseConnection, revoked: bool) -> EvmBasicGrant { - insert_into(evm_basic_grant::table) - .values(NewEvmBasicGrant { - wallet_access_id: WALLET_ACCESS_ID, - chain_id: CHAIN_ID.into(), - valid_from: None, - valid_until: None, - max_gas_fee_per_gas: None, - max_priority_fee_per_gas: None, - rate_limit_count: None, - rate_limit_window_secs: None, - revoked_at: revoked.then(|| SqliteTimestamp(Utc::now())), - }) - .returning(EvmBasicGrant::as_select()) - .get_result(conn) - .await - .unwrap() -} - -fn make_settings(target: Option
, max_volume: Option) -> Settings { - Settings { - token_contract: DAI, - target, - volume_limits: max_volume - .map(|v| { - vec![VolumeRateLimit { - max_volume: U256::from(v), - window: Duration::hours(1), - }] - }) - .unwrap_or_default(), - } -} - -fn shared() -> SharedGrantSettings { - SharedGrantSettings { - wallet_access_id: WALLET_ACCESS_ID, - chain: CHAIN_ID, - valid_from: None, - valid_until: None, - revoked_at: None, - max_gas_fee_per_gas: None, - max_priority_fee_per_gas: None, - rate_limit: None, - } -} - -#[test] -fn analyze_known_token_valid_calldata() { - let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); - let m = TokenTransfer::analyze(&ctx(DAI, calldata)).unwrap(); - assert_eq!(m.to, RECIPIENT); - assert_eq!(m.value, U256::from(100u64)); -} - -#[test] -fn analyze_unknown_token_returns_none() { - let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); - assert!(TokenTransfer::analyze(&ctx(UNKNOWN_TOKEN, calldata)).is_none()); -} - -#[test] -fn analyze_invalid_calldata_returns_none() { - let calldata = Bytes::from(vec![0xde, 0xad, 0xbe, 0xef]); - assert!(TokenTransfer::analyze(&ctx(DAI, calldata)).is_none()); -} - -#[test] -fn analyze_empty_calldata_returns_none() { - assert!(TokenTransfer::analyze(&ctx(DAI, Bytes::new())).is_none()); -} - -#[tokio::test] -async fn evaluate_rejects_nonzero_eth_value() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let grant = Grant { - id: 999, - common_settings_id: 999, - settings: CombinedSettings { - shared: shared(), - specific: make_settings(None, None), - }, - }; - let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); - let mut context = ctx(DAI, calldata); - context.value = U256::from(1u64); // ETH attached to an ERC-20 call - - let m = TokenTransfer::analyze(&EvalContext { - value: U256::ZERO, - ..context.clone() - }) - .unwrap(); - let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!( - v.iter() - .any(|e| matches!(e, EvalViolation::InvalidTransactionType)) - ); -} - -#[tokio::test] -async fn evaluate_passes_any_recipient_when_no_restriction() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let grant = Grant { - id: 999, - common_settings_id: 999, - settings: CombinedSettings { - shared: shared(), - specific: make_settings(None, None), - }, - }; - let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); - let context = ctx(DAI, calldata); - let m = TokenTransfer::analyze(&context).unwrap(); - let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!(v.is_empty()); -} - -#[tokio::test] -async fn evaluate_passes_matching_restricted_recipient() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let grant = Grant { - id: 999, - common_settings_id: 999, - settings: CombinedSettings { - shared: shared(), - specific: make_settings(Some(RECIPIENT), None), - }, - }; - let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); - let context = ctx(DAI, calldata); - let m = TokenTransfer::analyze(&context).unwrap(); - let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!(v.is_empty()); -} - -#[tokio::test] -async fn evaluate_rejects_wrong_restricted_recipient() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let grant = Grant { - id: 999, - common_settings_id: 999, - settings: CombinedSettings { - shared: shared(), - specific: make_settings(Some(RECIPIENT), None), - }, - }; - let calldata = transfer_calldata(OTHER, U256::from(100u64)); - let context = ctx(DAI, calldata); - let m = TokenTransfer::analyze(&context).unwrap(); - let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!( - v.iter() - .any(|e| matches!(e, EvalViolation::InvalidTarget { .. })) - ); -} - -#[tokio::test] -async fn evaluate_passes_volume_at_exact_limit() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(None, Some(1_000)); - let grant_id = TokenTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - // Record a past transfer of 900, with current transfer 100 => exactly 1000 limit - insert_into(db::schema::evm_token_transfer_log::table) - .values(db::models::NewEvmTokenTransferLog { - grant_id, - log_id: 0, - chain_id: CHAIN_ID.into(), - token_contract: DAI.to_vec(), - recipient_address: RECIPIENT.to_vec(), - value: utils::u256_to_bytes(U256::from(900u64)).to_vec(), - }) - .execute(&mut *conn) - .await - .unwrap(); - - let grant = Grant { - id: grant_id, - common_settings_id: basic.id, - settings: CombinedSettings { - shared: shared(), - specific: settings, - }, - }; - let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); - let context = ctx(DAI, calldata); - let m = TokenTransfer::analyze(&context).unwrap(); - let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!( - !v.iter() - .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) - ); -} - -#[tokio::test] -async fn evaluate_rejects_volume_over_limit() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(None, Some(1_000)); - let grant_id = TokenTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - insert_into(db::schema::evm_token_transfer_log::table) - .values(db::models::NewEvmTokenTransferLog { - grant_id, - log_id: 0, - chain_id: CHAIN_ID.into(), - token_contract: DAI.to_vec(), - recipient_address: RECIPIENT.to_vec(), - value: utils::u256_to_bytes(U256::from(1_000u64)).to_vec(), - }) - .execute(&mut *conn) - .await - .unwrap(); - - let grant = Grant { - id: grant_id, - common_settings_id: basic.id, - settings: CombinedSettings { - shared: shared(), - specific: settings, - }, - }; - let calldata = transfer_calldata(RECIPIENT, U256::from(1u64)); - let context = ctx(DAI, calldata); - let m = TokenTransfer::analyze(&context).unwrap(); - let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!( - v.iter() - .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) - ); -} - -#[tokio::test] -async fn evaluate_no_volume_limits_always_passes() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let grant = Grant { - id: 999, - common_settings_id: 999, - settings: CombinedSettings { - shared: shared(), - specific: make_settings(None, None), // no volume limits - }, - }; - let calldata = transfer_calldata(RECIPIENT, U256::from(u64::MAX)); - let context = ctx(DAI, calldata); - let m = TokenTransfer::analyze(&context).unwrap(); - let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) - .await - .unwrap(); - assert!( - !v.iter() - .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) - ); -} - -// ── try_find_grant ─────────────────────────────────────────────────────── - -#[tokio::test] -async fn try_find_grant_roundtrip() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(Some(RECIPIENT), Some(5_000)); - TokenTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); - let found = TokenTransfer::try_find_grant(&ctx(DAI, calldata), &mut *conn) - .await - .unwrap(); - - assert!(found.is_some()); - let g = found.unwrap(); - assert_eq!(g.settings.specific.token_contract, DAI); - assert_eq!(g.settings.specific.target, Some(RECIPIENT)); - assert_eq!(g.settings.specific.volume_limits.len(), 1); - assert_eq!( - g.settings.specific.volume_limits[0].max_volume, - U256::from(5_000u64) - ); -} - -#[tokio::test] -async fn try_find_grant_revoked_returns_none() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, true).await; - let settings = make_settings(None, None); - TokenTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - let calldata = transfer_calldata(RECIPIENT, U256::from(1u64)); - let found = TokenTransfer::try_find_grant(&ctx(DAI, calldata), &mut *conn) - .await - .unwrap(); - assert!(found.is_none()); -} - -#[tokio::test] -async fn try_find_grant_unknown_token_returns_none() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(None, None); - TokenTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - // Query with a different token contract - let calldata = transfer_calldata(RECIPIENT, U256::from(1u64)); - let found = TokenTransfer::try_find_grant(&ctx(UNKNOWN_TOKEN, calldata), &mut *conn) - .await - .unwrap(); - assert!(found.is_none()); -} - -proptest::proptest! { - #[test] - fn volume_limits_order_does_not_affect_hash( - raw_limits in proptest::collection::vec( - (proptest::prelude::any::(), 1i64..=86400), - 0..8, - ), - seed in proptest::prelude::any::(), - ) { - use rand::{SeedableRng, seq::SliceRandom}; - use sha2::Digest; - use arbiter_crypto::hashing::Hashable; - - let limits: Vec = raw_limits - .iter() - .map(|(max_vol, window_secs)| VolumeRateLimit { - max_volume: U256::from(*max_vol), - window: Duration::seconds(*window_secs), - }) - .collect(); - - let mut shuffled = limits.clone(); - shuffled.shuffle(&mut rand::rngs::StdRng::seed_from_u64(seed)); - - let mut h1 = sha2::Sha256::new(); - Settings { token_contract: DAI, target: None, volume_limits: limits }.hash(&mut h1); - - let mut h2 = sha2::Sha256::new(); - Settings { token_contract: DAI, target: None, volume_limits: shuffled }.hash(&mut h2); - - proptest::prop_assert_eq!(h1.finalize(), h2.finalize()); - } -} - -#[tokio::test] -async fn find_all_grants_empty_db() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - let all = TokenTransfer::find_all_grants(&mut *conn).await.unwrap(); - assert!(all.is_empty()); -} - -#[tokio::test] -async fn find_all_grants_excludes_revoked() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let settings = make_settings(None, Some(1_000)); - let active = insert_basic(&mut conn, false).await; - TokenTransfer::create_grant(&active, &settings, &mut *conn) - .await - .unwrap(); - let revoked = insert_basic(&mut conn, true).await; - TokenTransfer::create_grant(&revoked, &settings, &mut *conn) - .await - .unwrap(); - - let all = TokenTransfer::find_all_grants(&mut *conn).await.unwrap(); - assert_eq!(all.len(), 1); -} - -#[tokio::test] -async fn find_all_grants_loads_volume_limits() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let basic = insert_basic(&mut conn, false).await; - let settings = make_settings(None, Some(9_999)); - TokenTransfer::create_grant(&basic, &settings, &mut *conn) - .await - .unwrap(); - - let all = TokenTransfer::find_all_grants(&mut *conn).await.unwrap(); - assert_eq!(all.len(), 1); - assert_eq!(all[0].settings.specific.volume_limits.len(), 1); - assert_eq!( - all[0].settings.specific.volume_limits[0].max_volume, - U256::from(9_999u64) - ); -} - -#[tokio::test] -async fn find_all_grants_multiple_grants_batch_loaded() { - let db = db::create_test_pool().await; - let mut conn = db.get().await.unwrap(); - - let b1 = insert_basic(&mut conn, false).await; - TokenTransfer::create_grant(&b1, &make_settings(None, Some(1_000)), &mut *conn) - .await - .unwrap(); - let b2 = insert_basic(&mut conn, false).await; - TokenTransfer::create_grant( - &b2, - &make_settings(Some(RECIPIENT), Some(2_000)), - &mut *conn, - ) - .await - .unwrap(); - - let all = TokenTransfer::find_all_grants(&mut *conn).await.unwrap(); - assert_eq!(all.len(), 2); -} +use super::{Settings, TokenTransfer}; +use crate::{ + db::{ + self, DatabaseConnection, + models::{EvmBasicGrant, EvmWalletAccess, NewEvmBasicGrant, SqliteTimestamp}, + schema::evm_basic_grant, + }, + evm::{ + abi::IERC20::transferCall, + policies::{ + CombinedSettings, EvalContext, EvalViolation, Grant, Policy, SharedGrantSettings, + VolumeRateLimit, + }, + utils, + }, +}; + +use alloy::{ + primitives::{Address, Bytes, U256, address}, + sol_types::SolCall, +}; +use chrono::{Duration, Utc}; +use diesel::{SelectableHelper, insert_into}; +use diesel_async::RunQueryDsl; + +// DAI on Ethereum mainnet — present in the static token registry +const CHAIN_ID: u64 = 1; +const DAI: Address = address!("6B175474E89094C44Da98b954EedeAC495271d0F"); + +const WALLET_ACCESS_ID: i32 = 1; + +const RECIPIENT: Address = address!("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); +const OTHER: Address = address!("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); +const UNKNOWN_TOKEN: Address = address!("cccccccccccccccccccccccccccccccccccccccc"); + +/// Encode `transfer(to, value)` raw params (no 4-byte selector). +/// `abi_decode_raw_validate` expects exactly this format. +fn transfer_calldata(to: Address, value: U256) -> Bytes { + let mut raw = Vec::new(); + transferCall { to, value }.abi_encode_raw(&mut raw); + Bytes::from(raw) +} + +fn ctx(to: Address, calldata: Bytes) -> EvalContext { + EvalContext { + target: EvmWalletAccess { + id: WALLET_ACCESS_ID, + wallet_id: 10, + client_id: 20, + created_at: SqliteTimestamp(Utc::now()), + }, + chain: CHAIN_ID, + to, + value: U256::ZERO, + calldata, + max_fee_per_gas: 0, + max_priority_fee_per_gas: 0, + } +} + +async fn insert_basic(conn: &mut DatabaseConnection, revoked: bool) -> EvmBasicGrant { + insert_into(evm_basic_grant::table) + .values(NewEvmBasicGrant { + wallet_access_id: WALLET_ACCESS_ID, + chain_id: CHAIN_ID.into(), + valid_from: None, + valid_until: None, + max_gas_fee_per_gas: None, + max_priority_fee_per_gas: None, + rate_limit_count: None, + rate_limit_window_secs: None, + revoked_at: revoked.then(|| SqliteTimestamp(Utc::now())), + }) + .returning(EvmBasicGrant::as_select()) + .get_result(conn) + .await + .unwrap() +} + +fn make_settings(target: Option
, max_volume: Option) -> Settings { + Settings { + token_contract: DAI, + target, + volume_limits: max_volume + .map(|v| { + vec![VolumeRateLimit { + max_volume: U256::from(v), + window: Duration::hours(1), + }] + }) + .unwrap_or_default(), + } +} + +fn shared() -> SharedGrantSettings { + SharedGrantSettings { + wallet_access_id: WALLET_ACCESS_ID, + chain: CHAIN_ID, + valid_from: None, + valid_until: None, + revoked_at: None, + max_gas_fee_per_gas: None, + max_priority_fee_per_gas: None, + rate_limit: None, + } +} + +#[test] +fn analyze_known_token_valid_calldata() { + let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); + let m = TokenTransfer::analyze(&ctx(DAI, calldata)).unwrap(); + assert_eq!(m.to, RECIPIENT); + assert_eq!(m.value, U256::from(100u64)); +} + +#[test] +fn analyze_unknown_token_returns_none() { + let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); + assert!(TokenTransfer::analyze(&ctx(UNKNOWN_TOKEN, calldata)).is_none()); +} + +#[test] +fn analyze_invalid_calldata_returns_none() { + let calldata = Bytes::from(vec![0xde, 0xad, 0xbe, 0xef]); + assert!(TokenTransfer::analyze(&ctx(DAI, calldata)).is_none()); +} + +#[test] +fn analyze_empty_calldata_returns_none() { + assert!(TokenTransfer::analyze(&ctx(DAI, Bytes::new())).is_none()); +} + +#[tokio::test] +async fn evaluate_rejects_nonzero_eth_value() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let grant = Grant { + id: 999, + common_settings_id: 999, + settings: CombinedSettings { + shared: shared(), + specific: make_settings(None, None), + }, + }; + let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); + let mut context = ctx(DAI, calldata); + context.value = U256::from(1u64); // ETH attached to an ERC-20 call + + let m = TokenTransfer::analyze(&EvalContext { + value: U256::ZERO, + ..context.clone() + }) + .unwrap(); + let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!( + v.iter() + .any(|e| matches!(e, EvalViolation::InvalidTransactionType)) + ); +} + +#[tokio::test] +async fn evaluate_passes_any_recipient_when_no_restriction() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let grant = Grant { + id: 999, + common_settings_id: 999, + settings: CombinedSettings { + shared: shared(), + specific: make_settings(None, None), + }, + }; + let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); + let context = ctx(DAI, calldata); + let m = TokenTransfer::analyze(&context).unwrap(); + let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!(v.is_empty()); +} + +#[tokio::test] +async fn evaluate_passes_matching_restricted_recipient() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let grant = Grant { + id: 999, + common_settings_id: 999, + settings: CombinedSettings { + shared: shared(), + specific: make_settings(Some(RECIPIENT), None), + }, + }; + let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); + let context = ctx(DAI, calldata); + let m = TokenTransfer::analyze(&context).unwrap(); + let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!(v.is_empty()); +} + +#[tokio::test] +async fn evaluate_rejects_wrong_restricted_recipient() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let grant = Grant { + id: 999, + common_settings_id: 999, + settings: CombinedSettings { + shared: shared(), + specific: make_settings(Some(RECIPIENT), None), + }, + }; + let calldata = transfer_calldata(OTHER, U256::from(100u64)); + let context = ctx(DAI, calldata); + let m = TokenTransfer::analyze(&context).unwrap(); + let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!( + v.iter() + .any(|e| matches!(e, EvalViolation::InvalidTarget { .. })) + ); +} + +#[tokio::test] +async fn evaluate_passes_volume_at_exact_limit() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(None, Some(1_000)); + let grant_id = TokenTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + // Record a past transfer of 900, with current transfer 100 => exactly 1000 limit + insert_into(db::schema::evm_token_transfer_log::table) + .values(db::models::NewEvmTokenTransferLog { + grant_id, + log_id: 0, + chain_id: CHAIN_ID.into(), + token_contract: DAI.to_vec(), + recipient_address: RECIPIENT.to_vec(), + value: utils::u256_to_bytes(U256::from(900u64)).to_vec(), + }) + .execute(&mut *conn) + .await + .unwrap(); + + let grant = Grant { + id: grant_id, + common_settings_id: basic.id, + settings: CombinedSettings { + shared: shared(), + specific: settings, + }, + }; + let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); + let context = ctx(DAI, calldata); + let m = TokenTransfer::analyze(&context).unwrap(); + let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!( + !v.iter() + .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) + ); +} + +#[tokio::test] +async fn evaluate_rejects_volume_over_limit() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(None, Some(1_000)); + let grant_id = TokenTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + insert_into(db::schema::evm_token_transfer_log::table) + .values(db::models::NewEvmTokenTransferLog { + grant_id, + log_id: 0, + chain_id: CHAIN_ID.into(), + token_contract: DAI.to_vec(), + recipient_address: RECIPIENT.to_vec(), + value: utils::u256_to_bytes(U256::from(1_000u64)).to_vec(), + }) + .execute(&mut *conn) + .await + .unwrap(); + + let grant = Grant { + id: grant_id, + common_settings_id: basic.id, + settings: CombinedSettings { + shared: shared(), + specific: settings, + }, + }; + let calldata = transfer_calldata(RECIPIENT, U256::from(1u64)); + let context = ctx(DAI, calldata); + let m = TokenTransfer::analyze(&context).unwrap(); + let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!( + v.iter() + .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) + ); +} + +#[tokio::test] +async fn evaluate_no_volume_limits_always_passes() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let grant = Grant { + id: 999, + common_settings_id: 999, + settings: CombinedSettings { + shared: shared(), + specific: make_settings(None, None), // no volume limits + }, + }; + let calldata = transfer_calldata(RECIPIENT, U256::from(u64::MAX)); + let context = ctx(DAI, calldata); + let m = TokenTransfer::analyze(&context).unwrap(); + let v = TokenTransfer::evaluate(&context, &m, &grant, &mut *conn) + .await + .unwrap(); + assert!( + !v.iter() + .any(|e| matches!(e, EvalViolation::VolumetricLimitExceeded)) + ); +} + +// ── try_find_grant ─────────────────────────────────────────────────────── + +#[tokio::test] +async fn try_find_grant_roundtrip() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(Some(RECIPIENT), Some(5_000)); + TokenTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + let calldata = transfer_calldata(RECIPIENT, U256::from(100u64)); + let found = TokenTransfer::try_find_grant(&ctx(DAI, calldata), &mut *conn) + .await + .unwrap(); + + assert!(found.is_some()); + let g = found.unwrap(); + assert_eq!(g.settings.specific.token_contract, DAI); + assert_eq!(g.settings.specific.target, Some(RECIPIENT)); + assert_eq!(g.settings.specific.volume_limits.len(), 1); + assert_eq!( + g.settings.specific.volume_limits[0].max_volume, + U256::from(5_000u64) + ); +} + +#[tokio::test] +async fn try_find_grant_revoked_returns_none() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, true).await; + let settings = make_settings(None, None); + TokenTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + let calldata = transfer_calldata(RECIPIENT, U256::from(1u64)); + let found = TokenTransfer::try_find_grant(&ctx(DAI, calldata), &mut *conn) + .await + .unwrap(); + assert!(found.is_none()); +} + +#[tokio::test] +async fn try_find_grant_unknown_token_returns_none() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(None, None); + TokenTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + // Query with a different token contract + let calldata = transfer_calldata(RECIPIENT, U256::from(1u64)); + let found = TokenTransfer::try_find_grant(&ctx(UNKNOWN_TOKEN, calldata), &mut *conn) + .await + .unwrap(); + assert!(found.is_none()); +} + +proptest::proptest! { + #[test] + fn volume_limits_order_does_not_affect_hash( + raw_limits in proptest::collection::vec( + (proptest::prelude::any::(), 1i64..=86400), + 0..8, + ), + seed in proptest::prelude::any::(), + ) { + use rand::{SeedableRng, seq::SliceRandom}; + use sha2::Digest; + use arbiter_crypto::hashing::Hashable; + + let limits: Vec = raw_limits + .iter() + .map(|(max_vol, window_secs)| VolumeRateLimit { + max_volume: U256::from(*max_vol), + window: Duration::seconds(*window_secs), + }) + .collect(); + + let mut shuffled = limits.clone(); + shuffled.shuffle(&mut rand::rngs::StdRng::seed_from_u64(seed)); + + let mut h1 = sha2::Sha256::new(); + Settings { token_contract: DAI, target: None, volume_limits: limits }.hash(&mut h1); + + let mut h2 = sha2::Sha256::new(); + Settings { token_contract: DAI, target: None, volume_limits: shuffled }.hash(&mut h2); + + proptest::prop_assert_eq!(h1.finalize(), h2.finalize()); + } +} + +#[tokio::test] +async fn find_all_grants_empty_db() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + let all = TokenTransfer::find_all_grants(&mut *conn).await.unwrap(); + assert!(all.is_empty()); +} + +#[tokio::test] +async fn find_all_grants_excludes_revoked() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let settings = make_settings(None, Some(1_000)); + let active = insert_basic(&mut conn, false).await; + TokenTransfer::create_grant(&active, &settings, &mut *conn) + .await + .unwrap(); + let revoked = insert_basic(&mut conn, true).await; + TokenTransfer::create_grant(&revoked, &settings, &mut *conn) + .await + .unwrap(); + + let all = TokenTransfer::find_all_grants(&mut *conn).await.unwrap(); + assert_eq!(all.len(), 1); +} + +#[tokio::test] +async fn find_all_grants_loads_volume_limits() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let basic = insert_basic(&mut conn, false).await; + let settings = make_settings(None, Some(9_999)); + TokenTransfer::create_grant(&basic, &settings, &mut *conn) + .await + .unwrap(); + + let all = TokenTransfer::find_all_grants(&mut *conn).await.unwrap(); + assert_eq!(all.len(), 1); + assert_eq!(all[0].settings.specific.volume_limits.len(), 1); + assert_eq!( + all[0].settings.specific.volume_limits[0].max_volume, + U256::from(9_999u64) + ); +} + +#[tokio::test] +async fn find_all_grants_multiple_grants_batch_loaded() { + let db = db::create_test_pool().await; + let mut conn = db.get().await.unwrap(); + + let b1 = insert_basic(&mut conn, false).await; + TokenTransfer::create_grant(&b1, &make_settings(None, Some(1_000)), &mut *conn) + .await + .unwrap(); + let b2 = insert_basic(&mut conn, false).await; + TokenTransfer::create_grant( + &b2, + &make_settings(Some(RECIPIENT), Some(2_000)), + &mut *conn, + ) + .await + .unwrap(); + + let all = TokenTransfer::find_all_grants(&mut *conn).await.unwrap(); + assert_eq!(all.len(), 2); +} diff --git a/server/crates/arbiter-server/src/evm/safe_signer.rs b/server/crates/arbiter-server/src/evm/safe_signer.rs index 02597a8..c996bd2 100644 --- a/server/crates/arbiter-server/src/evm/safe_signer.rs +++ b/server/crates/arbiter-server/src/evm/safe_signer.rs @@ -1,194 +1,194 @@ -use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; - -use alloy::{ - consensus::SignableTransaction, - network::{TxSigner, TxSignerSync}, - primitives::{Address, B256, ChainId, Signature}, - signers::{Error, Result, Signer, SignerSync, utils::secret_key_to_address}, -}; -use async_trait::async_trait; -use k256::ecdsa::{self, RecoveryId, SigningKey, signature::hazmat::PrehashSigner}; -use std::sync::Mutex; - -/// An Ethereum signer that stores its secp256k1 secret key inside a -/// hardware-protected [`MemSafe`] cell. -/// -/// The underlying memory page is kept non-readable/non-writable at rest. -/// Access is temporarily elevated only for the duration of each signing -/// operation, then immediately revoked. -/// -/// Because [`MemSafe::read`] requires `&mut self` while the [`Signer`] trait -/// requires `&self`, the cell is wrapped in a [`Mutex`]. -pub struct SafeSigner { - key: Mutex>, - address: Address, - chain_id: Option, -} - -impl std::fmt::Debug for SafeSigner { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("SafeSigner") - .field("address", &self.address) - .field("chain_id", &self.chain_id) - .finish() - } -} - -/// Generates a secp256k1 secret key directly inside a [`MemSafe`] cell. -/// -/// Random bytes are written in-place into protected memory, then validated -/// as a legal scalar on the secp256k1 curve (the scalar must be in -/// `[1, n)` where `n` is the curve order — roughly 1-in-2^128 chance of -/// rejection, but we retry to be correct). -/// -/// Returns the protected key bytes and the derived Ethereum address. -pub fn generate(rng: &mut impl rand::Rng) -> (SafeCell<[u8; 32]>, Address) { - loop { - let mut cell = SafeCell::new_inline(|w: &mut [u8; 32]| { - rng.fill_bytes(w); - }); - - let reader = cell.read(); - if let Ok(sk) = SigningKey::from_slice(reader.as_ref()) { - let address = secret_key_to_address(&sk); - drop(reader); - return (cell, address); - } - } -} - -impl SafeSigner { - /// Reconstructs a `SafeSigner` from key material held in a [`MemSafe`] buffer. - /// - /// The key bytes are read from protected memory, parsed as a secp256k1 - /// scalar, and immediately moved into a new [`MemSafe`] cell. The raw - /// bytes are never exposed outside this function. - pub fn from_cell(mut cell: SafeCell>) -> Result { - let reader = cell.read(); - let sk = SigningKey::from_slice(reader.as_slice()).map_err(Error::other)?; - drop(reader); - Self::new(sk) - } - - /// Creates a new `SafeSigner` by moving the signing key into a protected - /// memory region. - pub fn new(key: SigningKey) -> Result { - let address = secret_key_to_address(&key); - let cell = SafeCell::new(key); - Ok(Self { - key: Mutex::new(cell), - address, - chain_id: None, - }) - } - - #[expect(clippy::significant_drop_tightening, reason = "false positive")] - fn sign_hash_inner(&self, hash: &B256) -> Result { - let mut cell = self.key.lock().expect("SafeSigner mutex poisoned"); - let reader = cell.read(); - let sig: (ecdsa::Signature, RecoveryId) = reader.sign_prehash(hash.as_ref())?; - Ok(sig.into()) - } - - fn sign_tx_inner(&self, tx: &mut dyn SignableTransaction) -> Result { - if let Some(chain_id) = self.chain_id - && !tx.set_chain_id_checked(chain_id) - { - return Err(Error::TransactionChainIdMismatch { - signer: chain_id, - tx: tx.chain_id().expect("Chain ID is guaranteed to be set"), - }); - } - self.sign_hash_inner(&tx.signature_hash()) - .map_err(Error::other) - } -} - -#[async_trait] -impl Signer for SafeSigner { - #[inline] - async fn sign_hash(&self, hash: &B256) -> Result { - self.sign_hash_inner(hash) - } - - #[inline] - fn address(&self) -> Address { - self.address - } - - #[inline] - fn chain_id(&self) -> Option { - self.chain_id - } - - #[inline] - fn set_chain_id(&mut self, chain_id: Option) { - self.chain_id = chain_id; - } -} - -impl SignerSync for SafeSigner { - #[inline] - fn sign_hash_sync(&self, hash: &B256) -> Result { - self.sign_hash_inner(hash) - } - - #[inline] - fn chain_id_sync(&self) -> Option { - self.chain_id - } -} - -#[async_trait] -impl TxSigner for SafeSigner { - fn address(&self) -> Address { - self.address - } - - async fn sign_transaction( - &self, - tx: &mut dyn SignableTransaction, - ) -> Result { - self.sign_tx_inner(tx) - } -} - -impl TxSignerSync for SafeSigner { - fn address(&self) -> Address { - self.address - } - - fn sign_transaction_sync( - &self, - tx: &mut dyn SignableTransaction, - ) -> Result { - self.sign_tx_inner(tx) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use alloy::signers::local::PrivateKeySigner; - - #[test] - fn sign_and_recover() { - let pk = PrivateKeySigner::random(); - let key = pk.into_credential(); - let signer = SafeSigner::new(key).unwrap(); - let message = b"hello arbiter"; - let sig = signer.sign_message_sync(message).unwrap(); - let recovered = sig.recover_address_from_msg(message).unwrap(); - assert_eq!(recovered, Signer::address(&signer)); - } - - #[test] - fn chain_id_roundtrip() { - let pk = PrivateKeySigner::random(); - let key = pk.into_credential(); - let mut signer = SafeSigner::new(key).unwrap(); - assert_eq!(Signer::chain_id(&signer), None); - signer.set_chain_id(Some(1337)); - assert_eq!(Signer::chain_id(&signer), Some(1337)); - } -} +use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; + +use alloy::{ + consensus::SignableTransaction, + network::{TxSigner, TxSignerSync}, + primitives::{Address, B256, ChainId, Signature}, + signers::{Error, Result, Signer, SignerSync, utils::secret_key_to_address}, +}; +use async_trait::async_trait; +use k256::ecdsa::{self, RecoveryId, SigningKey, signature::hazmat::PrehashSigner}; +use std::sync::Mutex; + +/// An Ethereum signer that stores its secp256k1 secret key inside a +/// hardware-protected [`MemSafe`] cell. +/// +/// The underlying memory page is kept non-readable/non-writable at rest. +/// Access is temporarily elevated only for the duration of each signing +/// operation, then immediately revoked. +/// +/// Because [`MemSafe::read`] requires `&mut self` while the [`Signer`] trait +/// requires `&self`, the cell is wrapped in a [`Mutex`]. +pub struct SafeSigner { + key: Mutex>, + address: Address, + chain_id: Option, +} + +impl std::fmt::Debug for SafeSigner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("SafeSigner") + .field("address", &self.address) + .field("chain_id", &self.chain_id) + .finish() + } +} + +/// Generates a secp256k1 secret key directly inside a [`MemSafe`] cell. +/// +/// Random bytes are written in-place into protected memory, then validated +/// as a legal scalar on the secp256k1 curve (the scalar must be in +/// `[1, n)` where `n` is the curve order — roughly 1-in-2^128 chance of +/// rejection, but we retry to be correct). +/// +/// Returns the protected key bytes and the derived Ethereum address. +pub fn generate(rng: &mut impl rand::Rng) -> (SafeCell<[u8; 32]>, Address) { + loop { + let mut cell = SafeCell::new_inline(|w: &mut [u8; 32]| { + rng.fill_bytes(w); + }); + + let reader = cell.read(); + if let Ok(sk) = SigningKey::from_slice(reader.as_ref()) { + let address = secret_key_to_address(&sk); + drop(reader); + return (cell, address); + } + } +} + +impl SafeSigner { + /// Reconstructs a `SafeSigner` from key material held in a [`MemSafe`] buffer. + /// + /// The key bytes are read from protected memory, parsed as a secp256k1 + /// scalar, and immediately moved into a new [`MemSafe`] cell. The raw + /// bytes are never exposed outside this function. + pub fn from_cell(mut cell: SafeCell>) -> Result { + let reader = cell.read(); + let sk = SigningKey::from_slice(reader.as_slice()).map_err(Error::other)?; + drop(reader); + Self::new(sk) + } + + /// Creates a new `SafeSigner` by moving the signing key into a protected + /// memory region. + pub fn new(key: SigningKey) -> Result { + let address = secret_key_to_address(&key); + let cell = SafeCell::new(key); + Ok(Self { + key: Mutex::new(cell), + address, + chain_id: None, + }) + } + + #[expect(clippy::significant_drop_tightening, reason = "false positive")] + fn sign_hash_inner(&self, hash: &B256) -> Result { + let mut cell = self.key.lock().expect("SafeSigner mutex poisoned"); + let reader = cell.read(); + let sig: (ecdsa::Signature, RecoveryId) = reader.sign_prehash(hash.as_ref())?; + Ok(sig.into()) + } + + fn sign_tx_inner(&self, tx: &mut dyn SignableTransaction) -> Result { + if let Some(chain_id) = self.chain_id + && !tx.set_chain_id_checked(chain_id) + { + return Err(Error::TransactionChainIdMismatch { + signer: chain_id, + tx: tx.chain_id().expect("Chain ID is guaranteed to be set"), + }); + } + self.sign_hash_inner(&tx.signature_hash()) + .map_err(Error::other) + } +} + +#[async_trait] +impl Signer for SafeSigner { + #[inline] + async fn sign_hash(&self, hash: &B256) -> Result { + self.sign_hash_inner(hash) + } + + #[inline] + fn address(&self) -> Address { + self.address + } + + #[inline] + fn chain_id(&self) -> Option { + self.chain_id + } + + #[inline] + fn set_chain_id(&mut self, chain_id: Option) { + self.chain_id = chain_id; + } +} + +impl SignerSync for SafeSigner { + #[inline] + fn sign_hash_sync(&self, hash: &B256) -> Result { + self.sign_hash_inner(hash) + } + + #[inline] + fn chain_id_sync(&self) -> Option { + self.chain_id + } +} + +#[async_trait] +impl TxSigner for SafeSigner { + fn address(&self) -> Address { + self.address + } + + async fn sign_transaction( + &self, + tx: &mut dyn SignableTransaction, + ) -> Result { + self.sign_tx_inner(tx) + } +} + +impl TxSignerSync for SafeSigner { + fn address(&self) -> Address { + self.address + } + + fn sign_transaction_sync( + &self, + tx: &mut dyn SignableTransaction, + ) -> Result { + self.sign_tx_inner(tx) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use alloy::signers::local::PrivateKeySigner; + + #[test] + fn sign_and_recover() { + let pk = PrivateKeySigner::random(); + let key = pk.into_credential(); + let signer = SafeSigner::new(key).unwrap(); + let message = b"hello arbiter"; + let sig = signer.sign_message_sync(message).unwrap(); + let recovered = sig.recover_address_from_msg(message).unwrap(); + assert_eq!(recovered, Signer::address(&signer)); + } + + #[test] + fn chain_id_roundtrip() { + let pk = PrivateKeySigner::random(); + let key = pk.into_credential(); + let mut signer = SafeSigner::new(key).unwrap(); + assert_eq!(Signer::chain_id(&signer), None); + signer.set_chain_id(Some(1337)); + assert_eq!(Signer::chain_id(&signer), Some(1337)); + } +} diff --git a/server/crates/arbiter-server/src/evm/utils.rs b/server/crates/arbiter-server/src/evm/utils.rs index 2d8a14a..aa53b41 100644 --- a/server/crates/arbiter-server/src/evm/utils.rs +++ b/server/crates/arbiter-server/src/evm/utils.rs @@ -1,26 +1,26 @@ -use alloy::primitives::U256; - -#[derive(thiserror::Error, Debug)] -#[error("Expected {expected} bytes but got {actual} bytes")] -pub(super) struct LengthError { - pub(super) expected: usize, - pub(super) actual: usize, -} - -pub const fn u256_to_bytes(value: U256) -> [u8; 32] { - value.to_le_bytes() -} -pub(super) fn bytes_to_u256(bytes: &[u8]) -> Option { - let bytes: [u8; 32] = bytes.try_into().ok()?; - Some(U256::from_le_bytes(bytes)) -} - -pub(super) fn try_bytes_to_u256(bytes: &[u8]) -> diesel::result::QueryResult { - let bytes: [u8; 32] = bytes.try_into().map_err(|_| { - diesel::result::Error::DeserializationError(Box::new(LengthError { - expected: 32, - actual: bytes.len(), - })) - })?; - Ok(U256::from_le_bytes(bytes)) -} +use alloy::primitives::U256; + +#[derive(thiserror::Error, Debug)] +#[error("Expected {expected} bytes but got {actual} bytes")] +pub(super) struct LengthError { + pub(super) expected: usize, + pub(super) actual: usize, +} + +pub const fn u256_to_bytes(value: U256) -> [u8; 32] { + value.to_le_bytes() +} +pub(super) fn bytes_to_u256(bytes: &[u8]) -> Option { + let bytes: [u8; 32] = bytes.try_into().ok()?; + Some(U256::from_le_bytes(bytes)) +} + +pub(super) fn try_bytes_to_u256(bytes: &[u8]) -> diesel::result::QueryResult { + let bytes: [u8; 32] = bytes.try_into().map_err(|_| { + diesel::result::Error::DeserializationError(Box::new(LengthError { + expected: 32, + actual: bytes.len(), + })) + })?; + Ok(U256::from_le_bytes(bytes)) +} diff --git a/server/crates/arbiter-server/src/grpc/client.rs b/server/crates/arbiter-server/src/grpc/client.rs index 5bce872..4bcd821 100644 --- a/server/crates/arbiter-server/src/grpc/client.rs +++ b/server/crates/arbiter-server/src/grpc/client.rs @@ -1,115 +1,115 @@ -use crate::{ - grpc::request_tracker::RequestTracker, - peers::client::{ClientConnection, session::ClientSession}, -}; -use arbiter_proto::{ - proto::client::{ - ClientRequest, ClientResponse, client_request::Payload as ClientRequestPayload, - client_response::Payload as ClientResponsePayload, - }, - transport::{Receiver, Sender, grpc::GrpcBi}, -}; - -use kameo::actor::{ActorRef, Spawn as _}; -use tonic::Status; -use tracing::{info, warn}; - -mod auth; -mod evm; -mod inbound; -mod outbound; -mod vault; - -async fn dispatch_loop( - mut bi: GrpcBi, - actor: ActorRef, - mut request_tracker: RequestTracker, -) { - loop { - let Some(message) = bi.recv().await else { - return; - }; - - let conn = match message { - Ok(conn) => conn, - Err(err) => { - warn!(error = ?err, "Failed to receive client request"); - return; - } - }; - - let request_id = match request_tracker.request(conn.request_id) { - Ok(id) => id, - Err(err) => { - let _ = bi.send(Err(err)).await; - return; - } - }; - - let Some(payload) = conn.payload else { - let _ = bi - .send(Err(Status::invalid_argument( - "Missing client request payload", - ))) - .await; - return; - }; - - match dispatch_inner(&actor, payload).await { - Ok(response) => { - if bi - .send(Ok(ClientResponse { - request_id: Some(request_id), - payload: Some(response), - })) - .await - .is_err() - { - return; - } - } - Err(status) => { - let _ = bi.send(Err(status)).await; - return; - } - } - } -} - -async fn dispatch_inner( - actor: &ActorRef, - payload: ClientRequestPayload, -) -> Result { - match payload { - ClientRequestPayload::Vault(req) => vault::dispatch(actor, req).await, - ClientRequestPayload::Evm(req) => evm::dispatch(actor, req).await, - ClientRequestPayload::Auth(..) => { - warn!("Unsupported post-auth client auth request"); - Err(Status::invalid_argument("Unsupported client request")) - } - } -} - -pub async fn start(mut conn: ClientConnection, mut bi: GrpcBi) { - let mut request_tracker = RequestTracker::default(); - - let client_id = match auth::start(&mut conn, &mut bi, &mut request_tracker).await { - Ok(id) => id, - Err(err) => { - let _ = bi - .send(Err(Status::unauthenticated(format!( - "Authentication failed: {err}", - )))) - .await; - warn!(error = ?err, "Client authentication failed"); - return; - } - }; - - let actor = ClientSession::spawn(ClientSession::new(conn, client_id)); - let actor_for_cleanup = actor.clone(); - - info!("Client authenticated successfully"); - dispatch_loop(bi, actor, request_tracker).await; - actor_for_cleanup.kill(); -} +use crate::{ + grpc::request_tracker::RequestTracker, + peers::client::{ClientConnection, session::ClientSession}, +}; +use arbiter_proto::{ + proto::client::{ + ClientRequest, ClientResponse, client_request::Payload as ClientRequestPayload, + client_response::Payload as ClientResponsePayload, + }, + transport::{Receiver, Sender, grpc::GrpcBi}, +}; + +use kameo::actor::{ActorRef, Spawn as _}; +use tonic::Status; +use tracing::{info, warn}; + +mod auth; +mod evm; +mod inbound; +mod outbound; +mod vault; + +async fn dispatch_loop( + mut bi: GrpcBi, + actor: ActorRef, + mut request_tracker: RequestTracker, +) { + loop { + let Some(message) = bi.recv().await else { + return; + }; + + let conn = match message { + Ok(conn) => conn, + Err(err) => { + warn!(error = ?err, "Failed to receive client request"); + return; + } + }; + + let request_id = match request_tracker.request(conn.request_id) { + Ok(id) => id, + Err(err) => { + let _ = bi.send(Err(err)).await; + return; + } + }; + + let Some(payload) = conn.payload else { + let _ = bi + .send(Err(Status::invalid_argument( + "Missing client request payload", + ))) + .await; + return; + }; + + match dispatch_inner(&actor, payload).await { + Ok(response) => { + if bi + .send(Ok(ClientResponse { + request_id: Some(request_id), + payload: Some(response), + })) + .await + .is_err() + { + return; + } + } + Err(status) => { + let _ = bi.send(Err(status)).await; + return; + } + } + } +} + +async fn dispatch_inner( + actor: &ActorRef, + payload: ClientRequestPayload, +) -> Result { + match payload { + ClientRequestPayload::Vault(req) => vault::dispatch(actor, req).await, + ClientRequestPayload::Evm(req) => evm::dispatch(actor, req).await, + ClientRequestPayload::Auth(..) => { + warn!("Unsupported post-auth client auth request"); + Err(Status::invalid_argument("Unsupported client request")) + } + } +} + +pub async fn start(mut conn: ClientConnection, mut bi: GrpcBi) { + let mut request_tracker = RequestTracker::default(); + + let client_id = match auth::start(&mut conn, &mut bi, &mut request_tracker).await { + Ok(id) => id, + Err(err) => { + let _ = bi + .send(Err(Status::unauthenticated(format!( + "Authentication failed: {err}", + )))) + .await; + warn!(error = ?err, "Client authentication failed"); + return; + } + }; + + let actor = ClientSession::spawn(ClientSession::new(conn, client_id)); + let actor_for_cleanup = actor.clone(); + + info!("Client authenticated successfully"); + dispatch_loop(bi, actor, request_tracker).await; + actor_for_cleanup.kill(); +} diff --git a/server/crates/arbiter-server/src/grpc/client/auth.rs b/server/crates/arbiter-server/src/grpc/client/auth.rs index 2e5375a..677874b 100644 --- a/server/crates/arbiter-server/src/grpc/client/auth.rs +++ b/server/crates/arbiter-server/src/grpc/client/auth.rs @@ -1,219 +1,219 @@ -use crate::{ - grpc::{Convert, request_tracker::RequestTracker}, - peers::client::{ClientConnection, auth}, -}; -use arbiter_crypto::authn; -use arbiter_proto::{ - ClientMetadata, - proto::{ - client::{ - ClientRequest, ClientResponse, - auth::{ - self as proto_auth, AuthChallenge as ProtoAuthChallenge, - AuthChallengeRequest as ProtoAuthChallengeRequest, - AuthChallengeSolution as ProtoAuthChallengeSolution, AuthResult as ProtoAuthResult, - request::Payload as AuthRequestPayload, response::Payload as AuthResponsePayload, - }, - client_request::Payload as ClientRequestPayload, - client_response::Payload as ClientResponsePayload, - }, - shared::ClientInfo as ProtoClientInfo, - }, - transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi}, -}; - -use async_trait::async_trait; -use tonic::Status; -use tracing::warn; - -pub(super) struct AuthTransportAdapter<'a> { - bi: &'a mut GrpcBi, - request_tracker: &'a mut RequestTracker, -} - -impl<'a> AuthTransportAdapter<'a> { - pub(super) const fn new( - bi: &'a mut GrpcBi, - request_tracker: &'a mut RequestTracker, - ) -> Self { - Self { - bi, - request_tracker, - } - } - - async fn send_client_response( - &mut self, - payload: AuthResponsePayload, - ) -> Result<(), TransportError> { - self.bi - .send(Ok(ClientResponse { - request_id: Some(self.request_tracker.current_request_id()), - payload: Some(ClientResponsePayload::Auth(proto_auth::Response { - payload: Some(payload), - })), - })) - .await - } - - async fn send_auth_result(&mut self, result: ProtoAuthResult) -> Result<(), TransportError> { - self.send_client_response(AuthResponsePayload::Result(result.into())) - .await - } -} - -#[async_trait] -impl Sender> for AuthTransportAdapter<'_> { - async fn send( - &mut self, - item: Result, - ) -> Result<(), TransportError> { - let payload = match item { - Ok(message) => message.convert(), - Err(err) => err.convert(), - }; - - self.send_client_response(payload).await - } -} - -#[async_trait] -impl Receiver for AuthTransportAdapter<'_> { - async fn recv(&mut self) -> Option { - let request = match self.bi.recv().await? { - Ok(request) => request, - Err(error) => { - warn!(error = ?error, "grpc client recv failed; closing stream"); - return None; - } - }; - - match self.request_tracker.request(request.request_id) { - Ok(request_id) => request_id, - Err(error) => { - let _ = self.bi.send(Err(error)).await; - return None; - } - }; - let payload = request.payload?; - let ClientRequestPayload::Auth(auth_request) = payload else { - let _ = self - .bi - .send(Err(Status::invalid_argument( - "Unsupported client auth request", - ))) - .await; - return None; - }; - let Some(payload) = auth_request.payload else { - let _ = self - .bi - .send(Err(Status::invalid_argument( - "Missing client auth request payload", - ))) - .await; - return None; - }; - - match payload { - AuthRequestPayload::ChallengeRequest(ProtoAuthChallengeRequest { - pubkey, - client_info, - }) => { - let Some(client_info) = client_info else { - let _ = self - .bi - .send(Err(Status::invalid_argument("Missing client info"))) - .await; - return None; - }; - let Ok(pubkey) = authn::PublicKey::try_from(pubkey.as_slice()) else { - let _ = self.send_auth_result(ProtoAuthResult::InvalidKey).await; - return None; - }; - Some(auth::Inbound::AuthChallengeRequest { - pubkey, - metadata: client_info.convert(), - }) - } - AuthRequestPayload::ChallengeSolution(ProtoAuthChallengeSolution { signature }) => { - let Ok(signature) = authn::Signature::try_from(signature.as_slice()) else { - let _ = self - .send_auth_result(ProtoAuthResult::InvalidSignature) - .await; - return None; - }; - Some(auth::Inbound::AuthChallengeSolution { signature }) - } - } - } -} - -impl Bi> for AuthTransportAdapter<'_> {} - -impl Convert for ProtoClientInfo { - type Output = ClientMetadata; - - fn convert(self) -> Self::Output { - ClientMetadata { - name: self.name, - description: self.description, - version: self.version, - } - } -} - -impl Convert for auth::Error { - type Output = AuthResponsePayload; - - fn convert(self) -> Self::Output { - use auth::Error::{ - ApproveError, DatabaseOperationFailed, DatabasePoolUnavailable, IntegrityCheckFailed, - InvalidChallengeSolution, Transport, - }; - AuthResponsePayload::Result( - match self { - InvalidChallengeSolution => ProtoAuthResult::InvalidSignature, - ApproveError(auth::ApproveError::Denied) => ProtoAuthResult::ApprovalDenied, - ApproveError(auth::ApproveError::Upstream( - crate::actors::flow_coordinator::ApprovalError::NoOperatorsConnected, - )) => ProtoAuthResult::NoOperatorsOnline, - ApproveError(auth::ApproveError::Internal) - | DatabasePoolUnavailable - | DatabaseOperationFailed - | IntegrityCheckFailed - | Transport => ProtoAuthResult::Internal, - } - .into(), - ) - } -} - -impl Convert for auth::Outbound { - type Output = AuthResponsePayload; - - fn convert(self) -> Self::Output { - match self { - Self::AuthChallenge { challenge } => { - AuthResponsePayload::Challenge(ProtoAuthChallenge { - timestamp_nanos: challenge - .timestamp - .timestamp_nanos_opt() - .expect("timestamp within range") - .cast_unsigned(), - random: challenge.nonce.to_vec(), - }) - } - Self::AuthSuccess => AuthResponsePayload::Result(ProtoAuthResult::Success.into()), - } - } -} - -pub(super) async fn start( - conn: &mut ClientConnection, - bi: &mut GrpcBi, - request_tracker: &mut RequestTracker, -) -> Result { - let mut transport = AuthTransportAdapter::new(bi, request_tracker); - auth::authenticate(conn, &mut transport).await -} +use crate::{ + grpc::{Convert, request_tracker::RequestTracker}, + peers::client::{ClientConnection, auth}, +}; +use arbiter_crypto::authn; +use arbiter_proto::{ + ClientMetadata, + proto::{ + client::{ + ClientRequest, ClientResponse, + auth::{ + self as proto_auth, AuthChallenge as ProtoAuthChallenge, + AuthChallengeRequest as ProtoAuthChallengeRequest, + AuthChallengeSolution as ProtoAuthChallengeSolution, AuthResult as ProtoAuthResult, + request::Payload as AuthRequestPayload, response::Payload as AuthResponsePayload, + }, + client_request::Payload as ClientRequestPayload, + client_response::Payload as ClientResponsePayload, + }, + shared::ClientInfo as ProtoClientInfo, + }, + transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi}, +}; + +use async_trait::async_trait; +use tonic::Status; +use tracing::warn; + +pub(super) struct AuthTransportAdapter<'a> { + bi: &'a mut GrpcBi, + request_tracker: &'a mut RequestTracker, +} + +impl<'a> AuthTransportAdapter<'a> { + pub(super) const fn new( + bi: &'a mut GrpcBi, + request_tracker: &'a mut RequestTracker, + ) -> Self { + Self { + bi, + request_tracker, + } + } + + async fn send_client_response( + &mut self, + payload: AuthResponsePayload, + ) -> Result<(), TransportError> { + self.bi + .send(Ok(ClientResponse { + request_id: Some(self.request_tracker.current_request_id()), + payload: Some(ClientResponsePayload::Auth(proto_auth::Response { + payload: Some(payload), + })), + })) + .await + } + + async fn send_auth_result(&mut self, result: ProtoAuthResult) -> Result<(), TransportError> { + self.send_client_response(AuthResponsePayload::Result(result.into())) + .await + } +} + +#[async_trait] +impl Sender> for AuthTransportAdapter<'_> { + async fn send( + &mut self, + item: Result, + ) -> Result<(), TransportError> { + let payload = match item { + Ok(message) => message.convert(), + Err(err) => err.convert(), + }; + + self.send_client_response(payload).await + } +} + +#[async_trait] +impl Receiver for AuthTransportAdapter<'_> { + async fn recv(&mut self) -> Option { + let request = match self.bi.recv().await? { + Ok(request) => request, + Err(error) => { + warn!(error = ?error, "grpc client recv failed; closing stream"); + return None; + } + }; + + match self.request_tracker.request(request.request_id) { + Ok(request_id) => request_id, + Err(error) => { + let _ = self.bi.send(Err(error)).await; + return None; + } + }; + let payload = request.payload?; + let ClientRequestPayload::Auth(auth_request) = payload else { + let _ = self + .bi + .send(Err(Status::invalid_argument( + "Unsupported client auth request", + ))) + .await; + return None; + }; + let Some(payload) = auth_request.payload else { + let _ = self + .bi + .send(Err(Status::invalid_argument( + "Missing client auth request payload", + ))) + .await; + return None; + }; + + match payload { + AuthRequestPayload::ChallengeRequest(ProtoAuthChallengeRequest { + pubkey, + client_info, + }) => { + let Some(client_info) = client_info else { + let _ = self + .bi + .send(Err(Status::invalid_argument("Missing client info"))) + .await; + return None; + }; + let Ok(pubkey) = authn::PublicKey::try_from(pubkey.as_slice()) else { + let _ = self.send_auth_result(ProtoAuthResult::InvalidKey).await; + return None; + }; + Some(auth::Inbound::AuthChallengeRequest { + pubkey, + metadata: client_info.convert(), + }) + } + AuthRequestPayload::ChallengeSolution(ProtoAuthChallengeSolution { signature }) => { + let Ok(signature) = authn::Signature::try_from(signature.as_slice()) else { + let _ = self + .send_auth_result(ProtoAuthResult::InvalidSignature) + .await; + return None; + }; + Some(auth::Inbound::AuthChallengeSolution { signature }) + } + } + } +} + +impl Bi> for AuthTransportAdapter<'_> {} + +impl Convert for ProtoClientInfo { + type Output = ClientMetadata; + + fn convert(self) -> Self::Output { + ClientMetadata { + name: self.name, + description: self.description, + version: self.version, + } + } +} + +impl Convert for auth::Error { + type Output = AuthResponsePayload; + + fn convert(self) -> Self::Output { + use auth::Error::{ + ApproveError, DatabaseOperationFailed, DatabasePoolUnavailable, IntegrityCheckFailed, + InvalidChallengeSolution, Transport, + }; + AuthResponsePayload::Result( + match self { + InvalidChallengeSolution => ProtoAuthResult::InvalidSignature, + ApproveError(auth::ApproveError::Denied) => ProtoAuthResult::ApprovalDenied, + ApproveError(auth::ApproveError::Upstream( + crate::actors::flow_coordinator::ApprovalError::NoOperatorsConnected, + )) => ProtoAuthResult::NoOperatorsOnline, + ApproveError(auth::ApproveError::Internal) + | DatabasePoolUnavailable + | DatabaseOperationFailed + | IntegrityCheckFailed + | Transport => ProtoAuthResult::Internal, + } + .into(), + ) + } +} + +impl Convert for auth::Outbound { + type Output = AuthResponsePayload; + + fn convert(self) -> Self::Output { + match self { + Self::AuthChallenge { challenge } => { + AuthResponsePayload::Challenge(ProtoAuthChallenge { + timestamp_nanos: challenge + .timestamp + .timestamp_nanos_opt() + .expect("timestamp within range") + .cast_unsigned(), + random: challenge.nonce.to_vec(), + }) + } + Self::AuthSuccess => AuthResponsePayload::Result(ProtoAuthResult::Success.into()), + } + } +} + +pub(super) async fn start( + conn: &mut ClientConnection, + bi: &mut GrpcBi, + request_tracker: &mut RequestTracker, +) -> Result { + let mut transport = AuthTransportAdapter::new(bi, request_tracker); + auth::authenticate(conn, &mut transport).await +} diff --git a/server/crates/arbiter-server/src/grpc/client/evm.rs b/server/crates/arbiter-server/src/grpc/client/evm.rs index 4e3dc6d..00bb5f1 100644 --- a/server/crates/arbiter-server/src/grpc/client/evm.rs +++ b/server/crates/arbiter-server/src/grpc/client/evm.rs @@ -1,87 +1,87 @@ -use crate::{ - grpc::{ - Convert, TryConvert, - common::inbound::{RawEvmAddress, RawEvmTransaction}, - }, - peers::client::session::{ClientSession, HandleSignTransaction, SignTransactionRpcError}, -}; -use arbiter_proto::proto::{ - client::{ - client_response::Payload as ClientResponsePayload, - evm::{ - self as proto_evm, request::Payload as EvmRequestPayload, - response::Payload as EvmResponsePayload, - }, - }, - evm::{ - EvmError as ProtoEvmError, EvmSignTransactionResponse, - evm_sign_transaction_response::Result as EvmSignTransactionResult, - }, -}; - -use kameo::actor::ActorRef; -use tonic::Status; -use tracing::warn; - -const fn wrap_response(payload: EvmResponsePayload) -> ClientResponsePayload { - ClientResponsePayload::Evm(proto_evm::Response { - payload: Some(payload), - }) -} - -pub(super) async fn dispatch( - actor: &ActorRef, - req: proto_evm::Request, -) -> Result { - let Some(payload) = req.payload else { - return Err(Status::invalid_argument( - "Missing client EVM request payload", - )); - }; - - match payload { - EvmRequestPayload::SignTransaction(request) => { - let address = RawEvmAddress(request.wallet_address).try_convert()?; - let transaction = RawEvmTransaction(request.rlp_transaction).try_convert()?; - - let response = match actor - .ask(HandleSignTransaction { - wallet_address: address, - transaction, - }) - .await - { - Ok(signature) => EvmSignTransactionResponse { - result: Some(EvmSignTransactionResult::Signature( - signature.as_bytes().to_vec(), - )), - }, - Err(kameo::error::SendError::HandlerError(SignTransactionRpcError::Vet( - vet_error, - ))) => EvmSignTransactionResponse { - result: Some(vet_error.convert()), - }, - Err(kameo::error::SendError::HandlerError(SignTransactionRpcError::Internal)) => { - EvmSignTransactionResponse { - result: Some(EvmSignTransactionResult::Error( - ProtoEvmError::Internal.into(), - )), - } - } - Err(err) => { - warn!(error = ?err, "Failed to sign EVM transaction"); - EvmSignTransactionResponse { - result: Some(EvmSignTransactionResult::Error( - ProtoEvmError::Internal.into(), - )), - } - } - }; - - Ok(wrap_response(EvmResponsePayload::SignTransaction(response))) - } - EvmRequestPayload::AnalyzeTransaction(_) => Err(Status::unimplemented( - "EVM transaction analysis is not yet implemented", - )), - } -} +use crate::{ + grpc::{ + Convert, TryConvert, + common::inbound::{RawEvmAddress, RawEvmTransaction}, + }, + peers::client::session::{ClientSession, HandleSignTransaction, SignTransactionRpcError}, +}; +use arbiter_proto::proto::{ + client::{ + client_response::Payload as ClientResponsePayload, + evm::{ + self as proto_evm, request::Payload as EvmRequestPayload, + response::Payload as EvmResponsePayload, + }, + }, + evm::{ + EvmError as ProtoEvmError, EvmSignTransactionResponse, + evm_sign_transaction_response::Result as EvmSignTransactionResult, + }, +}; + +use kameo::actor::ActorRef; +use tonic::Status; +use tracing::warn; + +const fn wrap_response(payload: EvmResponsePayload) -> ClientResponsePayload { + ClientResponsePayload::Evm(proto_evm::Response { + payload: Some(payload), + }) +} + +pub(super) async fn dispatch( + actor: &ActorRef, + req: proto_evm::Request, +) -> Result { + let Some(payload) = req.payload else { + return Err(Status::invalid_argument( + "Missing client EVM request payload", + )); + }; + + match payload { + EvmRequestPayload::SignTransaction(request) => { + let address = RawEvmAddress(request.wallet_address).try_convert()?; + let transaction = RawEvmTransaction(request.rlp_transaction).try_convert()?; + + let response = match actor + .ask(HandleSignTransaction { + wallet_address: address, + transaction, + }) + .await + { + Ok(signature) => EvmSignTransactionResponse { + result: Some(EvmSignTransactionResult::Signature( + signature.as_bytes().to_vec(), + )), + }, + Err(kameo::error::SendError::HandlerError(SignTransactionRpcError::Vet( + vet_error, + ))) => EvmSignTransactionResponse { + result: Some(vet_error.convert()), + }, + Err(kameo::error::SendError::HandlerError(SignTransactionRpcError::Internal)) => { + EvmSignTransactionResponse { + result: Some(EvmSignTransactionResult::Error( + ProtoEvmError::Internal.into(), + )), + } + } + Err(err) => { + warn!(error = ?err, "Failed to sign EVM transaction"); + EvmSignTransactionResponse { + result: Some(EvmSignTransactionResult::Error( + ProtoEvmError::Internal.into(), + )), + } + } + }; + + Ok(wrap_response(EvmResponsePayload::SignTransaction(response))) + } + EvmRequestPayload::AnalyzeTransaction(_) => Err(Status::unimplemented( + "EVM transaction analysis is not yet implemented", + )), + } +} diff --git a/server/crates/arbiter-server/src/grpc/client/inbound.rs b/server/crates/arbiter-server/src/grpc/client/inbound.rs index 8b13789..d3f5a12 100644 --- a/server/crates/arbiter-server/src/grpc/client/inbound.rs +++ b/server/crates/arbiter-server/src/grpc/client/inbound.rs @@ -1 +1 @@ - + diff --git a/server/crates/arbiter-server/src/grpc/client/outbound.rs b/server/crates/arbiter-server/src/grpc/client/outbound.rs index 8b13789..d3f5a12 100644 --- a/server/crates/arbiter-server/src/grpc/client/outbound.rs +++ b/server/crates/arbiter-server/src/grpc/client/outbound.rs @@ -1 +1 @@ - + diff --git a/server/crates/arbiter-server/src/grpc/client/vault.rs b/server/crates/arbiter-server/src/grpc/client/vault.rs index f5561b9..3035889 100644 --- a/server/crates/arbiter-server/src/grpc/client/vault.rs +++ b/server/crates/arbiter-server/src/grpc/client/vault.rs @@ -1,47 +1,47 @@ -use crate::{ - actors::vault::VaultState, - peers::client::session::{ClientSession, Error, HandleQueryVaultState}, -}; -use arbiter_proto::proto::{ - client::{ - client_response::Payload as ClientResponsePayload, - vault::{ - self as proto_vault, request::Payload as VaultRequestPayload, - response::Payload as VaultResponsePayload, - }, - }, - shared::VaultState as ProtoVaultState, -}; - -use kameo::{actor::ActorRef, error::SendError}; -use tonic::Status; -use tracing::warn; - -pub(super) async fn dispatch( - actor: &ActorRef, - req: proto_vault::Request, -) -> Result { - let Some(payload) = req.payload else { - return Err(Status::invalid_argument( - "Missing client vault request payload", - )); - }; - - match payload { - VaultRequestPayload::QueryState(()) => { - let state = match actor.ask(HandleQueryVaultState {}).await { - Ok(VaultState::Unbootstrapped) => ProtoVaultState::Unbootstrapped, - Ok(VaultState::Sealed) => ProtoVaultState::Sealed, - Ok(VaultState::Unsealed) => ProtoVaultState::Unsealed, - Err(SendError::HandlerError(Error::Internal)) => ProtoVaultState::Error, - Err(err) => { - warn!(error = ?err, "Failed to query vault state"); - ProtoVaultState::Error - } - }; - Ok(ClientResponsePayload::Vault(proto_vault::Response { - payload: Some(VaultResponsePayload::State(state.into())), - })) - } - } -} +use crate::{ + actors::vault::VaultState, + peers::client::session::{ClientSession, Error, HandleQueryVaultState}, +}; +use arbiter_proto::proto::{ + client::{ + client_response::Payload as ClientResponsePayload, + vault::{ + self as proto_vault, request::Payload as VaultRequestPayload, + response::Payload as VaultResponsePayload, + }, + }, + shared::VaultState as ProtoVaultState, +}; + +use kameo::{actor::ActorRef, error::SendError}; +use tonic::Status; +use tracing::warn; + +pub(super) async fn dispatch( + actor: &ActorRef, + req: proto_vault::Request, +) -> Result { + let Some(payload) = req.payload else { + return Err(Status::invalid_argument( + "Missing client vault request payload", + )); + }; + + match payload { + VaultRequestPayload::QueryState(()) => { + let state = match actor.ask(HandleQueryVaultState {}).await { + Ok(VaultState::Unbootstrapped) => ProtoVaultState::Unbootstrapped, + Ok(VaultState::Sealed) => ProtoVaultState::Sealed, + Ok(VaultState::Unsealed) => ProtoVaultState::Unsealed, + Err(SendError::HandlerError(Error::Internal)) => ProtoVaultState::Error, + Err(err) => { + warn!(error = ?err, "Failed to query vault state"); + ProtoVaultState::Error + } + }; + Ok(ClientResponsePayload::Vault(proto_vault::Response { + payload: Some(VaultResponsePayload::State(state.into())), + })) + } + } +} diff --git a/server/crates/arbiter-server/src/grpc/common.rs b/server/crates/arbiter-server/src/grpc/common.rs index b638928..25b149e 100644 --- a/server/crates/arbiter-server/src/grpc/common.rs +++ b/server/crates/arbiter-server/src/grpc/common.rs @@ -1,2 +1,2 @@ -pub(super) mod inbound; -pub(super) mod outbound; +pub(super) mod inbound; +pub(super) mod outbound; diff --git a/server/crates/arbiter-server/src/grpc/common/inbound.rs b/server/crates/arbiter-server/src/grpc/common/inbound.rs index 5c71aed..dd9aeb8 100644 --- a/server/crates/arbiter-server/src/grpc/common/inbound.rs +++ b/server/crates/arbiter-server/src/grpc/common/inbound.rs @@ -1,35 +1,35 @@ -use crate::grpc::TryConvert; - -use alloy::{consensus::TxEip1559, primitives::Address, rlp::Decodable as _}; - -pub(in crate::grpc) struct RawEvmAddress(pub(in crate::grpc) Vec); -impl TryConvert for RawEvmAddress { - type Output = Address; - - type Error = tonic::Status; - - fn try_convert(self) -> Result { - let wallet_address = match <[u8; 20]>::try_from(self.0.as_slice()) { - Ok(address) => Address::from(address), - Err(_) => { - return Err(tonic::Status::invalid_argument( - "Invalid EVM wallet address", - )); - } - }; - Ok(wallet_address) - } -} - -pub(in crate::grpc) struct RawEvmTransaction(pub(in crate::grpc) Vec); -impl TryConvert for RawEvmTransaction { - type Output = TxEip1559; - - type Error = tonic::Status; - - fn try_convert(self) -> Result { - let tx = TxEip1559::decode(&mut self.0.as_slice()) - .map_err(|_| tonic::Status::invalid_argument("Invalid EVM transaction format"))?; - Ok(tx) - } -} +use crate::grpc::TryConvert; + +use alloy::{consensus::TxEip1559, primitives::Address, rlp::Decodable as _}; + +pub(in crate::grpc) struct RawEvmAddress(pub(in crate::grpc) Vec); +impl TryConvert for RawEvmAddress { + type Output = Address; + + type Error = tonic::Status; + + fn try_convert(self) -> Result { + let wallet_address = match <[u8; 20]>::try_from(self.0.as_slice()) { + Ok(address) => Address::from(address), + Err(_) => { + return Err(tonic::Status::invalid_argument( + "Invalid EVM wallet address", + )); + } + }; + Ok(wallet_address) + } +} + +pub(in crate::grpc) struct RawEvmTransaction(pub(in crate::grpc) Vec); +impl TryConvert for RawEvmTransaction { + type Output = TxEip1559; + + type Error = tonic::Status; + + fn try_convert(self) -> Result { + let tx = TxEip1559::decode(&mut self.0.as_slice()) + .map_err(|_| tonic::Status::invalid_argument("Invalid EVM transaction format"))?; + Ok(tx) + } +} diff --git a/server/crates/arbiter-server/src/grpc/common/outbound.rs b/server/crates/arbiter-server/src/grpc/common/outbound.rs index 51e098b..49bc17c 100644 --- a/server/crates/arbiter-server/src/grpc/common/outbound.rs +++ b/server/crates/arbiter-server/src/grpc/common/outbound.rs @@ -1,121 +1,121 @@ -use crate::{ - evm::{ - PolicyError, VetError, - policies::{EvalViolation, SpecificMeaning}, - }, - grpc::Convert, -}; -use arbiter_proto::proto::{ - evm::{ - EvmError as ProtoEvmError, - evm_sign_transaction_response::Result as EvmSignTransactionResult, - }, - shared::evm::{ - EvalViolation as ProtoEvalViolation, GasLimitExceededViolation, NoMatchingGrantError, - PolicyViolationsError, SpecificMeaning as ProtoSpecificMeaning, - TokenInfo as ProtoTokenInfo, TransactionEvalError as ProtoTransactionEvalError, - eval_violation as proto_eval_violation, eval_violation::Kind as ProtoEvalViolationKind, - specific_meaning::Meaning as ProtoSpecificMeaningKind, - transaction_eval_error::Kind as ProtoTransactionEvalErrorKind, - }, -}; - -use alloy::primitives::U256; - -fn u256_to_proto_bytes(value: U256) -> Vec { - value.to_be_bytes::<32>().to_vec() -} - -impl Convert for SpecificMeaning { - type Output = ProtoSpecificMeaning; - - fn convert(self) -> Self::Output { - let kind = match self { - Self::EtherTransfer(meaning) => ProtoSpecificMeaningKind::EtherTransfer( - arbiter_proto::proto::shared::evm::EtherTransferMeaning { - to: meaning.to.to_vec(), - value: u256_to_proto_bytes(meaning.value), - }, - ), - Self::TokenTransfer(meaning) => ProtoSpecificMeaningKind::TokenTransfer( - arbiter_proto::proto::shared::evm::TokenTransferMeaning { - token: Some(ProtoTokenInfo { - symbol: meaning.token.symbol.to_owned(), - address: meaning.token.contract.to_vec(), - chain_id: meaning.token.chain, - }), - to: meaning.to.to_vec(), - value: u256_to_proto_bytes(meaning.value), - }, - ), - }; - - ProtoSpecificMeaning { - meaning: Some(kind), - } - } -} - -impl Convert for EvalViolation { - type Output = ProtoEvalViolation; - - fn convert(self) -> Self::Output { - let kind = match self { - Self::InvalidTarget { target } => { - ProtoEvalViolationKind::InvalidTarget(target.to_vec()) - } - Self::GasLimitExceeded { - max_gas_fee_per_gas, - max_priority_fee_per_gas, - } => ProtoEvalViolationKind::GasLimitExceeded(GasLimitExceededViolation { - max_gas_fee_per_gas: max_gas_fee_per_gas.map(u256_to_proto_bytes), - max_priority_fee_per_gas: max_priority_fee_per_gas.map(u256_to_proto_bytes), - }), - Self::RateLimitExceeded => ProtoEvalViolationKind::RateLimitExceeded(()), - Self::VolumetricLimitExceeded => ProtoEvalViolationKind::VolumetricLimitExceeded(()), - Self::InvalidTime => ProtoEvalViolationKind::InvalidTime(()), - Self::InvalidTransactionType => ProtoEvalViolationKind::InvalidTransactionType(()), - Self::MismatchingChainId { expected, actual } => { - ProtoEvalViolationKind::ChainIdMismatch(proto_eval_violation::ChainIdMismatch { - expected, - actual, - }) - } - }; - - ProtoEvalViolation { kind: Some(kind) } - } -} - -impl Convert for VetError { - type Output = EvmSignTransactionResult; - - fn convert(self) -> Self::Output { - let kind = match self { - Self::ContractCreationNotSupported => { - ProtoTransactionEvalErrorKind::ContractCreationNotSupported(()) - } - Self::UnsupportedTransactionType => { - ProtoTransactionEvalErrorKind::UnsupportedTransactionType(()) - } - Self::Evaluated(meaning, policy_error) => match policy_error { - PolicyError::NoMatchingGrant => { - ProtoTransactionEvalErrorKind::NoMatchingGrant(NoMatchingGrantError { - meaning: Some(meaning.convert()), - }) - } - PolicyError::Violations(violations) => { - ProtoTransactionEvalErrorKind::PolicyViolations(PolicyViolationsError { - meaning: Some(meaning.convert()), - violations: violations.into_iter().map(Convert::convert).collect(), - }) - } - PolicyError::Database(_) | PolicyError::Integrity(_) => { - return EvmSignTransactionResult::Error(ProtoEvmError::Internal.into()); - } - }, - }; - - EvmSignTransactionResult::EvalError(ProtoTransactionEvalError { kind: Some(kind) }) - } -} +use crate::{ + evm::{ + PolicyError, VetError, + policies::{EvalViolation, SpecificMeaning}, + }, + grpc::Convert, +}; +use arbiter_proto::proto::{ + evm::{ + EvmError as ProtoEvmError, + evm_sign_transaction_response::Result as EvmSignTransactionResult, + }, + shared::evm::{ + EvalViolation as ProtoEvalViolation, GasLimitExceededViolation, NoMatchingGrantError, + PolicyViolationsError, SpecificMeaning as ProtoSpecificMeaning, + TokenInfo as ProtoTokenInfo, TransactionEvalError as ProtoTransactionEvalError, + eval_violation as proto_eval_violation, eval_violation::Kind as ProtoEvalViolationKind, + specific_meaning::Meaning as ProtoSpecificMeaningKind, + transaction_eval_error::Kind as ProtoTransactionEvalErrorKind, + }, +}; + +use alloy::primitives::U256; + +fn u256_to_proto_bytes(value: U256) -> Vec { + value.to_be_bytes::<32>().to_vec() +} + +impl Convert for SpecificMeaning { + type Output = ProtoSpecificMeaning; + + fn convert(self) -> Self::Output { + let kind = match self { + Self::EtherTransfer(meaning) => ProtoSpecificMeaningKind::EtherTransfer( + arbiter_proto::proto::shared::evm::EtherTransferMeaning { + to: meaning.to.to_vec(), + value: u256_to_proto_bytes(meaning.value), + }, + ), + Self::TokenTransfer(meaning) => ProtoSpecificMeaningKind::TokenTransfer( + arbiter_proto::proto::shared::evm::TokenTransferMeaning { + token: Some(ProtoTokenInfo { + symbol: meaning.token.symbol.to_owned(), + address: meaning.token.contract.to_vec(), + chain_id: meaning.token.chain, + }), + to: meaning.to.to_vec(), + value: u256_to_proto_bytes(meaning.value), + }, + ), + }; + + ProtoSpecificMeaning { + meaning: Some(kind), + } + } +} + +impl Convert for EvalViolation { + type Output = ProtoEvalViolation; + + fn convert(self) -> Self::Output { + let kind = match self { + Self::InvalidTarget { target } => { + ProtoEvalViolationKind::InvalidTarget(target.to_vec()) + } + Self::GasLimitExceeded { + max_gas_fee_per_gas, + max_priority_fee_per_gas, + } => ProtoEvalViolationKind::GasLimitExceeded(GasLimitExceededViolation { + max_gas_fee_per_gas: max_gas_fee_per_gas.map(u256_to_proto_bytes), + max_priority_fee_per_gas: max_priority_fee_per_gas.map(u256_to_proto_bytes), + }), + Self::RateLimitExceeded => ProtoEvalViolationKind::RateLimitExceeded(()), + Self::VolumetricLimitExceeded => ProtoEvalViolationKind::VolumetricLimitExceeded(()), + Self::InvalidTime => ProtoEvalViolationKind::InvalidTime(()), + Self::InvalidTransactionType => ProtoEvalViolationKind::InvalidTransactionType(()), + Self::MismatchingChainId { expected, actual } => { + ProtoEvalViolationKind::ChainIdMismatch(proto_eval_violation::ChainIdMismatch { + expected, + actual, + }) + } + }; + + ProtoEvalViolation { kind: Some(kind) } + } +} + +impl Convert for VetError { + type Output = EvmSignTransactionResult; + + fn convert(self) -> Self::Output { + let kind = match self { + Self::ContractCreationNotSupported => { + ProtoTransactionEvalErrorKind::ContractCreationNotSupported(()) + } + Self::UnsupportedTransactionType => { + ProtoTransactionEvalErrorKind::UnsupportedTransactionType(()) + } + Self::Evaluated(meaning, policy_error) => match policy_error { + PolicyError::NoMatchingGrant => { + ProtoTransactionEvalErrorKind::NoMatchingGrant(NoMatchingGrantError { + meaning: Some(meaning.convert()), + }) + } + PolicyError::Violations(violations) => { + ProtoTransactionEvalErrorKind::PolicyViolations(PolicyViolationsError { + meaning: Some(meaning.convert()), + violations: violations.into_iter().map(Convert::convert).collect(), + }) + } + PolicyError::Database(_) | PolicyError::Integrity(_) => { + return EvmSignTransactionResult::Error(ProtoEvmError::Internal.into()); + } + }, + }; + + EvmSignTransactionResult::EvalError(ProtoTransactionEvalError { kind: Some(kind) }) + } +} diff --git a/server/crates/arbiter-server/src/grpc/mod.rs b/server/crates/arbiter-server/src/grpc/mod.rs index fcd403b..8590060 100644 --- a/server/crates/arbiter-server/src/grpc/mod.rs +++ b/server/crates/arbiter-server/src/grpc/mod.rs @@ -1,75 +1,75 @@ -use crate::peers::{client::ClientConnection, operator::OperatorConnection}; -use arbiter_proto::{ - proto::{ - client::{ClientRequest, ClientResponse}, - operator::{OperatorRequest, OperatorResponse}, - }, - transport::grpc::GrpcBi, -}; - -use tokio_stream::wrappers::ReceiverStream; -use tonic::{Request, Response, Status, async_trait}; -use tracing::info; - -mod request_tracker; - -pub mod client; -pub mod operator; - -mod common; - -pub trait Convert { - type Output; - - fn convert(self) -> Self::Output; -} - -pub trait TryConvert { - type Output; - type Error; - - fn try_convert(self) -> Result; -} - -#[async_trait] -impl arbiter_proto::proto::arbiter_service_server::ArbiterService for super::Server { - type OperatorStream = ReceiverStream>; - type ClientStream = ReceiverStream>; - - #[tracing::instrument(level = "debug", skip(self))] - async fn client( - &self, - request: Request>, - ) -> Result, Status> { - let req_stream = request.into_inner(); - let (bi, rx) = GrpcBi::from_bi_stream(req_stream); - let props = ClientConnection::new(self.context.db.clone(), self.context.actors.clone()); - tokio::spawn(client::start(props, bi)); - - info!(event = "connection established", "grpc.client"); - - Ok(Response::new(rx)) - } - - #[tracing::instrument(level = "debug", skip(self))] - async fn operator( - &self, - request: Request>, - ) -> Result, Status> { - let req_stream = request.into_inner(); - - let (bi, rx) = GrpcBi::from_bi_stream(req_stream); - - tokio::spawn(operator::start( - OperatorConnection { - db: self.context.db.clone(), - actors: self.context.actors.clone(), - }, - bi, - )); - - info!(event = "connection established", "grpc.operator"); - - Ok(Response::new(rx)) - } -} +use crate::peers::{client::ClientConnection, operator::OperatorConnection}; +use arbiter_proto::{ + proto::{ + client::{ClientRequest, ClientResponse}, + operator::{OperatorRequest, OperatorResponse}, + }, + transport::grpc::GrpcBi, +}; + +use tokio_stream::wrappers::ReceiverStream; +use tonic::{Request, Response, Status, async_trait}; +use tracing::info; + +mod request_tracker; + +pub mod client; +pub mod operator; + +mod common; + +pub trait Convert { + type Output; + + fn convert(self) -> Self::Output; +} + +pub trait TryConvert { + type Output; + type Error; + + fn try_convert(self) -> Result; +} + +#[async_trait] +impl arbiter_proto::proto::arbiter_service_server::ArbiterService for super::Server { + type OperatorStream = ReceiverStream>; + type ClientStream = ReceiverStream>; + + #[tracing::instrument(level = "debug", skip(self))] + async fn client( + &self, + request: Request>, + ) -> Result, Status> { + let req_stream = request.into_inner(); + let (bi, rx) = GrpcBi::from_bi_stream(req_stream); + let props = ClientConnection::new(self.context.db.clone(), self.context.actors.clone()); + tokio::spawn(client::start(props, bi)); + + info!(event = "connection established", "grpc.client"); + + Ok(Response::new(rx)) + } + + #[tracing::instrument(level = "debug", skip(self))] + async fn operator( + &self, + request: Request>, + ) -> Result, Status> { + let req_stream = request.into_inner(); + + let (bi, rx) = GrpcBi::from_bi_stream(req_stream); + + tokio::spawn(operator::start( + OperatorConnection { + db: self.context.db.clone(), + actors: self.context.actors.clone(), + }, + bi, + )); + + info!(event = "connection established", "grpc.operator"); + + Ok(Response::new(rx)) + } +} diff --git a/server/crates/arbiter-server/src/grpc/operator.rs b/server/crates/arbiter-server/src/grpc/operator.rs index cdd4e80..078056c 100644 --- a/server/crates/arbiter-server/src/grpc/operator.rs +++ b/server/crates/arbiter-server/src/grpc/operator.rs @@ -1,145 +1,145 @@ -use crate::{ - grpc::request_tracker::RequestTracker, - peers::operator::{OutOfBand, OperatorConnection, OperatorSession}, -}; -use arbiter_proto::{ - proto::operator::{ - OperatorRequest, OperatorResponse, - operator_request::Payload as OperatorRequestPayload, - operator_response::Payload as OperatorResponsePayload, - }, - transport::{Error as TransportError, Receiver, Sender, grpc::GrpcBi}, -}; - -use async_trait::async_trait; -use kameo::actor::ActorRef; -use tokio::sync::mpsc; -use tonic::Status; -use tracing::{error, info, warn}; - -mod auth; -mod evm; -mod inbound; -mod outbound; -mod sdk_client; -mod vault; -mod vault_gate; - -pub struct OutOfBandAdapter(mpsc::Sender); - -#[async_trait] -impl Sender for OutOfBandAdapter { - async fn send(&mut self, item: OutOfBand) -> Result<(), TransportError> { - self.0.send(item).await.map_err(|e| { - warn!(error = ?e, "Failed to send out-of-band message"); - TransportError::ChannelClosed - }) - } -} - -async fn dispatch_loop( - mut bi: GrpcBi, - actor: ActorRef, - mut receiver: mpsc::Receiver, - mut request_tracker: RequestTracker, -) { - loop { - tokio::select! { - oob = receiver.recv() => { - let Some(oob) = oob else { - warn!("Out-of-band message channel closed"); - return; - }; - - let payload = sdk_client::out_of_band_payload(oob); - - if bi.send(Ok(OperatorResponse { id: None, payload: Some(payload) })).await.is_err() { - return; - } - } - - message = bi.recv() => { - let Some(message) = message else { return; }; - - let conn = match message { - Ok(conn) => conn, - Err(err) => { - warn!(error = ?err, "Failed to receive operator request"); - return; - } - }; - - let request_id = match request_tracker.request(conn.id) { - Ok(id) => id, - Err(err) => { - let _ = bi.send(Err(err)).await; - return; - } - }; - - let Some(payload) = conn.payload else { - let _ = bi.send(Err(Status::invalid_argument("Missing operator request payload"))).await; - return; - }; - - match dispatch_inner(&actor, payload).await { - Ok(Some(response)) => { - if bi.send(Ok(OperatorResponse { - id: Some(request_id), - payload: Some(response), - })).await.is_err() { - return; - } - } - Ok(None) => {} - Err(status) => { - error!(?status, "Failed to process operator request"); - let _ = bi.send(Err(status)).await; - return; - } - } - } - } - } -} - -async fn dispatch_inner( - actor: &ActorRef, - payload: OperatorRequestPayload, -) -> Result, Status> { - match payload { - OperatorRequestPayload::Vault(req) => vault::dispatch(actor, req).await, - OperatorRequestPayload::Evm(req) => evm::dispatch(actor, req).await, - OperatorRequestPayload::SdkClient(req) => sdk_client::dispatch(actor, req).await, - OperatorRequestPayload::Auth(..) => { - warn!("Unsupported post-auth operator auth request"); - Err(Status::invalid_argument("Unsupported operator request")) - } - } -} - -pub async fn start( - mut conn: OperatorConnection, - mut bi: GrpcBi, -) { - let mut request_tracker = RequestTracker::default(); - - let (oob_sender, oob_receiver) = mpsc::channel(16); - let oob_adapter = OutOfBandAdapter(oob_sender); - - let actor = { - let transport = auth::AuthTransportAdapter::new(&mut bi, &mut request_tracker); - match crate::peers::operator::start(&mut conn, transport, Box::new(oob_adapter)).await { - Ok(actor) => actor, - Err(e) => { - warn!(error = ?e, "Operator connection failed"); - return; - } - } - }; - - info!("Operator session established"); - - dispatch_loop(bi, actor.clone(), oob_receiver, request_tracker).await; - actor.kill(); -} +use crate::{ + grpc::request_tracker::RequestTracker, + peers::operator::{OutOfBand, OperatorConnection, OperatorSession}, +}; +use arbiter_proto::{ + proto::operator::{ + OperatorRequest, OperatorResponse, + operator_request::Payload as OperatorRequestPayload, + operator_response::Payload as OperatorResponsePayload, + }, + transport::{Error as TransportError, Receiver, Sender, grpc::GrpcBi}, +}; + +use async_trait::async_trait; +use kameo::actor::ActorRef; +use tokio::sync::mpsc; +use tonic::Status; +use tracing::{error, info, warn}; + +mod auth; +mod evm; +mod inbound; +mod outbound; +mod sdk_client; +mod vault; +mod vault_gate; + +pub struct OutOfBandAdapter(mpsc::Sender); + +#[async_trait] +impl Sender for OutOfBandAdapter { + async fn send(&mut self, item: OutOfBand) -> Result<(), TransportError> { + self.0.send(item).await.map_err(|e| { + warn!(error = ?e, "Failed to send out-of-band message"); + TransportError::ChannelClosed + }) + } +} + +async fn dispatch_loop( + mut bi: GrpcBi, + actor: ActorRef, + mut receiver: mpsc::Receiver, + mut request_tracker: RequestTracker, +) { + loop { + tokio::select! { + oob = receiver.recv() => { + let Some(oob) = oob else { + warn!("Out-of-band message channel closed"); + return; + }; + + let payload = sdk_client::out_of_band_payload(oob); + + if bi.send(Ok(OperatorResponse { id: None, payload: Some(payload) })).await.is_err() { + return; + } + } + + message = bi.recv() => { + let Some(message) = message else { return; }; + + let conn = match message { + Ok(conn) => conn, + Err(err) => { + warn!(error = ?err, "Failed to receive operator request"); + return; + } + }; + + let request_id = match request_tracker.request(conn.id) { + Ok(id) => id, + Err(err) => { + let _ = bi.send(Err(err)).await; + return; + } + }; + + let Some(payload) = conn.payload else { + let _ = bi.send(Err(Status::invalid_argument("Missing operator request payload"))).await; + return; + }; + + match dispatch_inner(&actor, payload).await { + Ok(Some(response)) => { + if bi.send(Ok(OperatorResponse { + id: Some(request_id), + payload: Some(response), + })).await.is_err() { + return; + } + } + Ok(None) => {} + Err(status) => { + error!(?status, "Failed to process operator request"); + let _ = bi.send(Err(status)).await; + return; + } + } + } + } + } +} + +async fn dispatch_inner( + actor: &ActorRef, + payload: OperatorRequestPayload, +) -> Result, Status> { + match payload { + OperatorRequestPayload::Vault(req) => vault::dispatch(actor, req).await, + OperatorRequestPayload::Evm(req) => evm::dispatch(actor, req).await, + OperatorRequestPayload::SdkClient(req) => sdk_client::dispatch(actor, req).await, + OperatorRequestPayload::Auth(..) => { + warn!("Unsupported post-auth operator auth request"); + Err(Status::invalid_argument("Unsupported operator request")) + } + } +} + +pub async fn start( + mut conn: OperatorConnection, + mut bi: GrpcBi, +) { + let mut request_tracker = RequestTracker::default(); + + let (oob_sender, oob_receiver) = mpsc::channel(16); + let oob_adapter = OutOfBandAdapter(oob_sender); + + let actor = { + let transport = auth::AuthTransportAdapter::new(&mut bi, &mut request_tracker); + match crate::peers::operator::start(&mut conn, transport, Box::new(oob_adapter)).await { + Ok(actor) => actor, + Err(e) => { + warn!(error = ?e, "Operator connection failed"); + return; + } + } + }; + + info!("Operator session established"); + + dispatch_loop(bi, actor.clone(), oob_receiver, request_tracker).await; + actor.kill(); +} diff --git a/server/crates/arbiter-server/src/grpc/operator/auth.rs b/server/crates/arbiter-server/src/grpc/operator/auth.rs index fa15310..9d13c84 100644 --- a/server/crates/arbiter-server/src/grpc/operator/auth.rs +++ b/server/crates/arbiter-server/src/grpc/operator/auth.rs @@ -1,184 +1,184 @@ -use crate::{grpc::request_tracker::RequestTracker, peers::operator::auth}; -use arbiter_crypto::authn; -use arbiter_proto::{ - proto::operator::{ - OperatorRequest, OperatorResponse, - auth::{ - self as proto_auth, AuthChallenge as ProtoAuthChallenge, - AuthChallengeRequest as ProtoAuthChallengeRequest, - AuthChallengeSolution as ProtoAuthChallengeSolution, AuthResult as ProtoAuthResult, - request::Payload as AuthRequestPayload, response::Payload as AuthResponsePayload, - }, - operator_request::Payload as OperatorRequestPayload, - operator_response::Payload as OperatorResponsePayload, - }, - transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi}, -}; - -use async_trait::async_trait; -use tonic::Status; -use tracing::warn; - -pub(super) struct AuthTransportAdapter<'a> { - pub(super) bi: &'a mut GrpcBi, - pub(super) request_tracker: &'a mut RequestTracker, -} - -impl<'a> AuthTransportAdapter<'a> { - pub(super) const fn new( - bi: &'a mut GrpcBi, - request_tracker: &'a mut RequestTracker, - ) -> Self { - Self { - bi, - request_tracker, - } - } - - pub(super) const fn bi_mut(&mut self) -> &mut GrpcBi { - self.bi - } - - pub(super) const fn tracker_mut(&mut self) -> &mut RequestTracker { - self.request_tracker - } - - pub(super) async fn send_response_payload( - &mut self, - payload: OperatorResponsePayload, - ) -> Result<(), TransportError> { - self.bi - .send(Ok(OperatorResponse { - id: Some(self.request_tracker.current_request_id()), - payload: Some(payload), - })) - .await - } - - async fn send_operator_response( - &mut self, - payload: AuthResponsePayload, - ) -> Result<(), TransportError> { - self.send_response_payload(OperatorResponsePayload::Auth(proto_auth::Response { - payload: Some(payload), - })) - .await - } -} - -#[async_trait] -impl Sender> for AuthTransportAdapter<'_> { - async fn send( - &mut self, - item: Result, - ) -> Result<(), TransportError> { - use auth::{Error, Outbound}; - let payload = match item { - Ok(Outbound::AuthChallenge { challenge }) => { - AuthResponsePayload::Challenge(ProtoAuthChallenge { - timestamp_nanos: challenge - .timestamp - .timestamp_nanos_opt() - .expect("timestamp within range") - .cast_unsigned(), - random: challenge.nonce.to_vec(), - }) - } - Ok(Outbound::AuthSuccess) => { - AuthResponsePayload::Result(ProtoAuthResult::Success.into()) - } - Err(Error::UnregisteredPublicKey) => { - AuthResponsePayload::Result(ProtoAuthResult::InvalidKey.into()) - } - Err(Error::InvalidChallengeSolution) => { - AuthResponsePayload::Result(ProtoAuthResult::InvalidSignature.into()) - } - Err(Error::InvalidBootstrapToken) => { - AuthResponsePayload::Result(ProtoAuthResult::TokenInvalid.into()) - } - Err(Error::Internal { details }) => { - return self.bi.send(Err(Status::internal(details))).await; - } - Err(Error::Transport) => { - return self - .bi - .send(Err(Status::unavailable("transport error"))) - .await; - } - }; - - self.send_operator_response(payload).await - } -} - -#[async_trait] -impl Receiver for AuthTransportAdapter<'_> { - async fn recv(&mut self) -> Option { - let request = match self.bi.recv().await? { - Ok(request) => request, - Err(error) => { - warn!(error = ?error, "Failed to receive operator auth request"); - return None; - } - }; - - match self.request_tracker.request(request.id) { - Ok(request_id) => request_id, - Err(error) => { - let _ = self.bi.send(Err(error)).await; - return None; - } - }; - - let Some(payload) = request.payload else { - warn!( - event = "received request with empty payload", - "grpc.operator.auth_adapter" - ); - return None; - }; - - let OperatorRequestPayload::Auth(auth_request) = payload else { - let _ = self - .bi - .send(Err(Status::invalid_argument( - "Unsupported operator auth request", - ))) - .await; - return None; - }; - - let Some(payload) = auth_request.payload else { - warn!( - event = "received auth request with empty payload", - "grpc.operator.auth_adapter" - ); - return None; - }; - - match payload { - AuthRequestPayload::ChallengeRequest(ProtoAuthChallengeRequest { - pubkey, - bootstrap_token, - }) => { - let Ok(pubkey) = authn::PublicKey::try_from(pubkey.as_slice()) else { - warn!( - event = "received request with invalid public key", - "grpc.operator.auth_adapter" - ); - return None; - }; - - Some(auth::Inbound::AuthChallengeRequest { - pubkey, - bootstrap_token, - }) - } - AuthRequestPayload::ChallengeSolution(ProtoAuthChallengeSolution { signature }) => { - Some(auth::Inbound::AuthChallengeSolution { signature }) - } - } - } -} - -impl Bi> for AuthTransportAdapter<'_> {} +use crate::{grpc::request_tracker::RequestTracker, peers::operator::auth}; +use arbiter_crypto::authn; +use arbiter_proto::{ + proto::operator::{ + OperatorRequest, OperatorResponse, + auth::{ + self as proto_auth, AuthChallenge as ProtoAuthChallenge, + AuthChallengeRequest as ProtoAuthChallengeRequest, + AuthChallengeSolution as ProtoAuthChallengeSolution, AuthResult as ProtoAuthResult, + request::Payload as AuthRequestPayload, response::Payload as AuthResponsePayload, + }, + operator_request::Payload as OperatorRequestPayload, + operator_response::Payload as OperatorResponsePayload, + }, + transport::{Bi, Error as TransportError, Receiver, Sender, grpc::GrpcBi}, +}; + +use async_trait::async_trait; +use tonic::Status; +use tracing::warn; + +pub(super) struct AuthTransportAdapter<'a> { + pub(super) bi: &'a mut GrpcBi, + pub(super) request_tracker: &'a mut RequestTracker, +} + +impl<'a> AuthTransportAdapter<'a> { + pub(super) const fn new( + bi: &'a mut GrpcBi, + request_tracker: &'a mut RequestTracker, + ) -> Self { + Self { + bi, + request_tracker, + } + } + + pub(super) const fn bi_mut(&mut self) -> &mut GrpcBi { + self.bi + } + + pub(super) const fn tracker_mut(&mut self) -> &mut RequestTracker { + self.request_tracker + } + + pub(super) async fn send_response_payload( + &mut self, + payload: OperatorResponsePayload, + ) -> Result<(), TransportError> { + self.bi + .send(Ok(OperatorResponse { + id: Some(self.request_tracker.current_request_id()), + payload: Some(payload), + })) + .await + } + + async fn send_operator_response( + &mut self, + payload: AuthResponsePayload, + ) -> Result<(), TransportError> { + self.send_response_payload(OperatorResponsePayload::Auth(proto_auth::Response { + payload: Some(payload), + })) + .await + } +} + +#[async_trait] +impl Sender> for AuthTransportAdapter<'_> { + async fn send( + &mut self, + item: Result, + ) -> Result<(), TransportError> { + use auth::{Error, Outbound}; + let payload = match item { + Ok(Outbound::AuthChallenge { challenge }) => { + AuthResponsePayload::Challenge(ProtoAuthChallenge { + timestamp_nanos: challenge + .timestamp + .timestamp_nanos_opt() + .expect("timestamp within range") + .cast_unsigned(), + random: challenge.nonce.to_vec(), + }) + } + Ok(Outbound::AuthSuccess) => { + AuthResponsePayload::Result(ProtoAuthResult::Success.into()) + } + Err(Error::UnregisteredPublicKey) => { + AuthResponsePayload::Result(ProtoAuthResult::InvalidKey.into()) + } + Err(Error::InvalidChallengeSolution) => { + AuthResponsePayload::Result(ProtoAuthResult::InvalidSignature.into()) + } + Err(Error::InvalidBootstrapToken) => { + AuthResponsePayload::Result(ProtoAuthResult::TokenInvalid.into()) + } + Err(Error::Internal { details }) => { + return self.bi.send(Err(Status::internal(details))).await; + } + Err(Error::Transport) => { + return self + .bi + .send(Err(Status::unavailable("transport error"))) + .await; + } + }; + + self.send_operator_response(payload).await + } +} + +#[async_trait] +impl Receiver for AuthTransportAdapter<'_> { + async fn recv(&mut self) -> Option { + let request = match self.bi.recv().await? { + Ok(request) => request, + Err(error) => { + warn!(error = ?error, "Failed to receive operator auth request"); + return None; + } + }; + + match self.request_tracker.request(request.id) { + Ok(request_id) => request_id, + Err(error) => { + let _ = self.bi.send(Err(error)).await; + return None; + } + }; + + let Some(payload) = request.payload else { + warn!( + event = "received request with empty payload", + "grpc.operator.auth_adapter" + ); + return None; + }; + + let OperatorRequestPayload::Auth(auth_request) = payload else { + let _ = self + .bi + .send(Err(Status::invalid_argument( + "Unsupported operator auth request", + ))) + .await; + return None; + }; + + let Some(payload) = auth_request.payload else { + warn!( + event = "received auth request with empty payload", + "grpc.operator.auth_adapter" + ); + return None; + }; + + match payload { + AuthRequestPayload::ChallengeRequest(ProtoAuthChallengeRequest { + pubkey, + bootstrap_token, + }) => { + let Ok(pubkey) = authn::PublicKey::try_from(pubkey.as_slice()) else { + warn!( + event = "received request with invalid public key", + "grpc.operator.auth_adapter" + ); + return None; + }; + + Some(auth::Inbound::AuthChallengeRequest { + pubkey, + bootstrap_token, + }) + } + AuthRequestPayload::ChallengeSolution(ProtoAuthChallengeSolution { signature }) => { + Some(auth::Inbound::AuthChallengeSolution { signature }) + } + } + } +} + +impl Bi> for AuthTransportAdapter<'_> {} diff --git a/server/crates/arbiter-server/src/grpc/operator/evm.rs b/server/crates/arbiter-server/src/grpc/operator/evm.rs index 0b3ac2c..932a73b 100644 --- a/server/crates/arbiter-server/src/grpc/operator/evm.rs +++ b/server/crates/arbiter-server/src/grpc/operator/evm.rs @@ -1,240 +1,240 @@ -use crate::{ - grpc::{ - Convert, TryConvert, - common::inbound::{RawEvmAddress, RawEvmTransaction}, - }, - peers::operator::{ - OperatorSession, - session::handlers::{ - GrantMutationError, HandleEvmWalletCreate, HandleEvmWalletList, HandleGrantCreate, - HandleGrantDelete, HandleGrantList, HandleSignTransaction, - SignTransactionError as SessionSignTransactionError, - }, - }, -}; -use arbiter_proto::proto::{ - evm::{ - EvmError as ProtoEvmError, EvmGrantCreateRequest, EvmGrantCreateResponse, - EvmGrantDeleteRequest, EvmGrantDeleteResponse, EvmGrantList, EvmGrantListResponse, - EvmSignTransactionResponse, GrantEntry, WalletCreateResponse, WalletEntry, WalletList, - WalletListResponse, evm_grant_create_response::Result as EvmGrantCreateResult, - evm_grant_delete_response::Result as EvmGrantDeleteResult, - evm_grant_list_response::Result as EvmGrantListResult, - evm_sign_transaction_response::Result as EvmSignTransactionResult, - wallet_create_response::Result as WalletCreateResult, - wallet_list_response::Result as WalletListResult, - }, - operator::{ - evm::{ - self as proto_evm, SignTransactionRequest as ProtoSignTransactionRequest, - request::Payload as EvmRequestPayload, response::Payload as EvmResponsePayload, - }, - operator_response::Payload as OperatorResponsePayload, - }, -}; - -use kameo::actor::ActorRef; -use tonic::Status; -use tracing::warn; - -const fn wrap_evm_response(payload: EvmResponsePayload) -> OperatorResponsePayload { - OperatorResponsePayload::Evm(proto_evm::Response { - payload: Some(payload), - }) -} - -pub(super) async fn dispatch( - actor: &ActorRef, - req: proto_evm::Request, -) -> Result, Status> { - let Some(payload) = req.payload else { - return Err(Status::invalid_argument("Missing EVM request payload")); - }; - - match payload { - EvmRequestPayload::WalletCreate(()) => handle_wallet_create(actor).await, - EvmRequestPayload::WalletList(()) => handle_wallet_list(actor).await, - EvmRequestPayload::GrantCreate(req) => handle_grant_create(actor, req).await, - EvmRequestPayload::GrantDelete(req) => handle_grant_delete(actor, req).await, - EvmRequestPayload::GrantList(_) => handle_grant_list(actor).await, - EvmRequestPayload::SignTransaction(req) => handle_sign_transaction(actor, req).await, - } -} - -async fn handle_wallet_create( - actor: &ActorRef, -) -> Result, Status> { - let result = match actor.ask(HandleEvmWalletCreate {}).await { - Ok((wallet_id, address)) => WalletCreateResult::Wallet(WalletEntry { - id: wallet_id, - address: address.to_vec(), - }), - Err(err) => { - warn!(error = ?err, "Failed to create EVM wallet"); - WalletCreateResult::Error(ProtoEvmError::Internal.into()) - } - }; - Ok(Some(wrap_evm_response(EvmResponsePayload::WalletCreate( - WalletCreateResponse { - result: Some(result), - }, - )))) -} - -async fn handle_wallet_list( - actor: &ActorRef, -) -> Result, Status> { - let result = match actor.ask(HandleEvmWalletList {}).await { - Ok(wallets) => WalletListResult::Wallets(WalletList { - wallets: wallets - .into_iter() - .map(|(id, address)| WalletEntry { - address: address.to_vec(), - id, - }) - .collect(), - }), - Err(err) => { - warn!(error = ?err, "Failed to list EVM wallets"); - WalletListResult::Error(ProtoEvmError::Internal.into()) - } - }; - Ok(Some(wrap_evm_response(EvmResponsePayload::WalletList( - WalletListResponse { - result: Some(result), - }, - )))) -} - -async fn handle_grant_list( - actor: &ActorRef, -) -> Result, Status> { - let result = match actor.ask(HandleGrantList {}).await { - Ok(grants) => EvmGrantListResult::Grants(EvmGrantList { - grants: grants - .into_iter() - .map(|grant| GrantEntry { - id: grant.common_settings_id, - wallet_access_id: grant.settings.shared.wallet_access_id, - shared: Some(grant.settings.shared.convert()), - specific: Some(grant.settings.specific.convert()), - }) - .collect(), - }), - Err(err) => { - warn!(error = ?err, "Failed to list EVM grants"); - EvmGrantListResult::Error(ProtoEvmError::Internal.into()) - } - }; - Ok(Some(wrap_evm_response(EvmResponsePayload::GrantList( - EvmGrantListResponse { - result: Some(result), - }, - )))) -} - -async fn handle_grant_create( - actor: &ActorRef, - req: EvmGrantCreateRequest, -) -> Result, Status> { - let basic = req - .shared - .ok_or_else(|| Status::invalid_argument("Missing shared grant settings"))? - .try_convert()?; - let grant = req - .specific - .ok_or_else(|| Status::invalid_argument("Missing specific grant settings"))? - .try_convert()?; - - let result = match actor.ask(HandleGrantCreate { basic, grant }).await { - Ok(grant_id) => EvmGrantCreateResult::GrantId(grant_id), - Err(kameo::error::SendError::HandlerError(GrantMutationError::VaultSealed)) => { - EvmGrantCreateResult::Error(ProtoEvmError::VaultSealed.into()) - } - Err(err) => { - warn!(error = ?err, "Failed to create EVM grant"); - EvmGrantCreateResult::Error(ProtoEvmError::Internal.into()) - } - }; - Ok(Some(wrap_evm_response(EvmResponsePayload::GrantCreate( - EvmGrantCreateResponse { - result: Some(result), - }, - )))) -} - -async fn handle_grant_delete( - actor: &ActorRef, - req: EvmGrantDeleteRequest, -) -> Result, Status> { - let result = match actor - .ask(HandleGrantDelete { - grant_id: req.grant_id, - }) - .await - { - Ok(()) => EvmGrantDeleteResult::Ok(()), - Err(kameo::error::SendError::HandlerError(GrantMutationError::VaultSealed)) => { - EvmGrantDeleteResult::Error(ProtoEvmError::VaultSealed.into()) - } - Err(err) => { - warn!(error = ?err, "Failed to delete EVM grant"); - EvmGrantDeleteResult::Error(ProtoEvmError::Internal.into()) - } - }; - Ok(Some(wrap_evm_response(EvmResponsePayload::GrantDelete( - EvmGrantDeleteResponse { - result: Some(result), - }, - )))) -} - -async fn handle_sign_transaction( - actor: &ActorRef, - req: ProtoSignTransactionRequest, -) -> Result, Status> { - let request = req - .request - .ok_or_else(|| Status::invalid_argument("Missing sign transaction request"))?; - let wallet_address = RawEvmAddress(request.wallet_address).try_convert()?; - let transaction = RawEvmTransaction(request.rlp_transaction).try_convert()?; - - let response = match actor - .ask(HandleSignTransaction { - client_id: req.client_id, - wallet_address, - transaction, - }) - .await - { - Ok(signature) => EvmSignTransactionResponse { - result: Some(EvmSignTransactionResult::Signature( - signature.as_bytes().to_vec(), - )), - }, - Err(kameo::error::SendError::HandlerError(SessionSignTransactionError::Vet(vet_error))) => { - EvmSignTransactionResponse { - result: Some(vet_error.convert()), - } - } - Err(kameo::error::SendError::HandlerError(SessionSignTransactionError::Internal)) => { - EvmSignTransactionResponse { - result: Some(EvmSignTransactionResult::Error( - ProtoEvmError::Internal.into(), - )), - } - } - Err(err) => { - warn!(error = ?err, "Failed to sign EVM transaction"); - EvmSignTransactionResponse { - result: Some(EvmSignTransactionResult::Error( - ProtoEvmError::Internal.into(), - )), - } - } - }; - - Ok(Some(wrap_evm_response( - EvmResponsePayload::SignTransaction(response), - ))) -} +use crate::{ + grpc::{ + Convert, TryConvert, + common::inbound::{RawEvmAddress, RawEvmTransaction}, + }, + peers::operator::{ + OperatorSession, + session::handlers::{ + GrantMutationError, HandleEvmWalletCreate, HandleEvmWalletList, HandleGrantCreate, + HandleGrantDelete, HandleGrantList, HandleSignTransaction, + SignTransactionError as SessionSignTransactionError, + }, + }, +}; +use arbiter_proto::proto::{ + evm::{ + EvmError as ProtoEvmError, EvmGrantCreateRequest, EvmGrantCreateResponse, + EvmGrantDeleteRequest, EvmGrantDeleteResponse, EvmGrantList, EvmGrantListResponse, + EvmSignTransactionResponse, GrantEntry, WalletCreateResponse, WalletEntry, WalletList, + WalletListResponse, evm_grant_create_response::Result as EvmGrantCreateResult, + evm_grant_delete_response::Result as EvmGrantDeleteResult, + evm_grant_list_response::Result as EvmGrantListResult, + evm_sign_transaction_response::Result as EvmSignTransactionResult, + wallet_create_response::Result as WalletCreateResult, + wallet_list_response::Result as WalletListResult, + }, + operator::{ + evm::{ + self as proto_evm, SignTransactionRequest as ProtoSignTransactionRequest, + request::Payload as EvmRequestPayload, response::Payload as EvmResponsePayload, + }, + operator_response::Payload as OperatorResponsePayload, + }, +}; + +use kameo::actor::ActorRef; +use tonic::Status; +use tracing::warn; + +const fn wrap_evm_response(payload: EvmResponsePayload) -> OperatorResponsePayload { + OperatorResponsePayload::Evm(proto_evm::Response { + payload: Some(payload), + }) +} + +pub(super) async fn dispatch( + actor: &ActorRef, + req: proto_evm::Request, +) -> Result, Status> { + let Some(payload) = req.payload else { + return Err(Status::invalid_argument("Missing EVM request payload")); + }; + + match payload { + EvmRequestPayload::WalletCreate(()) => handle_wallet_create(actor).await, + EvmRequestPayload::WalletList(()) => handle_wallet_list(actor).await, + EvmRequestPayload::GrantCreate(req) => handle_grant_create(actor, req).await, + EvmRequestPayload::GrantDelete(req) => handle_grant_delete(actor, req).await, + EvmRequestPayload::GrantList(_) => handle_grant_list(actor).await, + EvmRequestPayload::SignTransaction(req) => handle_sign_transaction(actor, req).await, + } +} + +async fn handle_wallet_create( + actor: &ActorRef, +) -> Result, Status> { + let result = match actor.ask(HandleEvmWalletCreate {}).await { + Ok((wallet_id, address)) => WalletCreateResult::Wallet(WalletEntry { + id: wallet_id, + address: address.to_vec(), + }), + Err(err) => { + warn!(error = ?err, "Failed to create EVM wallet"); + WalletCreateResult::Error(ProtoEvmError::Internal.into()) + } + }; + Ok(Some(wrap_evm_response(EvmResponsePayload::WalletCreate( + WalletCreateResponse { + result: Some(result), + }, + )))) +} + +async fn handle_wallet_list( + actor: &ActorRef, +) -> Result, Status> { + let result = match actor.ask(HandleEvmWalletList {}).await { + Ok(wallets) => WalletListResult::Wallets(WalletList { + wallets: wallets + .into_iter() + .map(|(id, address)| WalletEntry { + address: address.to_vec(), + id, + }) + .collect(), + }), + Err(err) => { + warn!(error = ?err, "Failed to list EVM wallets"); + WalletListResult::Error(ProtoEvmError::Internal.into()) + } + }; + Ok(Some(wrap_evm_response(EvmResponsePayload::WalletList( + WalletListResponse { + result: Some(result), + }, + )))) +} + +async fn handle_grant_list( + actor: &ActorRef, +) -> Result, Status> { + let result = match actor.ask(HandleGrantList {}).await { + Ok(grants) => EvmGrantListResult::Grants(EvmGrantList { + grants: grants + .into_iter() + .map(|grant| GrantEntry { + id: grant.common_settings_id, + wallet_access_id: grant.settings.shared.wallet_access_id, + shared: Some(grant.settings.shared.convert()), + specific: Some(grant.settings.specific.convert()), + }) + .collect(), + }), + Err(err) => { + warn!(error = ?err, "Failed to list EVM grants"); + EvmGrantListResult::Error(ProtoEvmError::Internal.into()) + } + }; + Ok(Some(wrap_evm_response(EvmResponsePayload::GrantList( + EvmGrantListResponse { + result: Some(result), + }, + )))) +} + +async fn handle_grant_create( + actor: &ActorRef, + req: EvmGrantCreateRequest, +) -> Result, Status> { + let basic = req + .shared + .ok_or_else(|| Status::invalid_argument("Missing shared grant settings"))? + .try_convert()?; + let grant = req + .specific + .ok_or_else(|| Status::invalid_argument("Missing specific grant settings"))? + .try_convert()?; + + let result = match actor.ask(HandleGrantCreate { basic, grant }).await { + Ok(grant_id) => EvmGrantCreateResult::GrantId(grant_id), + Err(kameo::error::SendError::HandlerError(GrantMutationError::VaultSealed)) => { + EvmGrantCreateResult::Error(ProtoEvmError::VaultSealed.into()) + } + Err(err) => { + warn!(error = ?err, "Failed to create EVM grant"); + EvmGrantCreateResult::Error(ProtoEvmError::Internal.into()) + } + }; + Ok(Some(wrap_evm_response(EvmResponsePayload::GrantCreate( + EvmGrantCreateResponse { + result: Some(result), + }, + )))) +} + +async fn handle_grant_delete( + actor: &ActorRef, + req: EvmGrantDeleteRequest, +) -> Result, Status> { + let result = match actor + .ask(HandleGrantDelete { + grant_id: req.grant_id, + }) + .await + { + Ok(()) => EvmGrantDeleteResult::Ok(()), + Err(kameo::error::SendError::HandlerError(GrantMutationError::VaultSealed)) => { + EvmGrantDeleteResult::Error(ProtoEvmError::VaultSealed.into()) + } + Err(err) => { + warn!(error = ?err, "Failed to delete EVM grant"); + EvmGrantDeleteResult::Error(ProtoEvmError::Internal.into()) + } + }; + Ok(Some(wrap_evm_response(EvmResponsePayload::GrantDelete( + EvmGrantDeleteResponse { + result: Some(result), + }, + )))) +} + +async fn handle_sign_transaction( + actor: &ActorRef, + req: ProtoSignTransactionRequest, +) -> Result, Status> { + let request = req + .request + .ok_or_else(|| Status::invalid_argument("Missing sign transaction request"))?; + let wallet_address = RawEvmAddress(request.wallet_address).try_convert()?; + let transaction = RawEvmTransaction(request.rlp_transaction).try_convert()?; + + let response = match actor + .ask(HandleSignTransaction { + client_id: req.client_id, + wallet_address, + transaction, + }) + .await + { + Ok(signature) => EvmSignTransactionResponse { + result: Some(EvmSignTransactionResult::Signature( + signature.as_bytes().to_vec(), + )), + }, + Err(kameo::error::SendError::HandlerError(SessionSignTransactionError::Vet(vet_error))) => { + EvmSignTransactionResponse { + result: Some(vet_error.convert()), + } + } + Err(kameo::error::SendError::HandlerError(SessionSignTransactionError::Internal)) => { + EvmSignTransactionResponse { + result: Some(EvmSignTransactionResult::Error( + ProtoEvmError::Internal.into(), + )), + } + } + Err(err) => { + warn!(error = ?err, "Failed to sign EVM transaction"); + EvmSignTransactionResponse { + result: Some(EvmSignTransactionResult::Error( + ProtoEvmError::Internal.into(), + )), + } + } + }; + + Ok(Some(wrap_evm_response( + EvmResponsePayload::SignTransaction(response), + ))) +} diff --git a/server/crates/arbiter-server/src/grpc/operator/inbound.rs b/server/crates/arbiter-server/src/grpc/operator/inbound.rs index d31c3f6..cb8039c 100644 --- a/server/crates/arbiter-server/src/grpc/operator/inbound.rs +++ b/server/crates/arbiter-server/src/grpc/operator/inbound.rs @@ -1,174 +1,174 @@ -use crate::{ - db::models::{CoreEvmWalletAccess, NewEvmWalletAccess}, - evm::policies::{ - SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit, ether_transfer, - token_transfers, - }, - grpc::Convert, - grpc::TryConvert, -}; -use arbiter_proto::{ - proto::evm::{ - EtherTransferSettings as ProtoEtherTransferSettings, SharedSettings as ProtoSharedSettings, - SpecificGrant as ProtoSpecificGrant, TokenTransferSettings as ProtoTokenTransferSettings, - TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit, - specific_grant::Grant as ProtoSpecificGrantType, - }, - proto::operator::sdk_client::{WalletAccess, WalletAccessEntry as SdkClientWalletAccess}, -}; - -use alloy::primitives::{Address, U256}; -use chrono::{DateTime, TimeZone, Utc}; -use prost_types::Timestamp as ProtoTimestamp; -use tonic::Status; - -fn address_from_bytes(bytes: &[u8]) -> Result { - if bytes.len() != 20 { - return Err(Status::invalid_argument("Invalid EVM address")); - } - Ok(Address::from_slice(bytes)) -} - -fn u256_from_proto_bytes(bytes: &[u8]) -> Result { - if bytes.len() > 32 { - return Err(Status::invalid_argument("Invalid U256 byte length")); - } - Ok(U256::from_be_slice(bytes)) -} - -impl TryConvert for ProtoTimestamp { - type Output = DateTime; - type Error = Status; - - fn try_convert(self) -> Result, Status> { - Utc.timestamp_opt(self.seconds, self.nanos.try_into().unwrap_or_default()) - .single() - .ok_or_else(|| Status::invalid_argument("Invalid timestamp")) - } -} - -impl TryConvert for ProtoTransactionRateLimit { - type Output = TransactionRateLimit; - type Error = Status; - - fn try_convert(self) -> Result { - Ok(TransactionRateLimit { - count: self.count, - window: chrono::Duration::seconds(self.window_secs), - }) - } -} - -impl TryConvert for ProtoVolumeRateLimit { - type Output = VolumeRateLimit; - type Error = Status; - - fn try_convert(self) -> Result { - Ok(VolumeRateLimit { - max_volume: u256_from_proto_bytes(&self.max_volume)?, - window: chrono::Duration::seconds(self.window_secs), - }) - } -} - -impl TryConvert for ProtoSharedSettings { - type Output = SharedGrantSettings; - type Error = Status; - - fn try_convert(self) -> Result { - Ok(SharedGrantSettings { - wallet_access_id: self.wallet_access_id, - chain: self.chain_id, - valid_from: self - .valid_from - .map(ProtoTimestamp::try_convert) - .transpose()?, - valid_until: self - .valid_until - .map(ProtoTimestamp::try_convert) - .transpose()?, - revoked_at: None, - max_gas_fee_per_gas: self - .max_gas_fee_per_gas - .as_deref() - .map(u256_from_proto_bytes) - .transpose()?, - max_priority_fee_per_gas: self - .max_priority_fee_per_gas - .as_deref() - .map(u256_from_proto_bytes) - .transpose()?, - rate_limit: self - .rate_limit - .map(ProtoTransactionRateLimit::try_convert) - .transpose()?, - }) - } -} - -impl TryConvert for ProtoSpecificGrant { - type Output = SpecificGrant; - type Error = Status; - - fn try_convert(self) -> Result { - match self.grant { - Some(ProtoSpecificGrantType::EtherTransfer(ProtoEtherTransferSettings { - targets, - limit, - })) => Ok(SpecificGrant::EtherTransfer(ether_transfer::Settings { - target: targets - .iter() - .map(Vec::as_slice) - .map(address_from_bytes) - .collect::>()?, - limit: limit - .ok_or_else(|| { - Status::invalid_argument("Missing ether transfer volume rate limit") - })? - .try_convert()?, - })), - Some(ProtoSpecificGrantType::TokenTransfer(ProtoTokenTransferSettings { - token_contract, - target, - volume_limits, - })) => Ok(SpecificGrant::TokenTransfer(token_transfers::Settings { - token_contract: address_from_bytes(&token_contract)?, - target: target - .map(|target| address_from_bytes(&target)) - .transpose()?, - volume_limits: volume_limits - .into_iter() - .map(ProtoVolumeRateLimit::try_convert) - .collect::>()?, - })), - None => Err(Status::invalid_argument("Missing specific grant kind")), - } - } -} - -impl Convert for WalletAccess { - type Output = NewEvmWalletAccess; - - fn convert(self) -> Self::Output { - NewEvmWalletAccess { - wallet_id: self.wallet_id, - client_id: self.sdk_client_id, - } - } -} - -impl TryConvert for SdkClientWalletAccess { - type Output = CoreEvmWalletAccess; - type Error = Status; - - fn try_convert(self) -> Result { - let Some(access) = self.access else { - return Err(Status::invalid_argument("Missing wallet access entry")); - }; - Ok(CoreEvmWalletAccess { - wallet_id: access.wallet_id, - client_id: access.sdk_client_id, - id: self.id, - }) - } -} +use crate::{ + db::models::{CoreEvmWalletAccess, NewEvmWalletAccess}, + evm::policies::{ + SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit, ether_transfer, + token_transfers, + }, + grpc::Convert, + grpc::TryConvert, +}; +use arbiter_proto::{ + proto::evm::{ + EtherTransferSettings as ProtoEtherTransferSettings, SharedSettings as ProtoSharedSettings, + SpecificGrant as ProtoSpecificGrant, TokenTransferSettings as ProtoTokenTransferSettings, + TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit, + specific_grant::Grant as ProtoSpecificGrantType, + }, + proto::operator::sdk_client::{WalletAccess, WalletAccessEntry as SdkClientWalletAccess}, +}; + +use alloy::primitives::{Address, U256}; +use chrono::{DateTime, TimeZone, Utc}; +use prost_types::Timestamp as ProtoTimestamp; +use tonic::Status; + +fn address_from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != 20 { + return Err(Status::invalid_argument("Invalid EVM address")); + } + Ok(Address::from_slice(bytes)) +} + +fn u256_from_proto_bytes(bytes: &[u8]) -> Result { + if bytes.len() > 32 { + return Err(Status::invalid_argument("Invalid U256 byte length")); + } + Ok(U256::from_be_slice(bytes)) +} + +impl TryConvert for ProtoTimestamp { + type Output = DateTime; + type Error = Status; + + fn try_convert(self) -> Result, Status> { + Utc.timestamp_opt(self.seconds, self.nanos.try_into().unwrap_or_default()) + .single() + .ok_or_else(|| Status::invalid_argument("Invalid timestamp")) + } +} + +impl TryConvert for ProtoTransactionRateLimit { + type Output = TransactionRateLimit; + type Error = Status; + + fn try_convert(self) -> Result { + Ok(TransactionRateLimit { + count: self.count, + window: chrono::Duration::seconds(self.window_secs), + }) + } +} + +impl TryConvert for ProtoVolumeRateLimit { + type Output = VolumeRateLimit; + type Error = Status; + + fn try_convert(self) -> Result { + Ok(VolumeRateLimit { + max_volume: u256_from_proto_bytes(&self.max_volume)?, + window: chrono::Duration::seconds(self.window_secs), + }) + } +} + +impl TryConvert for ProtoSharedSettings { + type Output = SharedGrantSettings; + type Error = Status; + + fn try_convert(self) -> Result { + Ok(SharedGrantSettings { + wallet_access_id: self.wallet_access_id, + chain: self.chain_id, + valid_from: self + .valid_from + .map(ProtoTimestamp::try_convert) + .transpose()?, + valid_until: self + .valid_until + .map(ProtoTimestamp::try_convert) + .transpose()?, + revoked_at: None, + max_gas_fee_per_gas: self + .max_gas_fee_per_gas + .as_deref() + .map(u256_from_proto_bytes) + .transpose()?, + max_priority_fee_per_gas: self + .max_priority_fee_per_gas + .as_deref() + .map(u256_from_proto_bytes) + .transpose()?, + rate_limit: self + .rate_limit + .map(ProtoTransactionRateLimit::try_convert) + .transpose()?, + }) + } +} + +impl TryConvert for ProtoSpecificGrant { + type Output = SpecificGrant; + type Error = Status; + + fn try_convert(self) -> Result { + match self.grant { + Some(ProtoSpecificGrantType::EtherTransfer(ProtoEtherTransferSettings { + targets, + limit, + })) => Ok(SpecificGrant::EtherTransfer(ether_transfer::Settings { + target: targets + .iter() + .map(Vec::as_slice) + .map(address_from_bytes) + .collect::>()?, + limit: limit + .ok_or_else(|| { + Status::invalid_argument("Missing ether transfer volume rate limit") + })? + .try_convert()?, + })), + Some(ProtoSpecificGrantType::TokenTransfer(ProtoTokenTransferSettings { + token_contract, + target, + volume_limits, + })) => Ok(SpecificGrant::TokenTransfer(token_transfers::Settings { + token_contract: address_from_bytes(&token_contract)?, + target: target + .map(|target| address_from_bytes(&target)) + .transpose()?, + volume_limits: volume_limits + .into_iter() + .map(ProtoVolumeRateLimit::try_convert) + .collect::>()?, + })), + None => Err(Status::invalid_argument("Missing specific grant kind")), + } + } +} + +impl Convert for WalletAccess { + type Output = NewEvmWalletAccess; + + fn convert(self) -> Self::Output { + NewEvmWalletAccess { + wallet_id: self.wallet_id, + client_id: self.sdk_client_id, + } + } +} + +impl TryConvert for SdkClientWalletAccess { + type Output = CoreEvmWalletAccess; + type Error = Status; + + fn try_convert(self) -> Result { + let Some(access) = self.access else { + return Err(Status::invalid_argument("Missing wallet access entry")); + }; + Ok(CoreEvmWalletAccess { + wallet_id: access.wallet_id, + client_id: access.sdk_client_id, + id: self.id, + }) + } +} diff --git a/server/crates/arbiter-server/src/grpc/operator/outbound.rs b/server/crates/arbiter-server/src/grpc/operator/outbound.rs index a4f4c29..c5e6de9 100644 --- a/server/crates/arbiter-server/src/grpc/operator/outbound.rs +++ b/server/crates/arbiter-server/src/grpc/operator/outbound.rs @@ -1,111 +1,111 @@ -use crate::{ - db::models::EvmWalletAccess, - evm::policies::{SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit}, - grpc::Convert, -}; -use arbiter_proto::proto::{ - evm::{ - EtherTransferSettings as ProtoEtherTransferSettings, SharedSettings as ProtoSharedSettings, - SpecificGrant as ProtoSpecificGrant, TokenTransferSettings as ProtoTokenTransferSettings, - TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit, - specific_grant::Grant as ProtoSpecificGrantType, - }, - operator::sdk_client::{WalletAccess, WalletAccessEntry as ProtoSdkClientWalletAccess}, -}; - -use chrono::{DateTime, Utc}; -use prost_types::Timestamp as ProtoTimestamp; - -impl Convert for DateTime { - type Output = ProtoTimestamp; - - fn convert(self) -> ProtoTimestamp { - ProtoTimestamp { - seconds: self.timestamp(), - nanos: self.timestamp_subsec_nanos().try_into().unwrap_or(i32::MAX), - } - } -} - -impl Convert for TransactionRateLimit { - type Output = ProtoTransactionRateLimit; - - fn convert(self) -> ProtoTransactionRateLimit { - ProtoTransactionRateLimit { - count: self.count, - window_secs: self.window.num_seconds(), - } - } -} - -impl Convert for VolumeRateLimit { - type Output = ProtoVolumeRateLimit; - - fn convert(self) -> ProtoVolumeRateLimit { - ProtoVolumeRateLimit { - max_volume: self.max_volume.to_be_bytes::<32>().to_vec(), - window_secs: self.window.num_seconds(), - } - } -} - -impl Convert for SharedGrantSettings { - type Output = ProtoSharedSettings; - - fn convert(self) -> ProtoSharedSettings { - ProtoSharedSettings { - wallet_access_id: self.wallet_access_id, - chain_id: self.chain, - valid_from: self.valid_from.map(DateTime::convert), - valid_until: self.valid_until.map(DateTime::convert), - max_gas_fee_per_gas: self - .max_gas_fee_per_gas - .map(|value| value.to_be_bytes::<32>().to_vec()), - max_priority_fee_per_gas: self - .max_priority_fee_per_gas - .map(|value| value.to_be_bytes::<32>().to_vec()), - rate_limit: self.rate_limit.map(TransactionRateLimit::convert), - } - } -} - -impl Convert for SpecificGrant { - type Output = ProtoSpecificGrant; - - fn convert(self) -> ProtoSpecificGrant { - let grant = match self { - Self::EtherTransfer(s) => { - ProtoSpecificGrantType::EtherTransfer(ProtoEtherTransferSettings { - targets: s.target.into_iter().map(|a| a.to_vec()).collect(), - limit: Some(s.limit.convert()), - }) - } - Self::TokenTransfer(s) => { - ProtoSpecificGrantType::TokenTransfer(ProtoTokenTransferSettings { - token_contract: s.token_contract.to_vec(), - target: s.target.map(|a| a.to_vec()), - volume_limits: s - .volume_limits - .into_iter() - .map(VolumeRateLimit::convert) - .collect(), - }) - } - }; - ProtoSpecificGrant { grant: Some(grant) } - } -} - -impl Convert for EvmWalletAccess { - type Output = ProtoSdkClientWalletAccess; - - fn convert(self) -> Self::Output { - Self::Output { - id: self.id, - access: Some(WalletAccess { - wallet_id: self.wallet_id, - sdk_client_id: self.client_id, - }), - } - } -} +use crate::{ + db::models::EvmWalletAccess, + evm::policies::{SharedGrantSettings, SpecificGrant, TransactionRateLimit, VolumeRateLimit}, + grpc::Convert, +}; +use arbiter_proto::proto::{ + evm::{ + EtherTransferSettings as ProtoEtherTransferSettings, SharedSettings as ProtoSharedSettings, + SpecificGrant as ProtoSpecificGrant, TokenTransferSettings as ProtoTokenTransferSettings, + TransactionRateLimit as ProtoTransactionRateLimit, VolumeRateLimit as ProtoVolumeRateLimit, + specific_grant::Grant as ProtoSpecificGrantType, + }, + operator::sdk_client::{WalletAccess, WalletAccessEntry as ProtoSdkClientWalletAccess}, +}; + +use chrono::{DateTime, Utc}; +use prost_types::Timestamp as ProtoTimestamp; + +impl Convert for DateTime { + type Output = ProtoTimestamp; + + fn convert(self) -> ProtoTimestamp { + ProtoTimestamp { + seconds: self.timestamp(), + nanos: self.timestamp_subsec_nanos().try_into().unwrap_or(i32::MAX), + } + } +} + +impl Convert for TransactionRateLimit { + type Output = ProtoTransactionRateLimit; + + fn convert(self) -> ProtoTransactionRateLimit { + ProtoTransactionRateLimit { + count: self.count, + window_secs: self.window.num_seconds(), + } + } +} + +impl Convert for VolumeRateLimit { + type Output = ProtoVolumeRateLimit; + + fn convert(self) -> ProtoVolumeRateLimit { + ProtoVolumeRateLimit { + max_volume: self.max_volume.to_be_bytes::<32>().to_vec(), + window_secs: self.window.num_seconds(), + } + } +} + +impl Convert for SharedGrantSettings { + type Output = ProtoSharedSettings; + + fn convert(self) -> ProtoSharedSettings { + ProtoSharedSettings { + wallet_access_id: self.wallet_access_id, + chain_id: self.chain, + valid_from: self.valid_from.map(DateTime::convert), + valid_until: self.valid_until.map(DateTime::convert), + max_gas_fee_per_gas: self + .max_gas_fee_per_gas + .map(|value| value.to_be_bytes::<32>().to_vec()), + max_priority_fee_per_gas: self + .max_priority_fee_per_gas + .map(|value| value.to_be_bytes::<32>().to_vec()), + rate_limit: self.rate_limit.map(TransactionRateLimit::convert), + } + } +} + +impl Convert for SpecificGrant { + type Output = ProtoSpecificGrant; + + fn convert(self) -> ProtoSpecificGrant { + let grant = match self { + Self::EtherTransfer(s) => { + ProtoSpecificGrantType::EtherTransfer(ProtoEtherTransferSettings { + targets: s.target.into_iter().map(|a| a.to_vec()).collect(), + limit: Some(s.limit.convert()), + }) + } + Self::TokenTransfer(s) => { + ProtoSpecificGrantType::TokenTransfer(ProtoTokenTransferSettings { + token_contract: s.token_contract.to_vec(), + target: s.target.map(|a| a.to_vec()), + volume_limits: s + .volume_limits + .into_iter() + .map(VolumeRateLimit::convert) + .collect(), + }) + } + }; + ProtoSpecificGrant { grant: Some(grant) } + } +} + +impl Convert for EvmWalletAccess { + type Output = ProtoSdkClientWalletAccess; + + fn convert(self) -> Self::Output { + Self::Output { + id: self.id, + access: Some(WalletAccess { + wallet_id: self.wallet_id, + sdk_client_id: self.client_id, + }), + } + } +} diff --git a/server/crates/arbiter-server/src/grpc/operator/sdk_client.rs b/server/crates/arbiter-server/src/grpc/operator/sdk_client.rs index b88a73e..f529d05 100644 --- a/server/crates/arbiter-server/src/grpc/operator/sdk_client.rs +++ b/server/crates/arbiter-server/src/grpc/operator/sdk_client.rs @@ -1,198 +1,198 @@ -use crate::{ - db::models::NewEvmWalletAccess, - grpc::Convert, - peers::operator::{ - OutOfBand, OperatorSession, - session::handlers::{ - HandleGrantEvmWalletAccess, HandleListWalletAccess, HandleNewClientApprove, - HandleRevokeEvmWalletAccess, HandleSdkClientList, - }, - }, -}; -use arbiter_crypto::authn; -use arbiter_proto::proto::{ - shared::ClientInfo as ProtoClientMetadata, - operator::{ - sdk_client::{ - self as proto_sdk_client, ConnectionCancel as ProtoSdkClientConnectionCancel, - ConnectionRequest as ProtoSdkClientConnectionRequest, - ConnectionResponse as ProtoSdkClientConnectionResponse, Entry as ProtoSdkClientEntry, - Error as ProtoSdkClientError, GrantWalletAccess as ProtoSdkClientGrantWalletAccess, - List as ProtoSdkClientList, ListResponse as ProtoSdkClientListResponse, - ListWalletAccessResponse, RevokeWalletAccess as ProtoSdkClientRevokeWalletAccess, - list_response::Result as ProtoSdkClientListResult, - request::Payload as SdkClientRequestPayload, - response::Payload as SdkClientResponsePayload, - }, - operator_response::Payload as OperatorResponsePayload, - }, -}; - -use kameo::actor::ActorRef; -use tonic::Status; -use tracing::{info, warn}; - -const fn wrap_sdk_client_response(payload: SdkClientResponsePayload) -> OperatorResponsePayload { - OperatorResponsePayload::SdkClient(proto_sdk_client::Response { - payload: Some(payload), - }) -} - -pub(super) fn out_of_band_payload(oob: OutOfBand) -> OperatorResponsePayload { - match oob { - OutOfBand::ClientConnectionRequest { profile } => wrap_sdk_client_response( - SdkClientResponsePayload::ConnectionRequest(ProtoSdkClientConnectionRequest { - pubkey: profile.pubkey.to_bytes(), - info: Some(ProtoClientMetadata { - name: profile.metadata.name, - description: profile.metadata.description, - version: profile.metadata.version, - }), - }), - ), - OutOfBand::ClientConnectionCancel { pubkey } => wrap_sdk_client_response( - SdkClientResponsePayload::ConnectionCancel(ProtoSdkClientConnectionCancel { - pubkey: pubkey.to_bytes(), - }), - ), - } -} - -pub(super) async fn dispatch( - actor: &ActorRef, - req: proto_sdk_client::Request, -) -> Result, Status> { - let Some(payload) = req.payload else { - return Err(Status::invalid_argument( - "Missing SDK client request payload", - )); - }; - - match payload { - SdkClientRequestPayload::ConnectionResponse(resp) => { - handle_connection_response(actor, resp).await - } - SdkClientRequestPayload::Revoke(_) => Err(Status::unimplemented( - "SdkClientRevoke is not yet implemented", - )), - SdkClientRequestPayload::List(()) => handle_list(actor).await, - SdkClientRequestPayload::GrantWalletAccess(req) => { - handle_grant_wallet_access(actor, req).await - } - SdkClientRequestPayload::RevokeWalletAccess(req) => { - handle_revoke_wallet_access(actor, req).await - } - SdkClientRequestPayload::ListWalletAccess(()) => handle_list_wallet_access(actor).await, - } -} - -async fn handle_connection_response( - actor: &ActorRef, - resp: ProtoSdkClientConnectionResponse, -) -> Result, Status> { - let pubkey = authn::PublicKey::try_from(resp.pubkey.as_slice()) - .map_err(|()| Status::invalid_argument("Invalid ML-DSA public key"))?; - - actor - .ask(HandleNewClientApprove { - approved: resp.approved, - pubkey, - }) - .await - .map_err(|err| { - warn!(?err, "Failed to process client connection response"); - Status::internal("Failed to process response") - })?; - - Ok(None) -} - -async fn handle_list( - actor: &ActorRef, -) -> Result, Status> { - let result = match actor.ask(HandleSdkClientList {}).await { - Ok(clients) => ProtoSdkClientListResult::Clients(ProtoSdkClientList { - clients: clients - .into_iter() - .map(|(client, metadata)| ProtoSdkClientEntry { - id: client.id, - pubkey: client.public_key.clone(), - info: Some(ProtoClientMetadata { - name: metadata.name, - description: metadata.description, - version: metadata.version, - }), - #[expect( - clippy::cast_possible_truncation, - clippy::as_conversions, - reason = "fixme! #84" - )] - created_at: client.created_at.0.timestamp() as i32, - }) - .collect(), - }), - Err(err) => { - warn!(error = ?err, "Failed to list SDK clients"); - ProtoSdkClientListResult::Error(ProtoSdkClientError::Internal.into()) - } - }; - Ok(Some(wrap_sdk_client_response( - SdkClientResponsePayload::List(ProtoSdkClientListResponse { - result: Some(result), - }), - ))) -} - -async fn handle_grant_wallet_access( - actor: &ActorRef, - req: ProtoSdkClientGrantWalletAccess, -) -> Result, Status> { - let entries: Vec = req.accesses.into_iter().map(Convert::convert).collect(); - match actor.ask(HandleGrantEvmWalletAccess { entries }).await { - Ok(()) => { - info!("Successfully granted wallet access"); - Ok(None) - } - Err(err) => { - warn!(error = ?err, "Failed to grant wallet access"); - Err(Status::internal("Failed to grant wallet access")) - } - } -} - -async fn handle_revoke_wallet_access( - actor: &ActorRef, - req: ProtoSdkClientRevokeWalletAccess, -) -> Result, Status> { - match actor - .ask(HandleRevokeEvmWalletAccess { - entries: req.accesses, - }) - .await - { - Ok(()) => { - info!("Successfully revoked wallet access"); - Ok(None) - } - Err(err) => { - warn!(error = ?err, "Failed to revoke wallet access"); - Err(Status::internal("Failed to revoke wallet access")) - } - } -} - -async fn handle_list_wallet_access( - actor: &ActorRef, -) -> Result, Status> { - match actor.ask(HandleListWalletAccess {}).await { - Ok(accesses) => Ok(Some(wrap_sdk_client_response( - SdkClientResponsePayload::ListWalletAccess(ListWalletAccessResponse { - accesses: accesses.into_iter().map(Convert::convert).collect(), - }), - ))), - Err(err) => { - warn!(error = ?err, "Failed to list wallet access"); - Err(Status::internal("Failed to list wallet access")) - } - } -} +use crate::{ + db::models::NewEvmWalletAccess, + grpc::Convert, + peers::operator::{ + OutOfBand, OperatorSession, + session::handlers::{ + HandleGrantEvmWalletAccess, HandleListWalletAccess, HandleNewClientApprove, + HandleRevokeEvmWalletAccess, HandleSdkClientList, + }, + }, +}; +use arbiter_crypto::authn; +use arbiter_proto::proto::{ + shared::ClientInfo as ProtoClientMetadata, + operator::{ + sdk_client::{ + self as proto_sdk_client, ConnectionCancel as ProtoSdkClientConnectionCancel, + ConnectionRequest as ProtoSdkClientConnectionRequest, + ConnectionResponse as ProtoSdkClientConnectionResponse, Entry as ProtoSdkClientEntry, + Error as ProtoSdkClientError, GrantWalletAccess as ProtoSdkClientGrantWalletAccess, + List as ProtoSdkClientList, ListResponse as ProtoSdkClientListResponse, + ListWalletAccessResponse, RevokeWalletAccess as ProtoSdkClientRevokeWalletAccess, + list_response::Result as ProtoSdkClientListResult, + request::Payload as SdkClientRequestPayload, + response::Payload as SdkClientResponsePayload, + }, + operator_response::Payload as OperatorResponsePayload, + }, +}; + +use kameo::actor::ActorRef; +use tonic::Status; +use tracing::{info, warn}; + +const fn wrap_sdk_client_response(payload: SdkClientResponsePayload) -> OperatorResponsePayload { + OperatorResponsePayload::SdkClient(proto_sdk_client::Response { + payload: Some(payload), + }) +} + +pub(super) fn out_of_band_payload(oob: OutOfBand) -> OperatorResponsePayload { + match oob { + OutOfBand::ClientConnectionRequest { profile } => wrap_sdk_client_response( + SdkClientResponsePayload::ConnectionRequest(ProtoSdkClientConnectionRequest { + pubkey: profile.pubkey.to_bytes(), + info: Some(ProtoClientMetadata { + name: profile.metadata.name, + description: profile.metadata.description, + version: profile.metadata.version, + }), + }), + ), + OutOfBand::ClientConnectionCancel { pubkey } => wrap_sdk_client_response( + SdkClientResponsePayload::ConnectionCancel(ProtoSdkClientConnectionCancel { + pubkey: pubkey.to_bytes(), + }), + ), + } +} + +pub(super) async fn dispatch( + actor: &ActorRef, + req: proto_sdk_client::Request, +) -> Result, Status> { + let Some(payload) = req.payload else { + return Err(Status::invalid_argument( + "Missing SDK client request payload", + )); + }; + + match payload { + SdkClientRequestPayload::ConnectionResponse(resp) => { + handle_connection_response(actor, resp).await + } + SdkClientRequestPayload::Revoke(_) => Err(Status::unimplemented( + "SdkClientRevoke is not yet implemented", + )), + SdkClientRequestPayload::List(()) => handle_list(actor).await, + SdkClientRequestPayload::GrantWalletAccess(req) => { + handle_grant_wallet_access(actor, req).await + } + SdkClientRequestPayload::RevokeWalletAccess(req) => { + handle_revoke_wallet_access(actor, req).await + } + SdkClientRequestPayload::ListWalletAccess(()) => handle_list_wallet_access(actor).await, + } +} + +async fn handle_connection_response( + actor: &ActorRef, + resp: ProtoSdkClientConnectionResponse, +) -> Result, Status> { + let pubkey = authn::PublicKey::try_from(resp.pubkey.as_slice()) + .map_err(|()| Status::invalid_argument("Invalid ML-DSA public key"))?; + + actor + .ask(HandleNewClientApprove { + approved: resp.approved, + pubkey, + }) + .await + .map_err(|err| { + warn!(?err, "Failed to process client connection response"); + Status::internal("Failed to process response") + })?; + + Ok(None) +} + +async fn handle_list( + actor: &ActorRef, +) -> Result, Status> { + let result = match actor.ask(HandleSdkClientList {}).await { + Ok(clients) => ProtoSdkClientListResult::Clients(ProtoSdkClientList { + clients: clients + .into_iter() + .map(|(client, metadata)| ProtoSdkClientEntry { + id: client.id, + pubkey: client.public_key.clone(), + info: Some(ProtoClientMetadata { + name: metadata.name, + description: metadata.description, + version: metadata.version, + }), + #[expect( + clippy::cast_possible_truncation, + clippy::as_conversions, + reason = "fixme! #84" + )] + created_at: client.created_at.0.timestamp() as i32, + }) + .collect(), + }), + Err(err) => { + warn!(error = ?err, "Failed to list SDK clients"); + ProtoSdkClientListResult::Error(ProtoSdkClientError::Internal.into()) + } + }; + Ok(Some(wrap_sdk_client_response( + SdkClientResponsePayload::List(ProtoSdkClientListResponse { + result: Some(result), + }), + ))) +} + +async fn handle_grant_wallet_access( + actor: &ActorRef, + req: ProtoSdkClientGrantWalletAccess, +) -> Result, Status> { + let entries: Vec = req.accesses.into_iter().map(Convert::convert).collect(); + match actor.ask(HandleGrantEvmWalletAccess { entries }).await { + Ok(()) => { + info!("Successfully granted wallet access"); + Ok(None) + } + Err(err) => { + warn!(error = ?err, "Failed to grant wallet access"); + Err(Status::internal("Failed to grant wallet access")) + } + } +} + +async fn handle_revoke_wallet_access( + actor: &ActorRef, + req: ProtoSdkClientRevokeWalletAccess, +) -> Result, Status> { + match actor + .ask(HandleRevokeEvmWalletAccess { + entries: req.accesses, + }) + .await + { + Ok(()) => { + info!("Successfully revoked wallet access"); + Ok(None) + } + Err(err) => { + warn!(error = ?err, "Failed to revoke wallet access"); + Err(Status::internal("Failed to revoke wallet access")) + } + } +} + +async fn handle_list_wallet_access( + actor: &ActorRef, +) -> Result, Status> { + match actor.ask(HandleListWalletAccess {}).await { + Ok(accesses) => Ok(Some(wrap_sdk_client_response( + SdkClientResponsePayload::ListWalletAccess(ListWalletAccessResponse { + accesses: accesses.into_iter().map(Convert::convert).collect(), + }), + ))), + Err(err) => { + warn!(error = ?err, "Failed to list wallet access"); + Err(Status::internal("Failed to list wallet access")) + } + } +} diff --git a/server/crates/arbiter-server/src/grpc/operator/vault.rs b/server/crates/arbiter-server/src/grpc/operator/vault.rs index ac1c293..8eeb44a 100644 --- a/server/crates/arbiter-server/src/grpc/operator/vault.rs +++ b/server/crates/arbiter-server/src/grpc/operator/vault.rs @@ -1,59 +1,59 @@ -use crate::{ - actors::vault::VaultState, - peers::operator::{OperatorSession, session::handlers::HandleQueryVaultState}, -}; -use arbiter_proto::{ - proto::shared::VaultState as ProtoVaultState, - proto::operator::{ - operator_response::Payload as OperatorResponsePayload, - vault::{ - self as proto_vault, request::Payload as VaultRequestPayload, - response::Payload as VaultResponsePayload, - }, - }, -}; - -use kameo::actor::ActorRef; -use tonic::Status; -use tracing::warn; - -const fn wrap_vault_response(payload: VaultResponsePayload) -> OperatorResponsePayload { - OperatorResponsePayload::Vault(proto_vault::Response { - payload: Some(payload), - }) -} - -pub(super) async fn dispatch( - actor: &ActorRef, - req: proto_vault::Request, -) -> Result, Status> { - let Some(payload) = req.payload else { - return Err(Status::invalid_argument("Missing vault request payload")); - }; - - match payload { - VaultRequestPayload::QueryState(()) => handle_query_vault_state(actor).await, - VaultRequestPayload::Unseal(_) | VaultRequestPayload::Bootstrap(_) => { - Err(Status::permission_denied( - "Vault is already unsealed; unseal/bootstrap not permitted in session", - )) - } - } -} - -async fn handle_query_vault_state( - actor: &ActorRef, -) -> Result, Status> { - let state = match actor.ask(HandleQueryVaultState {}).await { - Ok(VaultState::Unbootstrapped) => ProtoVaultState::Unbootstrapped, - Ok(VaultState::Sealed) => ProtoVaultState::Sealed, - Ok(VaultState::Unsealed) => ProtoVaultState::Unsealed, - Err(err) => { - warn!(error = ?err, "Failed to query vault state"); - ProtoVaultState::Error - } - }; - Ok(Some(wrap_vault_response(VaultResponsePayload::State( - state.into(), - )))) -} +use crate::{ + actors::vault::VaultState, + peers::operator::{OperatorSession, session::handlers::HandleQueryVaultState}, +}; +use arbiter_proto::{ + proto::shared::VaultState as ProtoVaultState, + proto::operator::{ + operator_response::Payload as OperatorResponsePayload, + vault::{ + self as proto_vault, request::Payload as VaultRequestPayload, + response::Payload as VaultResponsePayload, + }, + }, +}; + +use kameo::actor::ActorRef; +use tonic::Status; +use tracing::warn; + +const fn wrap_vault_response(payload: VaultResponsePayload) -> OperatorResponsePayload { + OperatorResponsePayload::Vault(proto_vault::Response { + payload: Some(payload), + }) +} + +pub(super) async fn dispatch( + actor: &ActorRef, + req: proto_vault::Request, +) -> Result, Status> { + let Some(payload) = req.payload else { + return Err(Status::invalid_argument("Missing vault request payload")); + }; + + match payload { + VaultRequestPayload::QueryState(()) => handle_query_vault_state(actor).await, + VaultRequestPayload::Unseal(_) | VaultRequestPayload::Bootstrap(_) => { + Err(Status::permission_denied( + "Vault is already unsealed; unseal/bootstrap not permitted in session", + )) + } + } +} + +async fn handle_query_vault_state( + actor: &ActorRef, +) -> Result, Status> { + let state = match actor.ask(HandleQueryVaultState {}).await { + Ok(VaultState::Unbootstrapped) => ProtoVaultState::Unbootstrapped, + Ok(VaultState::Sealed) => ProtoVaultState::Sealed, + Ok(VaultState::Unsealed) => ProtoVaultState::Unsealed, + Err(err) => { + warn!(error = ?err, "Failed to query vault state"); + ProtoVaultState::Error + } + }; + Ok(Some(wrap_vault_response(VaultResponsePayload::State( + state.into(), + )))) +} diff --git a/server/crates/arbiter-server/src/grpc/operator/vault_gate.rs b/server/crates/arbiter-server/src/grpc/operator/vault_gate.rs index 2d5bc6c..f743b62 100644 --- a/server/crates/arbiter-server/src/grpc/operator/vault_gate.rs +++ b/server/crates/arbiter-server/src/grpc/operator/vault_gate.rs @@ -1,79 +1,79 @@ -use super::auth::AuthTransportAdapter; -use crate::{ - grpc::TryConvert, - peers::operator::vault_gate::{self as vault_gate}, -}; -use arbiter_proto::transport::{Bi, Error as TransportError, Receiver, Sender}; - -use async_trait::async_trait; -use tonic::Status; -use tracing::warn; - -mod inbound; -mod outbound; - -#[async_trait] -impl Receiver for AuthTransportAdapter<'_> { - async fn recv(&mut self) -> Option { - let request = match self.bi_mut().recv().await? { - Ok(request) => request, - Err(error) => { - warn!( - ?error, - "Failed to receive operator request during vault gate" - ); - return None; - } - }; - - if let Err(err) = self.tracker_mut().request(request.id) { - let _ = self.bi_mut().send(Err(err)).await; - return None; - } - - let Some(payload) = request.payload else { - let _ = self - .bi_mut() - .send(Err(Status::invalid_argument("Missing request payload"))) - .await; - return None; - }; - - match payload.try_convert() { - Ok(inbound) => Some(inbound), - Err(status) => { - let _ = self.bi_mut().send(Err(status)).await; - None - } - } - } -} - -#[async_trait] -impl Sender> for AuthTransportAdapter<'_> { - async fn send( - &mut self, - item: Result, - ) -> Result<(), TransportError> { - let outbound = match item { - Ok(outbound) => outbound, - Err(err) => { - warn!(?err, "vault gate produced transport-level error"); - return self - .bi_mut() - .send(Err(Status::internal(err.to_string()))) - .await; - } - }; - - match outbound.try_convert() { - Ok(payload) => self.send_response_payload(payload).await, - Err(status) => self.bi_mut().send(Err(status)).await, - } - } -} - -impl Bi> - for AuthTransportAdapter<'_> -{ -} +use super::auth::AuthTransportAdapter; +use crate::{ + grpc::TryConvert, + peers::operator::vault_gate::{self as vault_gate}, +}; +use arbiter_proto::transport::{Bi, Error as TransportError, Receiver, Sender}; + +use async_trait::async_trait; +use tonic::Status; +use tracing::warn; + +mod inbound; +mod outbound; + +#[async_trait] +impl Receiver for AuthTransportAdapter<'_> { + async fn recv(&mut self) -> Option { + let request = match self.bi_mut().recv().await? { + Ok(request) => request, + Err(error) => { + warn!( + ?error, + "Failed to receive operator request during vault gate" + ); + return None; + } + }; + + if let Err(err) = self.tracker_mut().request(request.id) { + let _ = self.bi_mut().send(Err(err)).await; + return None; + } + + let Some(payload) = request.payload else { + let _ = self + .bi_mut() + .send(Err(Status::invalid_argument("Missing request payload"))) + .await; + return None; + }; + + match payload.try_convert() { + Ok(inbound) => Some(inbound), + Err(status) => { + let _ = self.bi_mut().send(Err(status)).await; + None + } + } + } +} + +#[async_trait] +impl Sender> for AuthTransportAdapter<'_> { + async fn send( + &mut self, + item: Result, + ) -> Result<(), TransportError> { + let outbound = match item { + Ok(outbound) => outbound, + Err(err) => { + warn!(?err, "vault gate produced transport-level error"); + return self + .bi_mut() + .send(Err(Status::internal(err.to_string()))) + .await; + } + }; + + match outbound.try_convert() { + Ok(payload) => self.send_response_payload(payload).await, + Err(status) => self.bi_mut().send(Err(status)).await, + } + } +} + +impl Bi> + for AuthTransportAdapter<'_> +{ +} diff --git a/server/crates/arbiter-server/src/grpc/operator/vault_gate/inbound.rs b/server/crates/arbiter-server/src/grpc/operator/vault_gate/inbound.rs index 6a08235..c987a45 100644 --- a/server/crates/arbiter-server/src/grpc/operator/vault_gate/inbound.rs +++ b/server/crates/arbiter-server/src/grpc/operator/vault_gate/inbound.rs @@ -1,129 +1,129 @@ -use crate::{ - grpc::{Convert, TryConvert}, - peers::operator::vault_gate::{ - self as vault_gate, HandleBootstrapEncryptedKey, HandleHandshake, HandleUnsealEncryptedKey, - }, -}; -use arbiter_proto::proto::operator::{ - operator_request::Payload as OperatorRequestPayload, - vault::{ - self as proto_vault, - bootstrap::{self as proto_bootstrap}, - request::Payload as VaultRequestPayload, - unseal::{self as proto_unseal, request::Payload as UnsealRequestPayload}, - }, -}; - -use tonic::Status; - -impl TryConvert for OperatorRequestPayload { - type Output = vault_gate::Inbound; - type Error = Status; - - fn try_convert(self) -> Result { - match self { - Self::Vault(req) => req.try_convert(), - _ => Err(Status::permission_denied( - "Only vault operations are permitted before unsealing", - )), - } - } -} - -impl TryConvert for proto_vault::Request { - type Output = vault_gate::Inbound; - type Error = Status; - - fn try_convert(self) -> Result { - self.payload - .ok_or_else(|| Status::invalid_argument("Missing vault request payload"))? - .try_convert() - } -} - -impl TryConvert for VaultRequestPayload { - type Output = vault_gate::Inbound; - type Error = Status; - - fn try_convert(self) -> Result { - match self { - Self::QueryState(()) => Ok(vault_gate::Inbound::HandleVaultState), - Self::Unseal(req) => req.try_convert(), - Self::Bootstrap(req) => req.try_convert(), - } - } -} - -impl TryConvert for proto_unseal::Request { - type Output = vault_gate::Inbound; - type Error = Status; - - fn try_convert(self) -> Result { - self.payload - .ok_or_else(|| Status::invalid_argument("Missing unseal request payload"))? - .try_convert() - } -} - -impl TryConvert for UnsealRequestPayload { - type Output = vault_gate::Inbound; - type Error = Status; - - fn try_convert(self) -> Result { - match self { - Self::Start(start) => start.try_convert(), - Self::EncryptedKey(key) => Ok(key.convert()), - } - } -} - -impl TryConvert for proto_unseal::UnsealStart { - type Output = vault_gate::Inbound; - type Error = Status; - - fn try_convert(self) -> Result { - let bytes = <[u8; 32]>::try_from(self.client_pubkey) - .map_err(|_| Status::invalid_argument("Invalid X25519 public key"))?; - Ok(vault_gate::Inbound::HandleHandshake(HandleHandshake { - client_pubkey: x25519_dalek::PublicKey::from(bytes), - })) - } -} - -impl Convert for proto_unseal::UnsealEncryptedKey { - type Output = vault_gate::Inbound; - - fn convert(self) -> vault_gate::Inbound { - vault_gate::Inbound::HandleUnsealEncryptedKey(HandleUnsealEncryptedKey { - nonce: self.nonce, - ciphertext: self.ciphertext, - associated_data: self.associated_data, - }) - } -} - -impl TryConvert for proto_bootstrap::Request { - type Output = vault_gate::Inbound; - type Error = Status; - - fn try_convert(self) -> Result { - self.encrypted_key - .ok_or_else(|| Status::invalid_argument("Missing bootstrap encrypted key"))? - .try_convert() - } -} - -impl TryConvert for proto_bootstrap::BootstrapEncryptedKey { - type Output = vault_gate::Inbound; - type Error = Status; - - fn try_convert(self) -> Result { - Ok(vault_gate::Inbound::HandleBootstrapEncryptedKey( - HandleBootstrapEncryptedKey { - nonce: self.nonce, - ciphertext: self.ciphertext, - associated_data: self.associated_data, - }, - )) - } -} +use crate::{ + grpc::{Convert, TryConvert}, + peers::operator::vault_gate::{ + self as vault_gate, HandleBootstrapEncryptedKey, HandleHandshake, HandleUnsealEncryptedKey, + }, +}; +use arbiter_proto::proto::operator::{ + operator_request::Payload as OperatorRequestPayload, + vault::{ + self as proto_vault, + bootstrap::{self as proto_bootstrap}, + request::Payload as VaultRequestPayload, + unseal::{self as proto_unseal, request::Payload as UnsealRequestPayload}, + }, +}; + +use tonic::Status; + +impl TryConvert for OperatorRequestPayload { + type Output = vault_gate::Inbound; + type Error = Status; + + fn try_convert(self) -> Result { + match self { + Self::Vault(req) => req.try_convert(), + _ => Err(Status::permission_denied( + "Only vault operations are permitted before unsealing", + )), + } + } +} + +impl TryConvert for proto_vault::Request { + type Output = vault_gate::Inbound; + type Error = Status; + + fn try_convert(self) -> Result { + self.payload + .ok_or_else(|| Status::invalid_argument("Missing vault request payload"))? + .try_convert() + } +} + +impl TryConvert for VaultRequestPayload { + type Output = vault_gate::Inbound; + type Error = Status; + + fn try_convert(self) -> Result { + match self { + Self::QueryState(()) => Ok(vault_gate::Inbound::HandleVaultState), + Self::Unseal(req) => req.try_convert(), + Self::Bootstrap(req) => req.try_convert(), + } + } +} + +impl TryConvert for proto_unseal::Request { + type Output = vault_gate::Inbound; + type Error = Status; + + fn try_convert(self) -> Result { + self.payload + .ok_or_else(|| Status::invalid_argument("Missing unseal request payload"))? + .try_convert() + } +} + +impl TryConvert for UnsealRequestPayload { + type Output = vault_gate::Inbound; + type Error = Status; + + fn try_convert(self) -> Result { + match self { + Self::Start(start) => start.try_convert(), + Self::EncryptedKey(key) => Ok(key.convert()), + } + } +} + +impl TryConvert for proto_unseal::UnsealStart { + type Output = vault_gate::Inbound; + type Error = Status; + + fn try_convert(self) -> Result { + let bytes = <[u8; 32]>::try_from(self.client_pubkey) + .map_err(|_| Status::invalid_argument("Invalid X25519 public key"))?; + Ok(vault_gate::Inbound::HandleHandshake(HandleHandshake { + client_pubkey: x25519_dalek::PublicKey::from(bytes), + })) + } +} + +impl Convert for proto_unseal::UnsealEncryptedKey { + type Output = vault_gate::Inbound; + + fn convert(self) -> vault_gate::Inbound { + vault_gate::Inbound::HandleUnsealEncryptedKey(HandleUnsealEncryptedKey { + nonce: self.nonce, + ciphertext: self.ciphertext, + associated_data: self.associated_data, + }) + } +} + +impl TryConvert for proto_bootstrap::Request { + type Output = vault_gate::Inbound; + type Error = Status; + + fn try_convert(self) -> Result { + self.encrypted_key + .ok_or_else(|| Status::invalid_argument("Missing bootstrap encrypted key"))? + .try_convert() + } +} + +impl TryConvert for proto_bootstrap::BootstrapEncryptedKey { + type Output = vault_gate::Inbound; + type Error = Status; + + fn try_convert(self) -> Result { + Ok(vault_gate::Inbound::HandleBootstrapEncryptedKey( + HandleBootstrapEncryptedKey { + nonce: self.nonce, + ciphertext: self.ciphertext, + associated_data: self.associated_data, + }, + )) + } +} diff --git a/server/crates/arbiter-server/src/grpc/operator/vault_gate/outbound.rs b/server/crates/arbiter-server/src/grpc/operator/vault_gate/outbound.rs index 4a2f072..28c8388 100644 --- a/server/crates/arbiter-server/src/grpc/operator/vault_gate/outbound.rs +++ b/server/crates/arbiter-server/src/grpc/operator/vault_gate/outbound.rs @@ -1,115 +1,115 @@ -use crate::{ - actors::vault::VaultState, - grpc::{Convert, TryConvert}, - peers::operator::vault_gate::{self as vault_gate}, -}; -use arbiter_proto::proto::{ - shared::VaultState as ProtoVaultState, - operator::{ - operator_response::Payload as OperatorResponsePayload, - vault::{ - self as proto_vault, - bootstrap::{self as proto_bootstrap, BootstrapResult as ProtoBootstrapResult}, - response::Payload as VaultResponsePayload, - unseal::{ - self as proto_unseal, UnsealResult as ProtoUnsealResult, - response::Payload as UnsealResponsePayload, - }, - }, - }, -}; - -use tonic::Status; -use tracing::warn; - -const fn wrap_vault_response(payload: VaultResponsePayload) -> OperatorResponsePayload { - OperatorResponsePayload::Vault(proto_vault::Response { - payload: Some(payload), - }) -} - -const fn wrap_unseal_response(payload: UnsealResponsePayload) -> OperatorResponsePayload { - wrap_vault_response(VaultResponsePayload::Unseal(proto_unseal::Response { - payload: Some(payload), - })) -} - -fn wrap_bootstrap_response(result: ProtoBootstrapResult) -> OperatorResponsePayload { - wrap_vault_response(VaultResponsePayload::Bootstrap(proto_bootstrap::Response { - result: result.into(), - })) -} - -impl Convert for VaultState { - type Output = OperatorResponsePayload; - - fn convert(self) -> OperatorResponsePayload { - let proto_state = match self { - Self::Unbootstrapped => ProtoVaultState::Unbootstrapped, - Self::Sealed => ProtoVaultState::Sealed, - Self::Unsealed => ProtoVaultState::Unsealed, - }; - wrap_vault_response(VaultResponsePayload::State(proto_state.into())) - } -} - -impl Convert for vault_gate::HandshakeResponse { - type Output = OperatorResponsePayload; - - fn convert(self) -> OperatorResponsePayload { - wrap_unseal_response(UnsealResponsePayload::Start( - proto_unseal::UnsealStartResponse { - server_pubkey: self.server_pubkey.as_bytes().to_vec(), - }, - )) - } -} - -impl TryConvert for vault_gate::Outbound { - type Output = OperatorResponsePayload; - type Error = Status; - - fn try_convert(self) -> Result { - match self { - Self::HandleVaultState(result) => result - .map_err(|err| { - warn!(?err, "vault state query failed"); - Status::internal("Failed to query vault state") - }) - .map(VaultState::convert), - Self::HandleHandshake(result) => result - .map_err(|err| { - warn!(?err, "handshake failed"); - Status::internal("Failed to start unseal flow") - }) - .map(vault_gate::HandshakeResponse::convert), - Self::HandleUnsealEncryptedKey(result) => { - let proto_result = match result { - Ok(()) => ProtoUnsealResult::Success, - Err(vault_gate::Error::InvalidKey) => ProtoUnsealResult::InvalidKey, - Err(err) => { - warn!(?err, "unseal failed"); - return Err(Status::internal("Failed to unseal vault")); - } - }; - Ok(wrap_unseal_response(UnsealResponsePayload::Result( - proto_result.into(), - ))) - } - Self::HandleBootstrapEncryptedKey(result) => { - let proto_result = match result { - Ok(()) => ProtoBootstrapResult::Success, - Err(vault_gate::Error::InvalidKey) => ProtoBootstrapResult::InvalidKey, - Err(vault_gate::Error::AlreadyBootstrapped) => { - ProtoBootstrapResult::AlreadyBootstrapped - } - Err(err) => { - warn!(?err, "bootstrap failed"); - return Err(Status::internal("Failed to bootstrap vault")); - } - }; - Ok(wrap_bootstrap_response(proto_result)) - } - } - } -} +use crate::{ + actors::vault::VaultState, + grpc::{Convert, TryConvert}, + peers::operator::vault_gate::{self as vault_gate}, +}; +use arbiter_proto::proto::{ + shared::VaultState as ProtoVaultState, + operator::{ + operator_response::Payload as OperatorResponsePayload, + vault::{ + self as proto_vault, + bootstrap::{self as proto_bootstrap, BootstrapResult as ProtoBootstrapResult}, + response::Payload as VaultResponsePayload, + unseal::{ + self as proto_unseal, UnsealResult as ProtoUnsealResult, + response::Payload as UnsealResponsePayload, + }, + }, + }, +}; + +use tonic::Status; +use tracing::warn; + +const fn wrap_vault_response(payload: VaultResponsePayload) -> OperatorResponsePayload { + OperatorResponsePayload::Vault(proto_vault::Response { + payload: Some(payload), + }) +} + +const fn wrap_unseal_response(payload: UnsealResponsePayload) -> OperatorResponsePayload { + wrap_vault_response(VaultResponsePayload::Unseal(proto_unseal::Response { + payload: Some(payload), + })) +} + +fn wrap_bootstrap_response(result: ProtoBootstrapResult) -> OperatorResponsePayload { + wrap_vault_response(VaultResponsePayload::Bootstrap(proto_bootstrap::Response { + result: result.into(), + })) +} + +impl Convert for VaultState { + type Output = OperatorResponsePayload; + + fn convert(self) -> OperatorResponsePayload { + let proto_state = match self { + Self::Unbootstrapped => ProtoVaultState::Unbootstrapped, + Self::Sealed => ProtoVaultState::Sealed, + Self::Unsealed => ProtoVaultState::Unsealed, + }; + wrap_vault_response(VaultResponsePayload::State(proto_state.into())) + } +} + +impl Convert for vault_gate::HandshakeResponse { + type Output = OperatorResponsePayload; + + fn convert(self) -> OperatorResponsePayload { + wrap_unseal_response(UnsealResponsePayload::Start( + proto_unseal::UnsealStartResponse { + server_pubkey: self.server_pubkey.as_bytes().to_vec(), + }, + )) + } +} + +impl TryConvert for vault_gate::Outbound { + type Output = OperatorResponsePayload; + type Error = Status; + + fn try_convert(self) -> Result { + match self { + Self::HandleVaultState(result) => result + .map_err(|err| { + warn!(?err, "vault state query failed"); + Status::internal("Failed to query vault state") + }) + .map(VaultState::convert), + Self::HandleHandshake(result) => result + .map_err(|err| { + warn!(?err, "handshake failed"); + Status::internal("Failed to start unseal flow") + }) + .map(vault_gate::HandshakeResponse::convert), + Self::HandleUnsealEncryptedKey(result) => { + let proto_result = match result { + Ok(()) => ProtoUnsealResult::Success, + Err(vault_gate::Error::InvalidKey) => ProtoUnsealResult::InvalidKey, + Err(err) => { + warn!(?err, "unseal failed"); + return Err(Status::internal("Failed to unseal vault")); + } + }; + Ok(wrap_unseal_response(UnsealResponsePayload::Result( + proto_result.into(), + ))) + } + Self::HandleBootstrapEncryptedKey(result) => { + let proto_result = match result { + Ok(()) => ProtoBootstrapResult::Success, + Err(vault_gate::Error::InvalidKey) => ProtoBootstrapResult::InvalidKey, + Err(vault_gate::Error::AlreadyBootstrapped) => { + ProtoBootstrapResult::AlreadyBootstrapped + } + Err(err) => { + warn!(?err, "bootstrap failed"); + return Err(Status::internal("Failed to bootstrap vault")); + } + }; + Ok(wrap_bootstrap_response(proto_result)) + } + } + } +} diff --git a/server/crates/arbiter-server/src/grpc/request_tracker.rs b/server/crates/arbiter-server/src/grpc/request_tracker.rs index 3b2edc3..b4ec65b 100644 --- a/server/crates/arbiter-server/src/grpc/request_tracker.rs +++ b/server/crates/arbiter-server/src/grpc/request_tracker.rs @@ -1,26 +1,26 @@ -use tonic::Status; - -#[derive(Default)] -pub(super) struct RequestTracker { - next_request_id: i32, -} - -impl RequestTracker { - pub(super) fn request(&mut self, id: i32) -> Result { - if id < self.next_request_id { - return Err(Status::invalid_argument("Duplicate request id")); - } - - self.next_request_id = id - .checked_add(1) - .ok_or_else(|| Status::invalid_argument("Invalid request id"))?; - - Ok(id) - } - - // This is used to set the response id for auth responses, which need to match the request id of the auth challenge request. - // -1 offset is needed because request() increments the next_request_id after returning the current request id. - pub(super) const fn current_request_id(&self) -> i32 { - self.next_request_id - 1 - } -} +use tonic::Status; + +#[derive(Default)] +pub(super) struct RequestTracker { + next_request_id: i32, +} + +impl RequestTracker { + pub(super) fn request(&mut self, id: i32) -> Result { + if id < self.next_request_id { + return Err(Status::invalid_argument("Duplicate request id")); + } + + self.next_request_id = id + .checked_add(1) + .ok_or_else(|| Status::invalid_argument("Invalid request id"))?; + + Ok(id) + } + + // This is used to set the response id for auth responses, which need to match the request id of the auth challenge request. + // -1 offset is needed because request() increments the next_request_id after returning the current request id. + pub(super) const fn current_request_id(&self) -> i32 { + self.next_request_id - 1 + } +} diff --git a/server/crates/arbiter-server/src/lib.rs b/server/crates/arbiter-server/src/lib.rs index 2336bd5..abc9fb2 100644 --- a/server/crates/arbiter-server/src/lib.rs +++ b/server/crates/arbiter-server/src/lib.rs @@ -1,20 +1,20 @@ -use crate::context::ServerContext; - -pub mod actors; -pub mod context; -pub mod crypto; -pub mod db; -pub mod evm; -pub mod grpc; -pub mod peers; -pub mod utils; - -pub struct Server { - context: ServerContext, -} - -impl Server { - pub const fn new(context: ServerContext) -> Self { - Self { context } - } -} +use crate::context::ServerContext; + +pub mod actors; +pub mod context; +pub mod crypto; +pub mod db; +pub mod evm; +pub mod grpc; +pub mod peers; +pub mod utils; + +pub struct Server { + context: ServerContext, +} + +impl Server { + pub const fn new(context: ServerContext) -> Self { + Self { context } + } +} diff --git a/server/crates/arbiter-server/src/main.rs b/server/crates/arbiter-server/src/main.rs index 0c2edde..4973dcb 100644 --- a/server/crates/arbiter-server/src/main.rs +++ b/server/crates/arbiter-server/src/main.rs @@ -1,57 +1,57 @@ -use arbiter_proto::{proto::arbiter_service_server::ArbiterServiceServer, url::ArbiterUrl}; -use arbiter_server::{Server, actors::bootstrap::GetToken, context::ServerContext, db}; - -use anyhow::anyhow; -use rustls::crypto::aws_lc_rs; -use std::net::SocketAddr; -use tonic::transport::{Identity, ServerTlsConfig}; -use tracing::info; - -const PORT: u16 = 50051; - -#[tokio::main] -#[mutants::skip] -async fn main() -> anyhow::Result<()> { - aws_lc_rs::default_provider().install_default().unwrap(); - - tracing_subscriber::fmt() - .with_env_filter( - tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")), - ) - .init(); - - info!("Starting arbiter server"); - - let db = db::create_pool(None).await?; - info!("Database ready"); - - let context = ServerContext::new(db).await?; - - let addr: SocketAddr = format!("127.0.0.1:{PORT}").parse().expect("valid address"); - info!(%addr, "Starting gRPC server"); - - let url = ArbiterUrl { - host: addr.ip().to_string(), - port: addr.port(), - ca_cert: context.tls.ca_cert().clone().into_owned(), - bootstrap_token: context.actors.bootstrapper.ask(GetToken).await.unwrap(), - }; - - info!(%url, "Server URL"); - - let tls = ServerTlsConfig::new().identity(Identity::from_pem( - context.tls.cert_pem(), - context.tls.key_pem(), - )); - - tonic::transport::Server::builder() - .tls_config(tls) - .map_err(|err| anyhow!("Failed to setup TLS: {err}"))? - .add_service(ArbiterServiceServer::new(Server::new(context))) - .serve(addr) - .await - .map_err(|e| anyhow!("gRPC server error: {e}"))?; - - unreachable!("gRPC server should run indefinitely"); -} +use arbiter_proto::{proto::arbiter_service_server::ArbiterServiceServer, url::ArbiterUrl}; +use arbiter_server::{Server, actors::bootstrap::GetToken, context::ServerContext, db}; + +use anyhow::anyhow; +use rustls::crypto::aws_lc_rs; +use std::net::SocketAddr; +use tonic::transport::{Identity, ServerTlsConfig}; +use tracing::info; + +const PORT: u16 = 50051; + +#[tokio::main] +#[mutants::skip] +async fn main() -> anyhow::Result<()> { + aws_lc_rs::default_provider().install_default().unwrap(); + + tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")), + ) + .init(); + + info!("Starting arbiter server"); + + let db = db::create_pool(None).await?; + info!("Database ready"); + + let context = ServerContext::new(db).await?; + + let addr: SocketAddr = format!("127.0.0.1:{PORT}").parse().expect("valid address"); + info!(%addr, "Starting gRPC server"); + + let url = ArbiterUrl { + host: addr.ip().to_string(), + port: addr.port(), + ca_cert: context.tls.ca_cert().clone().into_owned(), + bootstrap_token: context.actors.bootstrapper.ask(GetToken).await.unwrap(), + }; + + info!(%url, "Server URL"); + + let tls = ServerTlsConfig::new().identity(Identity::from_pem( + context.tls.cert_pem(), + context.tls.key_pem(), + )); + + tonic::transport::Server::builder() + .tls_config(tls) + .map_err(|err| anyhow!("Failed to setup TLS: {err}"))? + .add_service(ArbiterServiceServer::new(Server::new(context))) + .serve(addr) + .await + .map_err(|e| anyhow!("gRPC server error: {e}"))?; + + unreachable!("gRPC server should run indefinitely"); +} diff --git a/server/crates/arbiter-server/src/peers/client/auth.rs b/server/crates/arbiter-server/src/peers/client/auth.rs index f488161..a65a344 100644 --- a/server/crates/arbiter-server/src/peers/client/auth.rs +++ b/server/crates/arbiter-server/src/peers/client/auth.rs @@ -1,354 +1,354 @@ -use super::{ClientConnection, ClientCredentials, ClientProfile}; -use crate::{ - actors::{ - GlobalActors, - flow_coordinator::{self, RequestClientApproval}, - vault::Vault, - }, - crypto::integrity::{self, AttestationStatus}, - db::{ - self, - models::{ProgramClientMetadata, SqliteTimestamp}, - schema::program_client, - }, -}; -use arbiter_crypto::authn::{self, AuthChallenge, CLIENT_CONTEXT}; -use arbiter_proto::{ - ClientMetadata, - transport::{Bi, expect_message}, -}; - -use chrono::Utc; -use diesel::{ - ExpressionMethods as _, OptionalExtension as _, QueryDsl as _, SelectableHelper as _, - dsl::insert_into, update, -}; -use diesel_async::RunQueryDsl as _; -use kameo::{actor::ActorRef, error::SendError}; -use tracing::error; - -#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] -pub enum Error { - #[error("Database pool unavailable")] - DatabasePoolUnavailable, - #[error("Database operation failed")] - DatabaseOperationFailed, - #[error("Integrity check failed")] - IntegrityCheckFailed, - #[error("Invalid challenge solution")] - InvalidChallengeSolution, - #[error("Client approval request failed")] - ApproveError(#[from] ApproveError), - #[error("Transport error")] - Transport, -} - -impl From for Error { - fn from(e: diesel::result::Error) -> Self { - error!(?e, "Database error"); - Self::DatabaseOperationFailed - } -} - -#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] -pub enum ApproveError { - #[error("Internal error")] - Internal, - #[error("Client connection denied by operators")] - Denied, - #[error("Upstream error: {0}")] - Upstream(flow_coordinator::ApprovalError), -} - -#[derive(Debug, Clone)] -pub enum Inbound { - AuthChallengeRequest { - pubkey: authn::PublicKey, - metadata: ClientMetadata, - }, - AuthChallengeSolution { - signature: authn::Signature, - }, -} - -#[derive(Debug, Clone)] -pub enum Outbound { - AuthChallenge { challenge: AuthChallenge }, - AuthSuccess, -} - -async fn get_client_id( - db: &db::DatabasePool, - pubkey: &authn::PublicKey, -) -> Result, Error> { - let pubkey_bytes = pubkey.to_bytes(); - let mut conn = db.get().await.map_err(|e| { - error!(error = ?e, "Database pool error"); - Error::DatabasePoolUnavailable - })?; - program_client::table - .filter(program_client::public_key.eq(&pubkey_bytes)) - .select(program_client::id) - .first::(&mut conn) - .await - .optional() - .map_err(|e| { - error!(error = ?e, "Database error"); - Error::DatabaseOperationFailed - }) -} - -async fn verify_integrity( - db: &db::DatabasePool, - vault: &ActorRef, - pubkey: &authn::PublicKey, -) -> Result<(), Error> { - let mut db_conn = db.get().await.map_err(|e| { - error!(error = ?e, "Database pool error"); - Error::DatabasePoolUnavailable - })?; - - let id = get_client_id(db, pubkey).await?.ok_or_else(|| { - error!("Client not found during integrity verification"); - Error::DatabaseOperationFailed - })?; - - let attestation = integrity::verify_entity( - &mut db_conn, - vault, - &ClientCredentials { - pubkey: pubkey.clone(), - }, - id, - ) - .await - .map_err(|e| { - error!(?e, "Integrity verification failed"); - Error::IntegrityCheckFailed - })?; - - if attestation != AttestationStatus::Attested { - error!("Integrity attestation unavailable for client {id}"); - return Err(Error::IntegrityCheckFailed); - } - - Ok(()) -} - -async fn approve_new_client(actors: &GlobalActors, profile: ClientProfile) -> Result<(), Error> { - let result = actors - .flow_coordinator - .ask(RequestClientApproval { client: profile }) - .await; - - match result { - Ok(true) => Ok(()), - Ok(false) => Err(Error::ApproveError(ApproveError::Denied)), - Err(SendError::HandlerError(e)) => { - error!(error = ?e, "Approval upstream error"); - Err(Error::ApproveError(ApproveError::Upstream(e))) - } - Err(e) => { - error!(error = ?e, "Approval request to flow coordinator failed"); - Err(Error::ApproveError(ApproveError::Internal)) - } - } -} - -async fn insert_client( - db: &db::DatabasePool, - vault: &ActorRef, - pubkey: &authn::PublicKey, - metadata: &ClientMetadata, -) -> Result { - use crate::db::schema::client_metadata; - - let pubkey = pubkey.clone(); - let metadata = metadata.clone(); - - let mut conn = db.get().await.map_err(|e| { - error!(error = ?e, "Database pool error"); - Error::DatabasePoolUnavailable - })?; - - conn.exclusive_transaction(async |conn| { - let metadata_id = insert_into(client_metadata::table) - .values(( - client_metadata::name.eq(&metadata.name), - client_metadata::description.eq(&metadata.description), - client_metadata::version.eq(&metadata.version), - )) - .returning(client_metadata::id) - .get_result::(&mut *conn) - .await?; - - let client_id = insert_into(program_client::table) - .values(( - program_client::public_key.eq(pubkey.to_bytes()), - program_client::metadata_id.eq(metadata_id), - )) - .on_conflict_do_nothing() - .returning(program_client::id) - .get_result::(&mut *conn) - .await?; - - integrity::sign_entity( - &mut *conn, - vault, - &ClientCredentials { - pubkey: pubkey.clone(), - }, - client_id, - ) - .await - .map_err(|e| { - error!(error = ?e, "Failed to sign integrity tag for new client key"); - Error::DatabaseOperationFailed - })?; - - Ok(client_id) - }) - .await -} - -async fn sync_client_metadata( - db: &db::DatabasePool, - client_id: i32, - metadata: &ClientMetadata, -) -> Result<(), Error> { - use crate::db::schema::{client_metadata, client_metadata_history}; - - let now = SqliteTimestamp(Utc::now()); - - let mut conn = db.get().await.map_err(|e| { - error!(error = ?e, "Database pool error"); - Error::DatabasePoolUnavailable - })?; - - conn.exclusive_transaction(async |conn| { - let (current_metadata_id, current): (i32, ProgramClientMetadata) = program_client::table - .find(client_id) - .inner_join(client_metadata::table) - .select(( - program_client::metadata_id, - ProgramClientMetadata::as_select(), - )) - .first(&mut *conn) - .await?; - - let unchanged = current.name == metadata.name - && current.description == metadata.description - && current.version == metadata.version; - if unchanged { - return Ok(()); - } - - insert_into(client_metadata_history::table) - .values(( - client_metadata_history::metadata_id.eq(current_metadata_id), - client_metadata_history::client_id.eq(client_id), - )) - .execute(&mut *conn) - .await?; - - let metadata_id = insert_into(client_metadata::table) - .values(( - client_metadata::name.eq(&metadata.name), - client_metadata::description.eq(&metadata.description), - client_metadata::version.eq(&metadata.version), - )) - .returning(client_metadata::id) - .get_result::(&mut *conn) - .await?; - - update(program_client::table.find(client_id)) - .set(( - program_client::metadata_id.eq(metadata_id), - program_client::updated_at.eq(now), - )) - .execute(&mut *conn) - .await?; - - Ok::<(), diesel::result::Error>(()) - }) - .await - .map_err(|e| { - error!(error = ?e, "Database error"); - Error::DatabaseOperationFailed - }) -} - -async fn challenge_client( - transport: &mut T, - pubkey: authn::PublicKey, - challenge: AuthChallenge, -) -> Result<(), Error> -where - T: Bi> + ?Sized, -{ - transport - .send(Ok(Outbound::AuthChallenge { - challenge: challenge.clone(), - })) - .await - .map_err(|e| { - error!(error = ?e, "Failed to send auth challenge"); - Error::Transport - })?; - - let signature = expect_message(transport, |req: Inbound| match req { - Inbound::AuthChallengeSolution { signature } => Some(signature), - Inbound::AuthChallengeRequest { .. } => None, - }) - .await - .map_err(|e| { - error!(error = ?e, "Failed to receive challenge solution"); - Error::Transport - })?; - - if !pubkey.verify(&challenge, CLIENT_CONTEXT, &signature) { - error!("Challenge solution verification failed"); - return Err(Error::InvalidChallengeSolution); - } - - Ok(()) -} - -pub async fn authenticate(props: &mut ClientConnection, transport: &mut T) -> Result -where - T: Bi> + Send + ?Sized, -{ - let Some(Inbound::AuthChallengeRequest { pubkey, metadata }) = transport.recv().await else { - return Err(Error::Transport); - }; - - let client_id = if let Some(id) = get_client_id(&props.db, &pubkey).await? { - verify_integrity(&props.db, &props.actors.vault, &pubkey).await?; - id - } else { - approve_new_client( - &props.actors, - ClientProfile { - pubkey: pubkey.clone(), - metadata: metadata.clone(), - }, - ) - .await?; - insert_client(&props.db, &props.actors.vault, &pubkey, &metadata).await? - }; - - sync_client_metadata(&props.db, client_id, &metadata).await?; - - let challenge = AuthChallenge::generate(&mut rand::rng()); - challenge_client(transport, pubkey, challenge).await?; - - transport - .send(Ok(Outbound::AuthSuccess)) - .await - .map_err(|e| { - error!(error = ?e, "Failed to send auth success"); - Error::Transport - })?; - - Ok(client_id) -} +use super::{ClientConnection, ClientCredentials, ClientProfile}; +use crate::{ + actors::{ + GlobalActors, + flow_coordinator::{self, RequestClientApproval}, + vault::Vault, + }, + crypto::integrity::{self, AttestationStatus}, + db::{ + self, + models::{ProgramClientMetadata, SqliteTimestamp}, + schema::program_client, + }, +}; +use arbiter_crypto::authn::{self, AuthChallenge, CLIENT_CONTEXT}; +use arbiter_proto::{ + ClientMetadata, + transport::{Bi, expect_message}, +}; + +use chrono::Utc; +use diesel::{ + ExpressionMethods as _, OptionalExtension as _, QueryDsl as _, SelectableHelper as _, + dsl::insert_into, update, +}; +use diesel_async::RunQueryDsl as _; +use kameo::{actor::ActorRef, error::SendError}; +use tracing::error; + +#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] +pub enum Error { + #[error("Database pool unavailable")] + DatabasePoolUnavailable, + #[error("Database operation failed")] + DatabaseOperationFailed, + #[error("Integrity check failed")] + IntegrityCheckFailed, + #[error("Invalid challenge solution")] + InvalidChallengeSolution, + #[error("Client approval request failed")] + ApproveError(#[from] ApproveError), + #[error("Transport error")] + Transport, +} + +impl From for Error { + fn from(e: diesel::result::Error) -> Self { + error!(?e, "Database error"); + Self::DatabaseOperationFailed + } +} + +#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] +pub enum ApproveError { + #[error("Internal error")] + Internal, + #[error("Client connection denied by operators")] + Denied, + #[error("Upstream error: {0}")] + Upstream(flow_coordinator::ApprovalError), +} + +#[derive(Debug, Clone)] +pub enum Inbound { + AuthChallengeRequest { + pubkey: authn::PublicKey, + metadata: ClientMetadata, + }, + AuthChallengeSolution { + signature: authn::Signature, + }, +} + +#[derive(Debug, Clone)] +pub enum Outbound { + AuthChallenge { challenge: AuthChallenge }, + AuthSuccess, +} + +async fn get_client_id( + db: &db::DatabasePool, + pubkey: &authn::PublicKey, +) -> Result, Error> { + let pubkey_bytes = pubkey.to_bytes(); + let mut conn = db.get().await.map_err(|e| { + error!(error = ?e, "Database pool error"); + Error::DatabasePoolUnavailable + })?; + program_client::table + .filter(program_client::public_key.eq(&pubkey_bytes)) + .select(program_client::id) + .first::(&mut conn) + .await + .optional() + .map_err(|e| { + error!(error = ?e, "Database error"); + Error::DatabaseOperationFailed + }) +} + +async fn verify_integrity( + db: &db::DatabasePool, + vault: &ActorRef, + pubkey: &authn::PublicKey, +) -> Result<(), Error> { + let mut db_conn = db.get().await.map_err(|e| { + error!(error = ?e, "Database pool error"); + Error::DatabasePoolUnavailable + })?; + + let id = get_client_id(db, pubkey).await?.ok_or_else(|| { + error!("Client not found during integrity verification"); + Error::DatabaseOperationFailed + })?; + + let attestation = integrity::verify_entity( + &mut db_conn, + vault, + &ClientCredentials { + pubkey: pubkey.clone(), + }, + id, + ) + .await + .map_err(|e| { + error!(?e, "Integrity verification failed"); + Error::IntegrityCheckFailed + })?; + + if attestation != AttestationStatus::Attested { + error!("Integrity attestation unavailable for client {id}"); + return Err(Error::IntegrityCheckFailed); + } + + Ok(()) +} + +async fn approve_new_client(actors: &GlobalActors, profile: ClientProfile) -> Result<(), Error> { + let result = actors + .flow_coordinator + .ask(RequestClientApproval { client: profile }) + .await; + + match result { + Ok(true) => Ok(()), + Ok(false) => Err(Error::ApproveError(ApproveError::Denied)), + Err(SendError::HandlerError(e)) => { + error!(error = ?e, "Approval upstream error"); + Err(Error::ApproveError(ApproveError::Upstream(e))) + } + Err(e) => { + error!(error = ?e, "Approval request to flow coordinator failed"); + Err(Error::ApproveError(ApproveError::Internal)) + } + } +} + +async fn insert_client( + db: &db::DatabasePool, + vault: &ActorRef, + pubkey: &authn::PublicKey, + metadata: &ClientMetadata, +) -> Result { + use crate::db::schema::client_metadata; + + let pubkey = pubkey.clone(); + let metadata = metadata.clone(); + + let mut conn = db.get().await.map_err(|e| { + error!(error = ?e, "Database pool error"); + Error::DatabasePoolUnavailable + })?; + + conn.exclusive_transaction(async |conn| { + let metadata_id = insert_into(client_metadata::table) + .values(( + client_metadata::name.eq(&metadata.name), + client_metadata::description.eq(&metadata.description), + client_metadata::version.eq(&metadata.version), + )) + .returning(client_metadata::id) + .get_result::(&mut *conn) + .await?; + + let client_id = insert_into(program_client::table) + .values(( + program_client::public_key.eq(pubkey.to_bytes()), + program_client::metadata_id.eq(metadata_id), + )) + .on_conflict_do_nothing() + .returning(program_client::id) + .get_result::(&mut *conn) + .await?; + + integrity::sign_entity( + &mut *conn, + vault, + &ClientCredentials { + pubkey: pubkey.clone(), + }, + client_id, + ) + .await + .map_err(|e| { + error!(error = ?e, "Failed to sign integrity tag for new client key"); + Error::DatabaseOperationFailed + })?; + + Ok(client_id) + }) + .await +} + +async fn sync_client_metadata( + db: &db::DatabasePool, + client_id: i32, + metadata: &ClientMetadata, +) -> Result<(), Error> { + use crate::db::schema::{client_metadata, client_metadata_history}; + + let now = SqliteTimestamp(Utc::now()); + + let mut conn = db.get().await.map_err(|e| { + error!(error = ?e, "Database pool error"); + Error::DatabasePoolUnavailable + })?; + + conn.exclusive_transaction(async |conn| { + let (current_metadata_id, current): (i32, ProgramClientMetadata) = program_client::table + .find(client_id) + .inner_join(client_metadata::table) + .select(( + program_client::metadata_id, + ProgramClientMetadata::as_select(), + )) + .first(&mut *conn) + .await?; + + let unchanged = current.name == metadata.name + && current.description == metadata.description + && current.version == metadata.version; + if unchanged { + return Ok(()); + } + + insert_into(client_metadata_history::table) + .values(( + client_metadata_history::metadata_id.eq(current_metadata_id), + client_metadata_history::client_id.eq(client_id), + )) + .execute(&mut *conn) + .await?; + + let metadata_id = insert_into(client_metadata::table) + .values(( + client_metadata::name.eq(&metadata.name), + client_metadata::description.eq(&metadata.description), + client_metadata::version.eq(&metadata.version), + )) + .returning(client_metadata::id) + .get_result::(&mut *conn) + .await?; + + update(program_client::table.find(client_id)) + .set(( + program_client::metadata_id.eq(metadata_id), + program_client::updated_at.eq(now), + )) + .execute(&mut *conn) + .await?; + + Ok::<(), diesel::result::Error>(()) + }) + .await + .map_err(|e| { + error!(error = ?e, "Database error"); + Error::DatabaseOperationFailed + }) +} + +async fn challenge_client( + transport: &mut T, + pubkey: authn::PublicKey, + challenge: AuthChallenge, +) -> Result<(), Error> +where + T: Bi> + ?Sized, +{ + transport + .send(Ok(Outbound::AuthChallenge { + challenge: challenge.clone(), + })) + .await + .map_err(|e| { + error!(error = ?e, "Failed to send auth challenge"); + Error::Transport + })?; + + let signature = expect_message(transport, |req: Inbound| match req { + Inbound::AuthChallengeSolution { signature } => Some(signature), + Inbound::AuthChallengeRequest { .. } => None, + }) + .await + .map_err(|e| { + error!(error = ?e, "Failed to receive challenge solution"); + Error::Transport + })?; + + if !pubkey.verify(&challenge, CLIENT_CONTEXT, &signature) { + error!("Challenge solution verification failed"); + return Err(Error::InvalidChallengeSolution); + } + + Ok(()) +} + +pub async fn authenticate(props: &mut ClientConnection, transport: &mut T) -> Result +where + T: Bi> + Send + ?Sized, +{ + let Some(Inbound::AuthChallengeRequest { pubkey, metadata }) = transport.recv().await else { + return Err(Error::Transport); + }; + + let client_id = if let Some(id) = get_client_id(&props.db, &pubkey).await? { + verify_integrity(&props.db, &props.actors.vault, &pubkey).await?; + id + } else { + approve_new_client( + &props.actors, + ClientProfile { + pubkey: pubkey.clone(), + metadata: metadata.clone(), + }, + ) + .await?; + insert_client(&props.db, &props.actors.vault, &pubkey, &metadata).await? + }; + + sync_client_metadata(&props.db, client_id, &metadata).await?; + + let challenge = AuthChallenge::generate(&mut rand::rng()); + challenge_client(transport, pubkey, challenge).await?; + + transport + .send(Ok(Outbound::AuthSuccess)) + .await + .map_err(|e| { + error!(error = ?e, "Failed to send auth success"); + Error::Transport + })?; + + Ok(client_id) +} diff --git a/server/crates/arbiter-server/src/peers/client/mod.rs b/server/crates/arbiter-server/src/peers/client/mod.rs index f142bb8..27f76e9 100644 --- a/server/crates/arbiter-server/src/peers/client/mod.rs +++ b/server/crates/arbiter-server/src/peers/client/mod.rs @@ -1,56 +1,56 @@ -use crate::{ - actors::GlobalActors, crypto::integrity::Integrable, db, peers::client::session::ClientSession, -}; -use arbiter_crypto::authn; -use arbiter_macros::Hashable; -use arbiter_proto::{ClientMetadata, transport::Bi}; - -use kameo::actor::Spawn; -use tracing::{error, info}; - -#[derive(Debug, Clone)] -pub struct ClientProfile { - pub pubkey: authn::PublicKey, - pub metadata: ClientMetadata, -} - -#[derive(Hashable)] -pub struct ClientCredentials { - pub pubkey: authn::PublicKey, -} - -impl Integrable for ClientCredentials { - const KIND: &'static str = "client_credentials"; -} - -pub struct ClientConnection { - pub(crate) db: db::DatabasePool, - pub(crate) actors: GlobalActors, -} - -impl ClientConnection { - pub const fn new(db: db::DatabasePool, actors: GlobalActors) -> Self { - Self { db, actors } - } -} - -pub mod auth; -pub mod session; - -pub async fn connect_client(mut props: ClientConnection, transport: &mut T) -where - T: Bi> + Send + ?Sized, -{ - let fut = auth::authenticate(&mut props, transport); - println!("authenticate future size: {}", size_of_val(&fut)); - match fut.await { - Ok(client_id) => { - ClientSession::spawn(ClientSession::new(props, client_id)); - info!("Client authenticated, session started"); - } - Err(err) => { - let _ = transport.send(Err(err.clone())).await; - error!(?err, "Authentication failed, closing connection"); - } - } -} +use crate::{ + actors::GlobalActors, crypto::integrity::Integrable, db, peers::client::session::ClientSession, +}; +use arbiter_crypto::authn; +use arbiter_macros::Hashable; +use arbiter_proto::{ClientMetadata, transport::Bi}; + +use kameo::actor::Spawn; +use tracing::{error, info}; + +#[derive(Debug, Clone)] +pub struct ClientProfile { + pub pubkey: authn::PublicKey, + pub metadata: ClientMetadata, +} + +#[derive(Hashable)] +pub struct ClientCredentials { + pub pubkey: authn::PublicKey, +} + +impl Integrable for ClientCredentials { + const KIND: &'static str = "client_credentials"; +} + +pub struct ClientConnection { + pub(crate) db: db::DatabasePool, + pub(crate) actors: GlobalActors, +} + +impl ClientConnection { + pub const fn new(db: db::DatabasePool, actors: GlobalActors) -> Self { + Self { db, actors } + } +} + +pub mod auth; +pub mod session; + +pub async fn connect_client(mut props: ClientConnection, transport: &mut T) +where + T: Bi> + Send + ?Sized, +{ + let fut = auth::authenticate(&mut props, transport); + println!("authenticate future size: {}", size_of_val(&fut)); + match fut.await { + Ok(client_id) => { + ClientSession::spawn(ClientSession::new(props, client_id)); + info!("Client authenticated, session started"); + } + Err(err) => { + let _ = transport.send(Err(err.clone())).await; + error!(?err, "Authentication failed, closing connection"); + } + } +} diff --git a/server/crates/arbiter-server/src/peers/client/session.rs b/server/crates/arbiter-server/src/peers/client/session.rs index 23ebf3c..da48610 100644 --- a/server/crates/arbiter-server/src/peers/client/session.rs +++ b/server/crates/arbiter-server/src/peers/client/session.rs @@ -1,118 +1,118 @@ -use super::ClientConnection; -use crate::{ - actors::{ - GlobalActors, - evm::{ClientSignTransaction, SignTransactionError}, - flow_coordinator::RegisterClient, - vault::VaultState, - }, - db, - evm::VetError, -}; - -use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature}; -use kameo::{Actor, messages}; -use tracing::error; - -pub struct ClientSession { - props: ClientConnection, - client_id: i32, -} - -impl ClientSession { - pub(crate) const fn new(props: ClientConnection, client_id: i32) -> Self { - Self { props, client_id } - } -} - -#[messages] -impl ClientSession { - #[message] - pub(crate) async fn handle_query_vault_state(&mut self) -> Result { - use crate::actors::vault::GetState; - - let vault_state = match self.props.actors.vault.ask(GetState {}).await { - Ok(state) => state, - Err(err) => { - error!(?err, actor = "client", "vault.query.failed"); - return Err(Error::Internal); - } - }; - - Ok(vault_state) - } - - #[message] - pub(crate) async fn handle_sign_transaction( - &mut self, - wallet_address: Address, - transaction: TxEip1559, - ) -> Result { - match self - .props - .actors - .evm - .ask(ClientSignTransaction { - client_id: self.client_id, - wallet_address, - transaction, - }) - .await - { - Ok(signature) => Ok(signature), - Err(kameo::error::SendError::HandlerError(SignTransactionError::Vet(vet_error))) => { - Err(SignTransactionRpcError::Vet(vet_error)) - } - Err(err) => { - error!(?err, "Failed to sign EVM transaction in client session"); - Err(SignTransactionRpcError::Internal) - } - } - } -} - -impl Actor for ClientSession { - type Args = Self; - - type Error = Error; - - async fn on_start( - args: Self::Args, - this: kameo::prelude::ActorRef, - ) -> Result { - args.props - .actors - .flow_coordinator - .ask(RegisterClient { actor: this }) - .await - .map_err(|_| Error::ConnectionRegistrationFailed)?; - Ok(args) - } -} - -impl ClientSession { - pub const fn new_test(db: db::DatabasePool, actors: GlobalActors) -> Self { - let props = ClientConnection::new(db, actors); - Self { - props, - client_id: 0, - } - } -} - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Connection registration failed")] - ConnectionRegistrationFailed, - #[error("Internal error")] - Internal, -} - -#[derive(Debug, thiserror::Error)] -pub enum SignTransactionRpcError { - #[error("Policy evaluation failed")] - Vet(#[from] VetError), - - #[error("Internal error")] - Internal, -} +use super::ClientConnection; +use crate::{ + actors::{ + GlobalActors, + evm::{ClientSignTransaction, SignTransactionError}, + flow_coordinator::RegisterClient, + vault::VaultState, + }, + db, + evm::VetError, +}; + +use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature}; +use kameo::{Actor, messages}; +use tracing::error; + +pub struct ClientSession { + props: ClientConnection, + client_id: i32, +} + +impl ClientSession { + pub(crate) const fn new(props: ClientConnection, client_id: i32) -> Self { + Self { props, client_id } + } +} + +#[messages] +impl ClientSession { + #[message] + pub(crate) async fn handle_query_vault_state(&mut self) -> Result { + use crate::actors::vault::GetState; + + let vault_state = match self.props.actors.vault.ask(GetState {}).await { + Ok(state) => state, + Err(err) => { + error!(?err, actor = "client", "vault.query.failed"); + return Err(Error::Internal); + } + }; + + Ok(vault_state) + } + + #[message] + pub(crate) async fn handle_sign_transaction( + &mut self, + wallet_address: Address, + transaction: TxEip1559, + ) -> Result { + match self + .props + .actors + .evm + .ask(ClientSignTransaction { + client_id: self.client_id, + wallet_address, + transaction, + }) + .await + { + Ok(signature) => Ok(signature), + Err(kameo::error::SendError::HandlerError(SignTransactionError::Vet(vet_error))) => { + Err(SignTransactionRpcError::Vet(vet_error)) + } + Err(err) => { + error!(?err, "Failed to sign EVM transaction in client session"); + Err(SignTransactionRpcError::Internal) + } + } + } +} + +impl Actor for ClientSession { + type Args = Self; + + type Error = Error; + + async fn on_start( + args: Self::Args, + this: kameo::prelude::ActorRef, + ) -> Result { + args.props + .actors + .flow_coordinator + .ask(RegisterClient { actor: this }) + .await + .map_err(|_| Error::ConnectionRegistrationFailed)?; + Ok(args) + } +} + +impl ClientSession { + pub const fn new_test(db: db::DatabasePool, actors: GlobalActors) -> Self { + let props = ClientConnection::new(db, actors); + Self { + props, + client_id: 0, + } + } +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Connection registration failed")] + ConnectionRegistrationFailed, + #[error("Internal error")] + Internal, +} + +#[derive(Debug, thiserror::Error)] +pub enum SignTransactionRpcError { + #[error("Policy evaluation failed")] + Vet(#[from] VetError), + + #[error("Internal error")] + Internal, +} diff --git a/server/crates/arbiter-server/src/peers/mod.rs b/server/crates/arbiter-server/src/peers/mod.rs index 70091d0..ca6f186 100644 --- a/server/crates/arbiter-server/src/peers/mod.rs +++ b/server/crates/arbiter-server/src/peers/mod.rs @@ -1,2 +1,2 @@ -pub mod client; -pub mod operator; +pub mod client; +pub mod operator; diff --git a/server/crates/arbiter-server/src/peers/operator/auth/mod.rs b/server/crates/arbiter-server/src/peers/operator/auth/mod.rs index 8bea8a0..53e4c7c 100644 --- a/server/crates/arbiter-server/src/peers/operator/auth/mod.rs +++ b/server/crates/arbiter-server/src/peers/operator/auth/mod.rs @@ -1,107 +1,107 @@ -use super::{Credentials, OperatorConnection}; -use arbiter_crypto::authn::{self, AuthChallenge}; -use arbiter_proto::transport::Bi; - -use state::{ - AuthContext, AuthError, AuthEvents, AuthStateMachine, AuthStates, ChallengeRequest, - ChallengeSolution, -}; -use tracing::error; - -mod state; - -#[derive(Debug, Clone)] -pub enum Inbound { - AuthChallengeRequest { - pubkey: authn::PublicKey, - bootstrap_token: Option, - }, - AuthChallengeSolution { - signature: Vec, - }, -} - -#[derive(Debug)] -pub enum Error { - UnregisteredPublicKey, - InvalidChallengeSolution, - InvalidBootstrapToken, - Internal { details: String }, - Transport, -} - -impl Error { - fn internal(details: impl Into) -> Self { - Self::Internal { - details: details.into(), - } - } -} - -impl From for Error { - fn from(e: diesel::result::Error) -> Self { - error!(?e, "Database error"); - Self::internal("Database error") - } -} - -#[derive(Debug, Clone)] -pub enum Outbound { - AuthChallenge { challenge: AuthChallenge }, - AuthSuccess, -} - -fn parse_auth_event(payload: Inbound) -> AuthEvents { - match payload { - Inbound::AuthChallengeRequest { - pubkey, - bootstrap_token, - } => AuthEvents::AuthRequest(ChallengeRequest { - pubkey, - bootstrap_token, - }), - Inbound::AuthChallengeSolution { signature } => { - AuthEvents::ReceivedSolution(ChallengeSolution { - solution: signature, - }) - } - } -} - -pub async fn authenticate( - props: &mut OperatorConnection, - transport: &mut T, -) -> Result -where - T: Bi> + Send + ?Sized, -{ - let mut state = AuthStateMachine::new(AuthContext::new(props, transport)); - - loop { - let Some(payload) = state.context_mut().transport.recv().await else { - return Err(Error::Transport); - }; - - match state.process_event(parse_auth_event(payload)).await { - Ok(AuthStates::AuthOk(result)) => return Ok(result.clone()), - Err(AuthError::ActionFailed(err)) => { - error!(?err, "State machine action failed"); - return Err(err); - } - Err(AuthError::GuardFailed(err)) => { - error!(?err, "State machine guard failed"); - return Err(err); - } - Err(AuthError::InvalidEvent) => { - error!("Invalid event for current state"); - return Err(Error::InvalidChallengeSolution); - } - Err(AuthError::TransitionsFailed) => { - error!("Invalid state transition"); - return Err(Error::InvalidChallengeSolution); - } - - _ => (), - } - } -} +use super::{Credentials, OperatorConnection}; +use arbiter_crypto::authn::{self, AuthChallenge}; +use arbiter_proto::transport::Bi; + +use state::{ + AuthContext, AuthError, AuthEvents, AuthStateMachine, AuthStates, ChallengeRequest, + ChallengeSolution, +}; +use tracing::error; + +mod state; + +#[derive(Debug, Clone)] +pub enum Inbound { + AuthChallengeRequest { + pubkey: authn::PublicKey, + bootstrap_token: Option, + }, + AuthChallengeSolution { + signature: Vec, + }, +} + +#[derive(Debug)] +pub enum Error { + UnregisteredPublicKey, + InvalidChallengeSolution, + InvalidBootstrapToken, + Internal { details: String }, + Transport, +} + +impl Error { + fn internal(details: impl Into) -> Self { + Self::Internal { + details: details.into(), + } + } +} + +impl From for Error { + fn from(e: diesel::result::Error) -> Self { + error!(?e, "Database error"); + Self::internal("Database error") + } +} + +#[derive(Debug, Clone)] +pub enum Outbound { + AuthChallenge { challenge: AuthChallenge }, + AuthSuccess, +} + +fn parse_auth_event(payload: Inbound) -> AuthEvents { + match payload { + Inbound::AuthChallengeRequest { + pubkey, + bootstrap_token, + } => AuthEvents::AuthRequest(ChallengeRequest { + pubkey, + bootstrap_token, + }), + Inbound::AuthChallengeSolution { signature } => { + AuthEvents::ReceivedSolution(ChallengeSolution { + solution: signature, + }) + } + } +} + +pub async fn authenticate( + props: &mut OperatorConnection, + transport: &mut T, +) -> Result +where + T: Bi> + Send + ?Sized, +{ + let mut state = AuthStateMachine::new(AuthContext::new(props, transport)); + + loop { + let Some(payload) = state.context_mut().transport.recv().await else { + return Err(Error::Transport); + }; + + match state.process_event(parse_auth_event(payload)).await { + Ok(AuthStates::AuthOk(result)) => return Ok(result.clone()), + Err(AuthError::ActionFailed(err)) => { + error!(?err, "State machine action failed"); + return Err(err); + } + Err(AuthError::GuardFailed(err)) => { + error!(?err, "State machine guard failed"); + return Err(err); + } + Err(AuthError::InvalidEvent) => { + error!("Invalid event for current state"); + return Err(Error::InvalidChallengeSolution); + } + Err(AuthError::TransitionsFailed) => { + error!("Invalid state transition"); + return Err(Error::InvalidChallengeSolution); + } + + _ => (), + } + } +} diff --git a/server/crates/arbiter-server/src/peers/operator/auth/state.rs b/server/crates/arbiter-server/src/peers/operator/auth/state.rs index 38f1ecd..e7f5393 100644 --- a/server/crates/arbiter-server/src/peers/operator/auth/state.rs +++ b/server/crates/arbiter-server/src/peers/operator/auth/state.rs @@ -1,196 +1,196 @@ -use super::{ - super::{Credentials, OperatorConnection}, - Error, -}; -use crate::{ - actors::bootstrap::ConsumeToken, - db::{DatabasePool, schema::operator_client}, - peers::operator::auth::Outbound, -}; -use arbiter_crypto::authn::{self, AuthChallenge, OPERATOR_CONTEXT}; -use arbiter_proto::transport::Bi; - -use diesel::{ExpressionMethods as _, OptionalExtension as _, QueryDsl}; -use diesel_async::RunQueryDsl; -use tracing::error; - -pub(super) struct ChallengeRequest { - pub(super) pubkey: authn::PublicKey, - pub(super) bootstrap_token: Option, -} - -pub struct ChallengeContext { - pub(super) challenge: AuthChallenge, - pub(super) pubkey: authn::PublicKey, - pub(super) bootstrap_token: Option, -} - -pub(super) struct ChallengeSolution { - pub(super) solution: Vec, -} - -smlang::statemachine!( - name: Auth, - custom_error: true, - transitions: { - *Init + AuthRequest(ChallengeRequest) / async prepare_challenge = SentChallenge(ChallengeContext), - SentChallenge(ChallengeContext) + ReceivedSolution(ChallengeSolution) / async verify_solution = AuthOk(Credentials), - } -); - -async fn get_client_id(db: &DatabasePool, pubkey: &authn::PublicKey) -> Result, Error> { - let mut conn = db.get().await.map_err(|e| { - error!(error = ?e, "Database pool error"); - Error::internal("Database unavailable") - })?; - - operator_client::table - .filter(operator_client::public_key.eq(pubkey.to_bytes())) - .select(operator_client::id) - .first::(&mut conn) - .await - .optional() - .map_err(|e| { - error!(error = ?e, "Database error"); - Error::internal("Database operation failed") - }) -} - -async fn register_key(db: &DatabasePool, pubkey: &authn::PublicKey) -> Result { - let pubkey_bytes = pubkey.to_bytes(); - let mut conn = db.get().await.map_err(|e| { - error!(error = ?e, "Database pool error"); - Error::internal("Database unavailable") - })?; - - let id: i32 = diesel::insert_into(operator_client::table) - .values((operator_client::public_key.eq(pubkey_bytes),)) - .returning(operator_client::id) - .get_result(&mut conn) - .await - .map_err(|e| { - error!(error = ?e, "Database error"); - Error::internal("Database operation failed") - })?; - - Ok(id) -} - -pub(super) struct AuthContext<'a, T: ?Sized> { - pub(super) conn: &'a mut OperatorConnection, - pub(super) transport: &'a mut T, -} - -impl<'a, T: ?Sized> AuthContext<'a, T> { - pub(super) const fn new(conn: &'a mut OperatorConnection, transport: &'a mut T) -> Self { - Self { conn, transport } - } -} - -impl AuthStateMachineContext for AuthContext<'_, T> -where - T: Bi> + Send + ?Sized, -{ - type Error = Error; - - async fn prepare_challenge( - &mut self, - ChallengeRequest { - pubkey, - bootstrap_token, - }: ChallengeRequest, - ) -> Result { - // Verify pubkey is registered (unless bootstrapping) - if bootstrap_token.is_none() { - let id = get_client_id(&self.conn.db, &pubkey).await?; - if id.is_none() { - return Err(Error::UnregisteredPublicKey); - } - } - - let challenge = AuthChallenge::generate(&mut rand::rng()); - - self.transport - .send(Ok(Outbound::AuthChallenge { - challenge: challenge.clone(), - })) - .await - .map_err(|e| { - error!(?e, "Failed to send auth challenge"); - Error::Transport - })?; - - Ok(ChallengeContext { - challenge, - pubkey, - bootstrap_token, - }) - } - - async fn verify_solution( - &mut self, - ChallengeContext { - challenge, - pubkey, - bootstrap_token, - }: &ChallengeContext, - ChallengeSolution { solution }: ChallengeSolution, - ) -> Result { - let signature = authn::Signature::try_from(solution.as_slice()).map_err(|()| { - error!("Failed to decode signature in challenge solution"); - Error::InvalidChallengeSolution - })?; - - let valid = pubkey.verify(challenge, OPERATOR_CONTEXT, &signature); - - if !valid { - self.transport - .send(Err(Error::InvalidChallengeSolution)) - .await - .map_err(|_| Error::Transport)?; - return Err(Error::InvalidChallengeSolution); - } - - // Resolve client id: bootstrap (consume token + register) or lookup - let id = match bootstrap_token { - Some(token) => { - let token_ok: bool = self - .conn - .actors - .bootstrapper - .ask(ConsumeToken { - token: token.clone(), - }) - .await - .map_err(|e| { - error!(?e, "Failed to consume bootstrap token"); - Error::internal("Failed to consume bootstrap token") - })?; - - if !token_ok { - error!("Invalid bootstrap token provided"); - self.transport - .send(Err(Error::InvalidBootstrapToken)) - .await - .map_err(|_| Error::Transport)?; - return Err(Error::InvalidBootstrapToken); - } - - register_key(&self.conn.db, pubkey).await? - } - None => get_client_id(&self.conn.db, pubkey) - .await? - .ok_or(Error::UnregisteredPublicKey)?, - }; - - self.transport - .send(Ok(Outbound::AuthSuccess)) - .await - .map_err(|_| Error::Transport)?; - - Ok(Credentials { - id, - pubkey: pubkey.clone(), - }) - } -} +use super::{ + super::{Credentials, OperatorConnection}, + Error, +}; +use crate::{ + actors::bootstrap::ConsumeToken, + db::{DatabasePool, schema::operator_client}, + peers::operator::auth::Outbound, +}; +use arbiter_crypto::authn::{self, AuthChallenge, OPERATOR_CONTEXT}; +use arbiter_proto::transport::Bi; + +use diesel::{ExpressionMethods as _, OptionalExtension as _, QueryDsl}; +use diesel_async::RunQueryDsl; +use tracing::error; + +pub(super) struct ChallengeRequest { + pub(super) pubkey: authn::PublicKey, + pub(super) bootstrap_token: Option, +} + +pub struct ChallengeContext { + pub(super) challenge: AuthChallenge, + pub(super) pubkey: authn::PublicKey, + pub(super) bootstrap_token: Option, +} + +pub(super) struct ChallengeSolution { + pub(super) solution: Vec, +} + +smlang::statemachine!( + name: Auth, + custom_error: true, + transitions: { + *Init + AuthRequest(ChallengeRequest) / async prepare_challenge = SentChallenge(ChallengeContext), + SentChallenge(ChallengeContext) + ReceivedSolution(ChallengeSolution) / async verify_solution = AuthOk(Credentials), + } +); + +async fn get_client_id(db: &DatabasePool, pubkey: &authn::PublicKey) -> Result, Error> { + let mut conn = db.get().await.map_err(|e| { + error!(error = ?e, "Database pool error"); + Error::internal("Database unavailable") + })?; + + operator_client::table + .filter(operator_client::public_key.eq(pubkey.to_bytes())) + .select(operator_client::id) + .first::(&mut conn) + .await + .optional() + .map_err(|e| { + error!(error = ?e, "Database error"); + Error::internal("Database operation failed") + }) +} + +async fn register_key(db: &DatabasePool, pubkey: &authn::PublicKey) -> Result { + let pubkey_bytes = pubkey.to_bytes(); + let mut conn = db.get().await.map_err(|e| { + error!(error = ?e, "Database pool error"); + Error::internal("Database unavailable") + })?; + + let id: i32 = diesel::insert_into(operator_client::table) + .values((operator_client::public_key.eq(pubkey_bytes),)) + .returning(operator_client::id) + .get_result(&mut conn) + .await + .map_err(|e| { + error!(error = ?e, "Database error"); + Error::internal("Database operation failed") + })?; + + Ok(id) +} + +pub(super) struct AuthContext<'a, T: ?Sized> { + pub(super) conn: &'a mut OperatorConnection, + pub(super) transport: &'a mut T, +} + +impl<'a, T: ?Sized> AuthContext<'a, T> { + pub(super) const fn new(conn: &'a mut OperatorConnection, transport: &'a mut T) -> Self { + Self { conn, transport } + } +} + +impl AuthStateMachineContext for AuthContext<'_, T> +where + T: Bi> + Send + ?Sized, +{ + type Error = Error; + + async fn prepare_challenge( + &mut self, + ChallengeRequest { + pubkey, + bootstrap_token, + }: ChallengeRequest, + ) -> Result { + // Verify pubkey is registered (unless bootstrapping) + if bootstrap_token.is_none() { + let id = get_client_id(&self.conn.db, &pubkey).await?; + if id.is_none() { + return Err(Error::UnregisteredPublicKey); + } + } + + let challenge = AuthChallenge::generate(&mut rand::rng()); + + self.transport + .send(Ok(Outbound::AuthChallenge { + challenge: challenge.clone(), + })) + .await + .map_err(|e| { + error!(?e, "Failed to send auth challenge"); + Error::Transport + })?; + + Ok(ChallengeContext { + challenge, + pubkey, + bootstrap_token, + }) + } + + async fn verify_solution( + &mut self, + ChallengeContext { + challenge, + pubkey, + bootstrap_token, + }: &ChallengeContext, + ChallengeSolution { solution }: ChallengeSolution, + ) -> Result { + let signature = authn::Signature::try_from(solution.as_slice()).map_err(|()| { + error!("Failed to decode signature in challenge solution"); + Error::InvalidChallengeSolution + })?; + + let valid = pubkey.verify(challenge, OPERATOR_CONTEXT, &signature); + + if !valid { + self.transport + .send(Err(Error::InvalidChallengeSolution)) + .await + .map_err(|_| Error::Transport)?; + return Err(Error::InvalidChallengeSolution); + } + + // Resolve client id: bootstrap (consume token + register) or lookup + let id = match bootstrap_token { + Some(token) => { + let token_ok: bool = self + .conn + .actors + .bootstrapper + .ask(ConsumeToken { + token: token.clone(), + }) + .await + .map_err(|e| { + error!(?e, "Failed to consume bootstrap token"); + Error::internal("Failed to consume bootstrap token") + })?; + + if !token_ok { + error!("Invalid bootstrap token provided"); + self.transport + .send(Err(Error::InvalidBootstrapToken)) + .await + .map_err(|_| Error::Transport)?; + return Err(Error::InvalidBootstrapToken); + } + + register_key(&self.conn.db, pubkey).await? + } + None => get_client_id(&self.conn.db, pubkey) + .await? + .ok_or(Error::UnregisteredPublicKey)?, + }; + + self.transport + .send(Ok(Outbound::AuthSuccess)) + .await + .map_err(|_| Error::Transport)?; + + Ok(Credentials { + id, + pubkey: pubkey.clone(), + }) + } +} diff --git a/server/crates/arbiter-server/src/peers/operator/mod.rs b/server/crates/arbiter-server/src/peers/operator/mod.rs index 0869d51..993f203 100644 --- a/server/crates/arbiter-server/src/peers/operator/mod.rs +++ b/server/crates/arbiter-server/src/peers/operator/mod.rs @@ -1,185 +1,185 @@ -use crate::{ - actors::{ - GlobalActors, - vault::{GetState, Vault}, - }, - crypto::integrity::{self, AttestationStatus, Integrable}, - db::{DatabaseError, DatabasePool}, - peers::client::ClientProfile, -}; -use arbiter_crypto::authn; -use arbiter_macros::Hashable; -use arbiter_proto::transport::{Bi, Sender}; -use vault_gate::VaultGate; - -use kameo::actor::{ActorRef, Spawn as _}; -use tokio::sync::oneshot; -use tracing::{error, warn}; - -pub use auth::authenticate; -pub use session::OperatorSession; - -pub mod auth; -pub mod session; -pub mod vault_gate; - -#[derive(Debug, Clone, Hashable)] -pub struct Credentials { - pub id: i32, - pub pubkey: authn::PublicKey, -} - -impl Integrable for Credentials { - const KIND: &'static str = "operator_credentials"; -} - -// Messages, sent by operator to connection client without having a request -#[derive(Debug)] -pub enum OutOfBand { - ClientConnectionRequest { profile: ClientProfile }, - ClientConnectionCancel { pubkey: authn::PublicKey }, -} - -#[derive(Clone)] -pub struct OperatorConnection { - pub(crate) db: DatabasePool, - pub(crate) actors: GlobalActors, -} - -impl OperatorConnection { - pub const fn new(db: DatabasePool, actors: GlobalActors) -> Self { - Self { db, actors } - } -} - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("authentication failed: {0:?}")] - Auth(auth::Error), - #[error("vault gate failed: {0}")] - VaultGate(#[from] vault_gate::Error), - #[error("transport closed unexpectedly")] - Transport, - #[error("database error: {0}")] - Database(DatabaseError), - #[error("internal: {0}")] - Internal(String), -} - -impl From for Error { - fn from(err: auth::Error) -> Self { - Self::Auth(err) - } -} - -async fn verify_integrity( - db: &DatabasePool, - vault: &ActorRef, - credentials: &Credentials, -) -> Result<(), Error> { - let mut conn = db - .get() - .await - .map_err(|_| Error::Internal("DB unavailable".into()))?; - match integrity::verify_entity(&mut conn, vault, credentials, credentials.id).await { - Ok(AttestationStatus::Attested) => Ok(()), - Ok(AttestationStatus::Unavailable) => { - Err(Error::Internal("Vault sealed during promotion".into())) - } - Err(e) => { - error!(?e, "Integrity verification failed during unseal promotion"); - Err(Error::Internal("Integrity check failed".into())) - } - } -} - -async fn should_run_gate(vault: &ActorRef) -> Result { - let vault_state = vault - .ask(GetState {}) - .await - .map_err(|_| Error::Internal("Failed to contact the vault".into()))?; - - Ok(!matches!( - vault_state, - crate::actors::vault::VaultState::Unsealed - )) -} - -async fn run_vault_gate( - props: &OperatorConnection, - transport: &mut T, - auth_creds: Credentials, -) -> Result<(), Error> -where - T: Bi> + Send + ?Sized, -{ - let (promotion_tx, mut promotion_rx) = oneshot::channel(); - let gate = VaultGate::spawn(VaultGate::new( - auth_creds, - props.actors.clone(), - props.db.clone(), - promotion_tx, - )); - - let result = loop { - tokio::select! { - promotion = &mut promotion_rx => { - break match promotion { - Ok(Ok(creds)) => Ok(creds), - Ok(Err(err)) => Err(Error::VaultGate(err)), - Err(_) => Err(Error::Internal( - "vault gate promotion channel closed".into(), - )), - }; - } - - inbound = transport.recv() => { - let Some(inbound) = inbound else { - break Err(Error::Transport); - }; - - match gate.ask(inbound).await { - Ok(outbound) => { - if transport.send(Ok(outbound)).await.is_err() { - break Err(Error::Transport); - } - } - Err(err) => { - warn!(?err, "VaultGate failed to handle message"); - break Err(Error::Internal(format!( - "vault gate ask failed: {err:?}" - ))); - } - } - } - } - }; - - gate.kill(); - result -} - -pub async fn start( - props: &mut OperatorConnection, - mut transport: T, - oob_sender: Box>, -) -> Result, Error> -where - T: Bi> + Send, - T: Bi> + Send, -{ - let creds = authenticate(props, &mut transport).await?; - - // should run vault gate only if sealed / unbootstrapped - if should_run_gate(&props.actors.vault).await? { - run_vault_gate(props, &mut transport, creds.clone()).await?; - } - - // checking the integrity - verify_integrity(&props.db, &props.actors.vault, &creds).await?; - - Ok(OperatorSession::spawn(OperatorSession::new( - props.clone(), - oob_sender, - ))) -} +use crate::{ + actors::{ + GlobalActors, + vault::{GetState, Vault}, + }, + crypto::integrity::{self, AttestationStatus, Integrable}, + db::{DatabaseError, DatabasePool}, + peers::client::ClientProfile, +}; +use arbiter_crypto::authn; +use arbiter_macros::Hashable; +use arbiter_proto::transport::{Bi, Sender}; +use vault_gate::VaultGate; + +use kameo::actor::{ActorRef, Spawn as _}; +use tokio::sync::oneshot; +use tracing::{error, warn}; + +pub use auth::authenticate; +pub use session::OperatorSession; + +pub mod auth; +pub mod session; +pub mod vault_gate; + +#[derive(Debug, Clone, Hashable)] +pub struct Credentials { + pub id: i32, + pub pubkey: authn::PublicKey, +} + +impl Integrable for Credentials { + const KIND: &'static str = "operator_credentials"; +} + +// Messages, sent by operator to connection client without having a request +#[derive(Debug)] +pub enum OutOfBand { + ClientConnectionRequest { profile: ClientProfile }, + ClientConnectionCancel { pubkey: authn::PublicKey }, +} + +#[derive(Clone)] +pub struct OperatorConnection { + pub(crate) db: DatabasePool, + pub(crate) actors: GlobalActors, +} + +impl OperatorConnection { + pub const fn new(db: DatabasePool, actors: GlobalActors) -> Self { + Self { db, actors } + } +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("authentication failed: {0:?}")] + Auth(auth::Error), + #[error("vault gate failed: {0}")] + VaultGate(#[from] vault_gate::Error), + #[error("transport closed unexpectedly")] + Transport, + #[error("database error: {0}")] + Database(DatabaseError), + #[error("internal: {0}")] + Internal(String), +} + +impl From for Error { + fn from(err: auth::Error) -> Self { + Self::Auth(err) + } +} + +async fn verify_integrity( + db: &DatabasePool, + vault: &ActorRef, + credentials: &Credentials, +) -> Result<(), Error> { + let mut conn = db + .get() + .await + .map_err(|_| Error::Internal("DB unavailable".into()))?; + match integrity::verify_entity(&mut conn, vault, credentials, credentials.id).await { + Ok(AttestationStatus::Attested) => Ok(()), + Ok(AttestationStatus::Unavailable) => { + Err(Error::Internal("Vault sealed during promotion".into())) + } + Err(e) => { + error!(?e, "Integrity verification failed during unseal promotion"); + Err(Error::Internal("Integrity check failed".into())) + } + } +} + +async fn should_run_gate(vault: &ActorRef) -> Result { + let vault_state = vault + .ask(GetState {}) + .await + .map_err(|_| Error::Internal("Failed to contact the vault".into()))?; + + Ok(!matches!( + vault_state, + crate::actors::vault::VaultState::Unsealed + )) +} + +async fn run_vault_gate( + props: &OperatorConnection, + transport: &mut T, + auth_creds: Credentials, +) -> Result<(), Error> +where + T: Bi> + Send + ?Sized, +{ + let (promotion_tx, mut promotion_rx) = oneshot::channel(); + let gate = VaultGate::spawn(VaultGate::new( + auth_creds, + props.actors.clone(), + props.db.clone(), + promotion_tx, + )); + + let result = loop { + tokio::select! { + promotion = &mut promotion_rx => { + break match promotion { + Ok(Ok(creds)) => Ok(creds), + Ok(Err(err)) => Err(Error::VaultGate(err)), + Err(_) => Err(Error::Internal( + "vault gate promotion channel closed".into(), + )), + }; + } + + inbound = transport.recv() => { + let Some(inbound) = inbound else { + break Err(Error::Transport); + }; + + match gate.ask(inbound).await { + Ok(outbound) => { + if transport.send(Ok(outbound)).await.is_err() { + break Err(Error::Transport); + } + } + Err(err) => { + warn!(?err, "VaultGate failed to handle message"); + break Err(Error::Internal(format!( + "vault gate ask failed: {err:?}" + ))); + } + } + } + } + }; + + gate.kill(); + result +} + +pub async fn start( + props: &mut OperatorConnection, + mut transport: T, + oob_sender: Box>, +) -> Result, Error> +where + T: Bi> + Send, + T: Bi> + Send, +{ + let creds = authenticate(props, &mut transport).await?; + + // should run vault gate only if sealed / unbootstrapped + if should_run_gate(&props.actors.vault).await? { + run_vault_gate(props, &mut transport, creds.clone()).await?; + } + + // checking the integrity + verify_integrity(&props.db, &props.actors.vault, &creds).await?; + + Ok(OperatorSession::spawn(OperatorSession::new( + props.clone(), + oob_sender, + ))) +} diff --git a/server/crates/arbiter-server/src/peers/operator/session/handlers.rs b/server/crates/arbiter-server/src/peers/operator/session/handlers.rs index 5ac6cb4..96c3d47 100644 --- a/server/crates/arbiter-server/src/peers/operator/session/handlers.rs +++ b/server/crates/arbiter-server/src/peers/operator/session/handlers.rs @@ -1,273 +1,273 @@ -use super::{Error, OperatorSession}; -use crate::{ - actors::evm::{ - ClientSignTransaction, Generate, ListWallets, OperatorCreateGrant, OperatorListGrants, - SignTransactionError as EvmSignError, - }, - actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer, - actors::vault::VaultState, - db::models::{EvmWalletAccess, NewEvmWalletAccess, ProgramClient, ProgramClientMetadata}, - evm::policies::{Grant, SpecificGrant}, -}; -use arbiter_crypto::authn; - -use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature}; -use diesel::{ExpressionMethods as _, QueryDsl as _, SelectableHelper}; -use diesel_async::{AsyncConnection, RunQueryDsl}; -use kameo::{error::SendError, messages, prelude::Context}; -use tracing::error; - -#[derive(Debug, Error)] -pub enum SignTransactionError { - #[error("Policy evaluation failed")] - Vet(#[from] crate::evm::VetError), - - #[error("Internal signing error")] - Internal, -} - -#[derive(Debug, Error)] -pub enum GrantMutationError { - #[error("Vault is sealed")] - VaultSealed, - - #[error("Internal grant mutation error")] - Internal, -} - -#[messages] -impl OperatorSession { - #[message] - pub(crate) async fn handle_query_vault_state(&mut self) -> Result { - use crate::actors::vault::GetState; - - let vault_state = match self.props.actors.vault.ask(GetState {}).await { - Ok(state) => state, - Err(err) => { - error!(?err, actor = "operator", "vault.query.failed"); - return Err(Error::internal("Vault is in broken state")); - } - }; - - Ok(vault_state) - } -} - -#[messages] -impl OperatorSession { - #[message] - pub(crate) async fn handle_evm_wallet_create(&mut self) -> Result<(i32, Address), Error> { - match self.props.actors.evm.ask(Generate {}).await { - Ok(address) => Ok(address), - Err(SendError::HandlerError(err)) => Err(Error::internal(format!( - "EVM wallet generation failed: {err}" - ))), - Err(err) => { - error!(?err, "EVM actor unreachable during wallet create"); - Err(Error::internal("EVM actor unreachable")) - } - } - } - - #[message] - pub(crate) async fn handle_evm_wallet_list(&mut self) -> Result, Error> { - match self.props.actors.evm.ask(ListWallets {}).await { - Ok(wallets) => Ok(wallets), - Err(err) => { - error!(?err, "EVM wallet list failed"); - Err(Error::internal("Failed to list EVM wallets")) - } - } - } -} - -#[messages] -impl OperatorSession { - #[message] - pub(crate) async fn handle_grant_list(&mut self) -> Result>, Error> { - match self.props.actors.evm.ask(OperatorListGrants {}).await { - Ok(grants) => Ok(grants), - Err(err) => { - error!(?err, "EVM grant list failed"); - Err(Error::internal("Failed to list EVM grants")) - } - } - } - - #[message] - pub(crate) async fn handle_grant_create( - &mut self, - basic: crate::evm::policies::SharedGrantSettings, - grant: SpecificGrant, - ) -> Result { - match self - .props - .actors - .evm - .ask(OperatorCreateGrant { basic, grant }) - .await - { - Ok(grant_id) => Ok(grant_id), - Err(err) => { - error!(?err, "EVM grant create failed"); - Err(GrantMutationError::Internal) - } - } - } - - #[message] - pub(crate) fn handle_grant_delete(&mut self, grant_id: i32) -> Result<(), GrantMutationError> { - // match self - // .props - // .actors - // .evm - // .ask(OperatorDeleteGrant { grant_id }) - // .await - // { - // Ok(()) => Ok(()), - // Err(err) => { - // error!(?err, "EVM grant delete failed"); - // Err(GrantMutationError::Internal) - // } - // } - let _ = grant_id; - todo!() - } - - #[message] - pub(crate) async fn handle_sign_transaction( - &mut self, - client_id: i32, - wallet_address: Address, - transaction: TxEip1559, - ) -> Result { - match self - .props - .actors - .evm - .ask(ClientSignTransaction { - client_id, - wallet_address, - transaction, - }) - .await - { - Ok(signature) => Ok(signature), - Err(SendError::HandlerError(EvmSignError::Vet(vet_error))) => { - Err(SignTransactionError::Vet(vet_error)) - } - Err(err) => { - error!(?err, "EVM sign transaction failed in operator session"); - Err(SignTransactionError::Internal) - } - } - } - - #[message] - pub(crate) async fn handle_grant_evm_wallet_access( - &mut self, - entries: Vec, - ) -> Result<(), Error> { - let mut conn = self.props.db.get().await?; - conn.transaction(async |conn| { - use crate::db::schema::evm_wallet_access; - - for entry in entries { - diesel::insert_into(evm_wallet_access::table) - .values(&entry) - .on_conflict_do_nothing() - .execute(&mut *conn) - .await?; - } - - Result::<_, Error>::Ok(()) - }) - .await?; - Ok(()) - } - - #[message] - pub(crate) async fn handle_revoke_evm_wallet_access( - &mut self, - entries: Vec, - ) -> Result<(), Error> { - let mut conn = self.props.db.get().await?; - conn.transaction(async |conn| { - use crate::db::schema::evm_wallet_access; - for entry in entries { - diesel::delete(evm_wallet_access::table) - .filter(evm_wallet_access::wallet_id.eq(entry)) - .execute(&mut *conn) - .await?; - } - - Result::<_, Error>::Ok(()) - }) - .await?; - Ok(()) - } - - #[message] - pub(crate) async fn handle_list_wallet_access( - &mut self, - ) -> Result, Error> { - let mut conn = self.props.db.get().await?; - let access_entries = crate::db::schema::evm_wallet_access::table - .select(EvmWalletAccess::as_select()) - .load::<_>(&mut conn) - .await?; - Ok(access_entries) - } -} - -#[messages] -impl OperatorSession { - #[message(ctx)] - pub(crate) async fn handle_new_client_approve( - &mut self, - approved: bool, - pubkey: authn::PublicKey, - ctx: &mut Context>, - ) -> Result<(), Error> { - let Some(pending_approval) = self.pending_client_approvals.remove(&pubkey.to_bytes()) - else { - error!("Received client connection response for unknown client"); - return Err(Error::internal("Unknown client in connection response")); - }; - - pending_approval - .controller - .tell(ClientApprovalAnswer { approved }) - .await - .map_err(|err| { - error!( - ?err, - "Failed to send client approval response to controller" - ); - Error::internal("Failed to send client approval response to controller") - })?; - - ctx.actor_ref().unlink(&pending_approval.controller).await; - - Ok(()) - } - - #[message] - pub(crate) async fn handle_sdk_client_list( - &mut self, - ) -> Result, Error> { - use crate::db::schema::{client_metadata, program_client}; - let mut conn = self.props.db.get().await?; - - let clients = program_client::table - .inner_join(client_metadata::table) - .select(( - ProgramClient::as_select(), - ProgramClientMetadata::as_select(), - )) - .load::<(ProgramClient, ProgramClientMetadata)>(&mut conn) - .await?; - - Ok(clients) - } -} +use super::{Error, OperatorSession}; +use crate::{ + actors::evm::{ + ClientSignTransaction, Generate, ListWallets, OperatorCreateGrant, OperatorListGrants, + SignTransactionError as EvmSignError, + }, + actors::flow_coordinator::client_connect_approval::ClientApprovalAnswer, + actors::vault::VaultState, + db::models::{EvmWalletAccess, NewEvmWalletAccess, ProgramClient, ProgramClientMetadata}, + evm::policies::{Grant, SpecificGrant}, +}; +use arbiter_crypto::authn; + +use alloy::{consensus::TxEip1559, primitives::Address, signers::Signature}; +use diesel::{ExpressionMethods as _, QueryDsl as _, SelectableHelper}; +use diesel_async::{AsyncConnection, RunQueryDsl}; +use kameo::{error::SendError, messages, prelude::Context}; +use tracing::error; + +#[derive(Debug, Error)] +pub enum SignTransactionError { + #[error("Policy evaluation failed")] + Vet(#[from] crate::evm::VetError), + + #[error("Internal signing error")] + Internal, +} + +#[derive(Debug, Error)] +pub enum GrantMutationError { + #[error("Vault is sealed")] + VaultSealed, + + #[error("Internal grant mutation error")] + Internal, +} + +#[messages] +impl OperatorSession { + #[message] + pub(crate) async fn handle_query_vault_state(&mut self) -> Result { + use crate::actors::vault::GetState; + + let vault_state = match self.props.actors.vault.ask(GetState {}).await { + Ok(state) => state, + Err(err) => { + error!(?err, actor = "operator", "vault.query.failed"); + return Err(Error::internal("Vault is in broken state")); + } + }; + + Ok(vault_state) + } +} + +#[messages] +impl OperatorSession { + #[message] + pub(crate) async fn handle_evm_wallet_create(&mut self) -> Result<(i32, Address), Error> { + match self.props.actors.evm.ask(Generate {}).await { + Ok(address) => Ok(address), + Err(SendError::HandlerError(err)) => Err(Error::internal(format!( + "EVM wallet generation failed: {err}" + ))), + Err(err) => { + error!(?err, "EVM actor unreachable during wallet create"); + Err(Error::internal("EVM actor unreachable")) + } + } + } + + #[message] + pub(crate) async fn handle_evm_wallet_list(&mut self) -> Result, Error> { + match self.props.actors.evm.ask(ListWallets {}).await { + Ok(wallets) => Ok(wallets), + Err(err) => { + error!(?err, "EVM wallet list failed"); + Err(Error::internal("Failed to list EVM wallets")) + } + } + } +} + +#[messages] +impl OperatorSession { + #[message] + pub(crate) async fn handle_grant_list(&mut self) -> Result>, Error> { + match self.props.actors.evm.ask(OperatorListGrants {}).await { + Ok(grants) => Ok(grants), + Err(err) => { + error!(?err, "EVM grant list failed"); + Err(Error::internal("Failed to list EVM grants")) + } + } + } + + #[message] + pub(crate) async fn handle_grant_create( + &mut self, + basic: crate::evm::policies::SharedGrantSettings, + grant: SpecificGrant, + ) -> Result { + match self + .props + .actors + .evm + .ask(OperatorCreateGrant { basic, grant }) + .await + { + Ok(grant_id) => Ok(grant_id), + Err(err) => { + error!(?err, "EVM grant create failed"); + Err(GrantMutationError::Internal) + } + } + } + + #[message] + pub(crate) fn handle_grant_delete(&mut self, grant_id: i32) -> Result<(), GrantMutationError> { + // match self + // .props + // .actors + // .evm + // .ask(OperatorDeleteGrant { grant_id }) + // .await + // { + // Ok(()) => Ok(()), + // Err(err) => { + // error!(?err, "EVM grant delete failed"); + // Err(GrantMutationError::Internal) + // } + // } + let _ = grant_id; + todo!() + } + + #[message] + pub(crate) async fn handle_sign_transaction( + &mut self, + client_id: i32, + wallet_address: Address, + transaction: TxEip1559, + ) -> Result { + match self + .props + .actors + .evm + .ask(ClientSignTransaction { + client_id, + wallet_address, + transaction, + }) + .await + { + Ok(signature) => Ok(signature), + Err(SendError::HandlerError(EvmSignError::Vet(vet_error))) => { + Err(SignTransactionError::Vet(vet_error)) + } + Err(err) => { + error!(?err, "EVM sign transaction failed in operator session"); + Err(SignTransactionError::Internal) + } + } + } + + #[message] + pub(crate) async fn handle_grant_evm_wallet_access( + &mut self, + entries: Vec, + ) -> Result<(), Error> { + let mut conn = self.props.db.get().await?; + conn.transaction(async |conn| { + use crate::db::schema::evm_wallet_access; + + for entry in entries { + diesel::insert_into(evm_wallet_access::table) + .values(&entry) + .on_conflict_do_nothing() + .execute(&mut *conn) + .await?; + } + + Result::<_, Error>::Ok(()) + }) + .await?; + Ok(()) + } + + #[message] + pub(crate) async fn handle_revoke_evm_wallet_access( + &mut self, + entries: Vec, + ) -> Result<(), Error> { + let mut conn = self.props.db.get().await?; + conn.transaction(async |conn| { + use crate::db::schema::evm_wallet_access; + for entry in entries { + diesel::delete(evm_wallet_access::table) + .filter(evm_wallet_access::wallet_id.eq(entry)) + .execute(&mut *conn) + .await?; + } + + Result::<_, Error>::Ok(()) + }) + .await?; + Ok(()) + } + + #[message] + pub(crate) async fn handle_list_wallet_access( + &mut self, + ) -> Result, Error> { + let mut conn = self.props.db.get().await?; + let access_entries = crate::db::schema::evm_wallet_access::table + .select(EvmWalletAccess::as_select()) + .load::<_>(&mut conn) + .await?; + Ok(access_entries) + } +} + +#[messages] +impl OperatorSession { + #[message(ctx)] + pub(crate) async fn handle_new_client_approve( + &mut self, + approved: bool, + pubkey: authn::PublicKey, + ctx: &mut Context>, + ) -> Result<(), Error> { + let Some(pending_approval) = self.pending_client_approvals.remove(&pubkey.to_bytes()) + else { + error!("Received client connection response for unknown client"); + return Err(Error::internal("Unknown client in connection response")); + }; + + pending_approval + .controller + .tell(ClientApprovalAnswer { approved }) + .await + .map_err(|err| { + error!( + ?err, + "Failed to send client approval response to controller" + ); + Error::internal("Failed to send client approval response to controller") + })?; + + ctx.actor_ref().unlink(&pending_approval.controller).await; + + Ok(()) + } + + #[message] + pub(crate) async fn handle_sdk_client_list( + &mut self, + ) -> Result, Error> { + use crate::db::schema::{client_metadata, program_client}; + let mut conn = self.props.db.get().await?; + + let clients = program_client::table + .inner_join(client_metadata::table) + .select(( + ProgramClient::as_select(), + ProgramClientMetadata::as_select(), + )) + .load::<(ProgramClient, ProgramClientMetadata)>(&mut conn) + .await?; + + Ok(clients) + } +} diff --git a/server/crates/arbiter-server/src/peers/operator/session/mod.rs b/server/crates/arbiter-server/src/peers/operator/session/mod.rs index d7566ac..d1dc524 100644 --- a/server/crates/arbiter-server/src/peers/operator/session/mod.rs +++ b/server/crates/arbiter-server/src/peers/operator/session/mod.rs @@ -1,161 +1,161 @@ -use super::{OutOfBand, OperatorConnection}; -use crate::{ - actors::{ - flow_coordinator::client_connect_approval::{ClientApprovalAnswer, ClientApprovalController}, - operator_registry::ConnectOperator, - }, - peers::client::ClientProfile, -}; -use arbiter_crypto::authn; -use arbiter_proto::transport::Sender; - -use kameo::{Actor, actor::ActorRef, messages}; -use std::{borrow::Cow, collections::HashMap}; -use thiserror::Error; -use tracing::error; - -#[derive(Debug, Error)] -pub enum Error { - #[error("State transition failed")] - State, - - #[error("Internal error: {message}")] - Internal { message: Cow<'static, str> }, -} - -impl From for Error { - fn from(err: crate::db::PoolError) -> Self { - error!(?err, "Database pool error"); - Self::internal("Database pool error") - } -} -impl From for Error { - fn from(err: diesel::result::Error) -> Self { - error!(?err, "Database error"); - Self::internal("Database error") - } -} - -impl Error { - pub fn internal(message: impl Into>) -> Self { - Self::Internal { - message: message.into(), - } - } -} - -pub struct PendingClientApproval { - pubkey: authn::PublicKey, - controller: ActorRef, -} - -pub struct OperatorSession { - props: OperatorConnection, - sender: Box>, - - pending_client_approvals: HashMap, PendingClientApproval>, -} - -pub mod handlers; - -impl OperatorSession { - pub(crate) fn new(props: OperatorConnection, sender: Box>) -> Self { - Self { - props, - sender, - pending_client_approvals: HashMap::default(), - } - } -} - -#[messages] -impl OperatorSession { - #[message] - pub async fn begin_new_client_approval( - &mut self, - client: ClientProfile, - controller: ActorRef, - ) { - if let Err(e) = self - .sender - .send(OutOfBand::ClientConnectionRequest { - profile: client.clone(), - }) - .await - { - error!( - ?e, - actor = "operator", - event = "failed to announce new client connection" - ); - let _ = controller.tell(ClientApprovalAnswer { approved: false }).await; - return; - } - - self.pending_client_approvals.insert( - client.pubkey.to_bytes(), - PendingClientApproval { - pubkey: client.pubkey, - controller, - }, - ); - } -} - -impl Actor for OperatorSession { - type Args = Self; - - type Error = Error; - - async fn on_start(args: Self::Args, this: ActorRef) -> Result { - args.props - .actors - .operator_registry - .ask(ConnectOperator { - actor: this.clone(), - }) - .await - .map_err(|err| { - error!( - ?err, - "Failed to register operator connection with operator registry" - ); - Error::internal("Failed to register operator connection with operator registry") - })?; - Ok(args) - } - - async fn on_link_died( - &mut self, - _: kameo::prelude::WeakActorRef, - id: kameo::prelude::ActorId, - _: kameo::prelude::ActorStopReason, - ) -> Result, Self::Error> { - let cancelled_pubkey = self - .pending_client_approvals - .iter() - .find_map(|(k, v)| (v.controller.id() == id).then_some(k.clone())); - - if let Some(pubkey_bytes) = cancelled_pubkey { - let Some(approval) = self.pending_client_approvals.remove(&pubkey_bytes) else { - return Ok(std::ops::ControlFlow::Continue(())); - }; - - if let Err(e) = self - .sender - .send(OutOfBand::ClientConnectionCancel { - pubkey: approval.pubkey, - }) - .await - { - error!( - ?e, - actor = "operator", - event = "failed to announce client connection cancellation" - ); - } - } - - Ok(std::ops::ControlFlow::Continue(())) - } -} +use super::{OutOfBand, OperatorConnection}; +use crate::{ + actors::{ + flow_coordinator::client_connect_approval::{ClientApprovalAnswer, ClientApprovalController}, + operator_registry::ConnectOperator, + }, + peers::client::ClientProfile, +}; +use arbiter_crypto::authn; +use arbiter_proto::transport::Sender; + +use kameo::{Actor, actor::ActorRef, messages}; +use std::{borrow::Cow, collections::HashMap}; +use thiserror::Error; +use tracing::error; + +#[derive(Debug, Error)] +pub enum Error { + #[error("State transition failed")] + State, + + #[error("Internal error: {message}")] + Internal { message: Cow<'static, str> }, +} + +impl From for Error { + fn from(err: crate::db::PoolError) -> Self { + error!(?err, "Database pool error"); + Self::internal("Database pool error") + } +} +impl From for Error { + fn from(err: diesel::result::Error) -> Self { + error!(?err, "Database error"); + Self::internal("Database error") + } +} + +impl Error { + pub fn internal(message: impl Into>) -> Self { + Self::Internal { + message: message.into(), + } + } +} + +pub struct PendingClientApproval { + pubkey: authn::PublicKey, + controller: ActorRef, +} + +pub struct OperatorSession { + props: OperatorConnection, + sender: Box>, + + pending_client_approvals: HashMap, PendingClientApproval>, +} + +pub mod handlers; + +impl OperatorSession { + pub(crate) fn new(props: OperatorConnection, sender: Box>) -> Self { + Self { + props, + sender, + pending_client_approvals: HashMap::default(), + } + } +} + +#[messages] +impl OperatorSession { + #[message] + pub async fn begin_new_client_approval( + &mut self, + client: ClientProfile, + controller: ActorRef, + ) { + if let Err(e) = self + .sender + .send(OutOfBand::ClientConnectionRequest { + profile: client.clone(), + }) + .await + { + error!( + ?e, + actor = "operator", + event = "failed to announce new client connection" + ); + let _ = controller.tell(ClientApprovalAnswer { approved: false }).await; + return; + } + + self.pending_client_approvals.insert( + client.pubkey.to_bytes(), + PendingClientApproval { + pubkey: client.pubkey, + controller, + }, + ); + } +} + +impl Actor for OperatorSession { + type Args = Self; + + type Error = Error; + + async fn on_start(args: Self::Args, this: ActorRef) -> Result { + args.props + .actors + .operator_registry + .ask(ConnectOperator { + actor: this.clone(), + }) + .await + .map_err(|err| { + error!( + ?err, + "Failed to register operator connection with operator registry" + ); + Error::internal("Failed to register operator connection with operator registry") + })?; + Ok(args) + } + + async fn on_link_died( + &mut self, + _: kameo::prelude::WeakActorRef, + id: kameo::prelude::ActorId, + _: kameo::prelude::ActorStopReason, + ) -> Result, Self::Error> { + let cancelled_pubkey = self + .pending_client_approvals + .iter() + .find_map(|(k, v)| (v.controller.id() == id).then_some(k.clone())); + + if let Some(pubkey_bytes) = cancelled_pubkey { + let Some(approval) = self.pending_client_approvals.remove(&pubkey_bytes) else { + return Ok(std::ops::ControlFlow::Continue(())); + }; + + if let Err(e) = self + .sender + .send(OutOfBand::ClientConnectionCancel { + pubkey: approval.pubkey, + }) + .await + { + error!( + ?e, + actor = "operator", + event = "failed to announce client connection cancellation" + ); + } + } + + Ok(std::ops::ControlFlow::Continue(())) + } +} diff --git a/server/crates/arbiter-server/src/peers/operator/vault_gate/mod.rs b/server/crates/arbiter-server/src/peers/operator/vault_gate/mod.rs index 6a8a265..f16178f 100644 --- a/server/crates/arbiter-server/src/peers/operator/vault_gate/mod.rs +++ b/server/crates/arbiter-server/src/peers/operator/vault_gate/mod.rs @@ -1,288 +1,288 @@ -use super::Credentials; -use crate::{ - actors::{ - GlobalActors, - vault::{self, Bootstrap, GetState, TryUnseal, VaultState, events}, - }, - crypto::integrity::{self}, - db::DatabasePool, -}; -use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; -use state::State; - -use chacha20poly1305::{AeadInPlace, KeyInit as _, XChaCha20Poly1305, XNonce}; -use kameo::{Actor, error::SendError, messages, prelude::Message}; -use kameo_actors::message_bus::Register; -use tokio::sync::oneshot; -use tracing::{error, info}; -use x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret}; - -pub mod state; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Vault is already bootstrapped")] - AlreadyBootstrapped, - #[error("Invalid key provided")] - InvalidKey, - - #[error("State transition failed")] - State, - - #[error("Internal error: {0}")] - Internal(String), -} -impl Error { - fn internal(message: impl Into) -> Self { - Self::Internal(message.into()) - } -} - -pub struct HandshakeResponse { - pub server_pubkey: PublicKey, -} - -pub struct VaultGate { - pub auth_creds: Credentials, - pub promotion_tx: Option>>, - pub state: State, - pub actors: GlobalActors, - pub db: DatabasePool, -} - -impl VaultGate { - pub fn new( - auth_creds: Credentials, - actors: GlobalActors, - db: DatabasePool, - promotion_tx: oneshot::Sender>, - ) -> Self { - Self { - auth_creds, - state: State::default(), - actors, - db, - promotion_tx: Some(promotion_tx), - } - } -} - -impl Actor for VaultGate { - type Args = Self; - - type Error = (); - - async fn on_start( - args: Self::Args, - actor_ref: kameo::prelude::ActorRef, - ) -> Result { - let _ = args - .actors - .events - .tell(Register( - actor_ref.clone().recipient::(), - )) - .await; - let _ = args - .actors - .events - .tell(Register(actor_ref.recipient::())) - .await; - Ok(args) - } -} - -impl VaultGate { - fn decrypt_key( - secret: &SharedSecret, - nonce: &[u8], - ciphertext: &[u8], - associated_data: &[u8], - ) -> Result>, ()> { - let nonce = XNonce::from_slice(nonce); - - let cipher = XChaCha20Poly1305::new(secret.as_bytes().into()); - - let mut key_buffer = SafeCell::new(ciphertext.to_vec()); - - let decryption_result = key_buffer.write_inline(|write_handle| { - cipher.decrypt_in_place(nonce, associated_data, write_handle) - }); - - match decryption_result { - Ok(()) => Ok(key_buffer), - Err(err) => { - error!(?err, "Failed to decrypt encrypted key material"); - Err(()) - } - } - } -} - -#[messages(messages = Inbound, replies = Outbound)] -impl VaultGate { - #[message] - pub fn handle_handshake( - &mut self, - client_pubkey: PublicKey, - ) -> Result { - let ephemeral_secret = EphemeralSecret::random(); - let public_key = PublicKey::from(&ephemeral_secret); - - let secret = ephemeral_secret.diffie_hellman(&client_pubkey); - - self.state = State::ReadyForExchange { - server_key: public_key, - secret, - }; - - Ok(HandshakeResponse { - server_pubkey: public_key, - }) - } - - #[message] - pub async fn handle_unseal_encrypted_key( - &mut self, - nonce: Vec, - ciphertext: Vec, - associated_data: Vec, - ) -> Result<(), Error> { - let State::ReadyForExchange { secret, .. } = &self.state else { - return Err(Error::State); - }; - - let Ok(seal_key_buffer) = Self::decrypt_key(secret, &nonce, &ciphertext, &associated_data) - else { - return Err(Error::InvalidKey); - }; - - match self - .actors - .vault - .ask(TryUnseal { - seal_key_raw: seal_key_buffer, - }) - .await - { - Ok(()) => { - info!("Successfully unsealed key with client-provided key"); - Ok(()) - } - Err(SendError::HandlerError(vault::Error::InvalidKey)) => Err(Error::InvalidKey), - Err(SendError::HandlerError(err)) => { - error!(?err, "Vault failed to unseal key"); - Err(Error::InvalidKey) - } - Err(err) => { - error!(?err, "Failed to send unseal request to vault"); - Err(Error::internal("Vault actor error")) - } - } - } - - #[message] - pub async fn handle_bootstrap_encrypted_key( - &mut self, - nonce: Vec, - ciphertext: Vec, - associated_data: Vec, - ) -> Result<(), Error> { - let State::ReadyForExchange { secret, .. } = &self.state else { - return Err(Error::State); - }; - - let Ok(seal_key_buffer) = Self::decrypt_key(secret, &nonce, &ciphertext, &associated_data) - else { - return Err(Error::InvalidKey); - }; - - match self - .actors - .vault - .ask(Bootstrap { - seal_key_raw: seal_key_buffer, - }) - .await - { - Ok(()) => { - info!("Successfully bootstrapped vault with client-provided key"); - Ok(()) - } - Err(SendError::HandlerError(vault::Error::AlreadyBootstrapped)) => { - Err(Error::AlreadyBootstrapped) - } - Err(SendError::HandlerError(err)) => { - error!(?err, "Vault failed to bootstrap vault"); - Err(Error::InvalidKey) - } - Err(err) => { - error!(?err, "Failed to send bootstrap request to vault"); - Err(Error::internal("Vault error")) - } - } - } - - #[message] - pub async fn handle_vault_state(&mut self) -> Result { - let answer = self - .actors - .vault - .ask(GetState {}) - .await - .map_err(|_| Error::internal("failed to query vault"))?; - - Ok(answer) - } -} - -impl Message for VaultGate { - type Reply = (); - - async fn handle( - &mut self, - _: events::Bootstrapped, - ctx: &mut kameo::prelude::Context, - ) -> Self::Reply { - let result = async { - let mut conn = self - .db - .get() - .await - .map_err(|_| Error::internal("DB unavailable"))?; - integrity::sign_entity( - &mut conn, - &self.actors.vault, - &self.auth_creds, - self.auth_creds.id, - ) - .await - .map_err(|e| { - error!(?e, "Failed to sign integrity envelope on bootstrap"); - Error::internal("Integrity sign failed") - })?; - Ok(()) - } - .await; - - if let Some(tx) = self.promotion_tx.take() { - let _ = tx.send(result); - } - ctx.stop(); - } -} - -impl Message for VaultGate { - type Reply = (); - - async fn handle( - &mut self, - _: events::Unsealed, - ctx: &mut kameo::prelude::Context, - ) -> Self::Reply { - if let Some(tx) = self.promotion_tx.take() { - let _ = tx.send(Ok(())); - } - ctx.stop(); - } -} +use super::Credentials; +use crate::{ + actors::{ + GlobalActors, + vault::{self, Bootstrap, GetState, TryUnseal, VaultState, events}, + }, + crypto::integrity::{self}, + db::DatabasePool, +}; +use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; +use state::State; + +use chacha20poly1305::{AeadInPlace, KeyInit as _, XChaCha20Poly1305, XNonce}; +use kameo::{Actor, error::SendError, messages, prelude::Message}; +use kameo_actors::message_bus::Register; +use tokio::sync::oneshot; +use tracing::{error, info}; +use x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret}; + +pub mod state; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Vault is already bootstrapped")] + AlreadyBootstrapped, + #[error("Invalid key provided")] + InvalidKey, + + #[error("State transition failed")] + State, + + #[error("Internal error: {0}")] + Internal(String), +} +impl Error { + fn internal(message: impl Into) -> Self { + Self::Internal(message.into()) + } +} + +pub struct HandshakeResponse { + pub server_pubkey: PublicKey, +} + +pub struct VaultGate { + pub auth_creds: Credentials, + pub promotion_tx: Option>>, + pub state: State, + pub actors: GlobalActors, + pub db: DatabasePool, +} + +impl VaultGate { + pub fn new( + auth_creds: Credentials, + actors: GlobalActors, + db: DatabasePool, + promotion_tx: oneshot::Sender>, + ) -> Self { + Self { + auth_creds, + state: State::default(), + actors, + db, + promotion_tx: Some(promotion_tx), + } + } +} + +impl Actor for VaultGate { + type Args = Self; + + type Error = (); + + async fn on_start( + args: Self::Args, + actor_ref: kameo::prelude::ActorRef, + ) -> Result { + let _ = args + .actors + .events + .tell(Register( + actor_ref.clone().recipient::(), + )) + .await; + let _ = args + .actors + .events + .tell(Register(actor_ref.recipient::())) + .await; + Ok(args) + } +} + +impl VaultGate { + fn decrypt_key( + secret: &SharedSecret, + nonce: &[u8], + ciphertext: &[u8], + associated_data: &[u8], + ) -> Result>, ()> { + let nonce = XNonce::from_slice(nonce); + + let cipher = XChaCha20Poly1305::new(secret.as_bytes().into()); + + let mut key_buffer = SafeCell::new(ciphertext.to_vec()); + + let decryption_result = key_buffer.write_inline(|write_handle| { + cipher.decrypt_in_place(nonce, associated_data, write_handle) + }); + + match decryption_result { + Ok(()) => Ok(key_buffer), + Err(err) => { + error!(?err, "Failed to decrypt encrypted key material"); + Err(()) + } + } + } +} + +#[messages(messages = Inbound, replies = Outbound)] +impl VaultGate { + #[message] + pub fn handle_handshake( + &mut self, + client_pubkey: PublicKey, + ) -> Result { + let ephemeral_secret = EphemeralSecret::random(); + let public_key = PublicKey::from(&ephemeral_secret); + + let secret = ephemeral_secret.diffie_hellman(&client_pubkey); + + self.state = State::ReadyForExchange { + server_key: public_key, + secret, + }; + + Ok(HandshakeResponse { + server_pubkey: public_key, + }) + } + + #[message] + pub async fn handle_unseal_encrypted_key( + &mut self, + nonce: Vec, + ciphertext: Vec, + associated_data: Vec, + ) -> Result<(), Error> { + let State::ReadyForExchange { secret, .. } = &self.state else { + return Err(Error::State); + }; + + let Ok(seal_key_buffer) = Self::decrypt_key(secret, &nonce, &ciphertext, &associated_data) + else { + return Err(Error::InvalidKey); + }; + + match self + .actors + .vault + .ask(TryUnseal { + seal_key_raw: seal_key_buffer, + }) + .await + { + Ok(()) => { + info!("Successfully unsealed key with client-provided key"); + Ok(()) + } + Err(SendError::HandlerError(vault::Error::InvalidKey)) => Err(Error::InvalidKey), + Err(SendError::HandlerError(err)) => { + error!(?err, "Vault failed to unseal key"); + Err(Error::InvalidKey) + } + Err(err) => { + error!(?err, "Failed to send unseal request to vault"); + Err(Error::internal("Vault actor error")) + } + } + } + + #[message] + pub async fn handle_bootstrap_encrypted_key( + &mut self, + nonce: Vec, + ciphertext: Vec, + associated_data: Vec, + ) -> Result<(), Error> { + let State::ReadyForExchange { secret, .. } = &self.state else { + return Err(Error::State); + }; + + let Ok(seal_key_buffer) = Self::decrypt_key(secret, &nonce, &ciphertext, &associated_data) + else { + return Err(Error::InvalidKey); + }; + + match self + .actors + .vault + .ask(Bootstrap { + seal_key_raw: seal_key_buffer, + }) + .await + { + Ok(()) => { + info!("Successfully bootstrapped vault with client-provided key"); + Ok(()) + } + Err(SendError::HandlerError(vault::Error::AlreadyBootstrapped)) => { + Err(Error::AlreadyBootstrapped) + } + Err(SendError::HandlerError(err)) => { + error!(?err, "Vault failed to bootstrap vault"); + Err(Error::InvalidKey) + } + Err(err) => { + error!(?err, "Failed to send bootstrap request to vault"); + Err(Error::internal("Vault error")) + } + } + } + + #[message] + pub async fn handle_vault_state(&mut self) -> Result { + let answer = self + .actors + .vault + .ask(GetState {}) + .await + .map_err(|_| Error::internal("failed to query vault"))?; + + Ok(answer) + } +} + +impl Message for VaultGate { + type Reply = (); + + async fn handle( + &mut self, + _: events::Bootstrapped, + ctx: &mut kameo::prelude::Context, + ) -> Self::Reply { + let result = async { + let mut conn = self + .db + .get() + .await + .map_err(|_| Error::internal("DB unavailable"))?; + integrity::sign_entity( + &mut conn, + &self.actors.vault, + &self.auth_creds, + self.auth_creds.id, + ) + .await + .map_err(|e| { + error!(?e, "Failed to sign integrity envelope on bootstrap"); + Error::internal("Integrity sign failed") + })?; + Ok(()) + } + .await; + + if let Some(tx) = self.promotion_tx.take() { + let _ = tx.send(result); + } + ctx.stop(); + } +} + +impl Message for VaultGate { + type Reply = (); + + async fn handle( + &mut self, + _: events::Unsealed, + ctx: &mut kameo::prelude::Context, + ) -> Self::Reply { + if let Some(tx) = self.promotion_tx.take() { + let _ = tx.send(Ok(())); + } + ctx.stop(); + } +} diff --git a/server/crates/arbiter-server/src/peers/operator/vault_gate/state.rs b/server/crates/arbiter-server/src/peers/operator/vault_gate/state.rs index 2f4baff..e4008a2 100644 --- a/server/crates/arbiter-server/src/peers/operator/vault_gate/state.rs +++ b/server/crates/arbiter-server/src/peers/operator/vault_gate/state.rs @@ -1,11 +1,11 @@ -use x25519_dalek::{PublicKey, SharedSecret}; - -#[derive(Default)] -pub enum State { - #[default] - Idle, - ReadyForExchange { - server_key: PublicKey, - secret: SharedSecret, - }, -} +use x25519_dalek::{PublicKey, SharedSecret}; + +#[derive(Default)] +pub enum State { + #[default] + Idle, + ReadyForExchange { + server_key: PublicKey, + secret: SharedSecret, + }, +} diff --git a/server/crates/arbiter-server/src/utils.rs b/server/crates/arbiter-server/src/utils.rs index d072aa7..82e6bcb 100644 --- a/server/crates/arbiter-server/src/utils.rs +++ b/server/crates/arbiter-server/src/utils.rs @@ -1,16 +1,16 @@ -struct DeferClosure { - f: Option, -} - -impl Drop for DeferClosure { - fn drop(&mut self) { - if let Some(f) = self.f.take() { - f(); - } - } -} - -// Run some code when a scope is exited, similar to Go's defer statement -pub fn defer(f: F) -> impl Drop + Sized { - DeferClosure { f: Some(f) } -} +struct DeferClosure { + f: Option, +} + +impl Drop for DeferClosure { + fn drop(&mut self) { + if let Some(f) = self.f.take() { + f(); + } + } +} + +// Run some code when a scope is exited, similar to Go's defer statement +pub fn defer(f: F) -> impl Drop + Sized { + DeferClosure { f: Some(f) } +} diff --git a/server/crates/arbiter-server/tests/client.rs b/server/crates/arbiter-server/tests/client.rs index de40258..b1b7500 100644 --- a/server/crates/arbiter-server/tests/client.rs +++ b/server/crates/arbiter-server/tests/client.rs @@ -1,4 +1,4 @@ -mod common; - -#[path = "client/auth.rs"] -mod auth; +mod common; + +#[path = "client/auth.rs"] +mod auth; diff --git a/server/crates/arbiter-server/tests/client/auth.rs b/server/crates/arbiter-server/tests/client/auth.rs index 90763a8..e449d84 100644 --- a/server/crates/arbiter-server/tests/client/auth.rs +++ b/server/crates/arbiter-server/tests/client/auth.rs @@ -1,408 +1,408 @@ -use super::common::ChannelTransport; -use arbiter_crypto::{ - authn::{self, AuthChallenge, CLIENT_CONTEXT}, - safecell::{SafeCell, SafeCellHandle as _}, -}; -use arbiter_proto::{ - ClientMetadata, - transport::{Receiver, Sender}, -}; -use arbiter_server::{ - actors::{GlobalActors, vault::Bootstrap}, - crypto::integrity, - db::{self, schema}, - peers::client::{ClientConnection, ClientCredentials, auth, connect_client}, -}; - -use diesel::{ExpressionMethods as _, NullableExpressionMethods as _, QueryDsl as _, insert_into}; -use diesel_async::RunQueryDsl; -use ml_dsa::{KeyGen, MlDsa87, SigningKey, VerifyingKey, signature::Keypair}; - -fn metadata(name: &str, description: Option<&str>, version: Option<&str>) -> ClientMetadata { - ClientMetadata { - name: name.to_owned(), - description: description.map(str::to_owned), - version: version.map(str::to_owned), - } -} - -fn verifying_key(key: &SigningKey) -> VerifyingKey { - as Keypair>::verifying_key(key) -} - -async fn insert_registered_client( - db: &db::DatabasePool, - actors: &GlobalActors, - pubkey: VerifyingKey, - metadata: &ClientMetadata, -) { - use arbiter_server::db::schema::{client_metadata, program_client}; - - let mut conn = db.get().await.unwrap(); - let metadata_id: i32 = insert_into(client_metadata::table) - .values(( - client_metadata::name.eq(&metadata.name), - client_metadata::description.eq(&metadata.description), - client_metadata::version.eq(&metadata.version), - )) - .returning(client_metadata::id) - .get_result(&mut conn) - .await - .unwrap(); - let client_id: i32 = insert_into(program_client::table) - .values(( - program_client::public_key.eq(pubkey.encode().0.to_vec()), - program_client::metadata_id.eq(metadata_id), - )) - .returning(program_client::id) - .get_result(&mut conn) - .await - .unwrap(); - - integrity::sign_entity( - &mut conn, - &actors.vault, - &ClientCredentials { - pubkey: pubkey.into(), - }, - client_id, - ) - .await - .unwrap(); -} - -fn sign_client_challenge(key: &SigningKey, challenge: &AuthChallenge) -> authn::Signature { - let challenge = challenge.format(); - key.signing_key() - .sign_deterministic(&challenge, CLIENT_CONTEXT) - .unwrap() - .into() -} - -async fn insert_bootstrap_sentinel_operator(db: &db::DatabasePool) { - let mut conn = db.get().await.unwrap(); - let sentinel_key = verifying_key(&MlDsa87::key_gen(&mut rand::rng())) - .encode() - .0 - .to_vec(); - - insert_into(schema::operator_client::table) - .values((schema::operator_client::public_key.eq(sentinel_key),)) - .execute(&mut conn) - .await - .unwrap(); -} - -async fn spawn_test_actors(db: &db::DatabasePool) -> GlobalActors { - insert_bootstrap_sentinel_operator(db).await; - - let actors = GlobalActors::spawn(db.clone()).await.unwrap(); - actors - .vault - .ask(Bootstrap { - seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()), - }) - .await - .unwrap(); - actors -} - -#[tokio::test] -#[test_log::test] -pub async fn unregistered_pubkey_rejected() { - let db = db::create_test_pool().await; - - let (server_transport, mut test_transport) = ChannelTransport::new(); - let actors = spawn_test_actors(&db).await; - let props = ClientConnection::new(db.clone(), actors); - let task = tokio::spawn(async move { - let mut server_transport = server_transport; - connect_client(props, &mut server_transport).await; - }); - - let new_key = MlDsa87::key_gen(&mut rand::rng()); - - test_transport - .send(auth::Inbound::AuthChallengeRequest { - pubkey: verifying_key(&new_key).into(), - metadata: metadata("client", Some("desc"), Some("1.0.0")), - }) - .await - .unwrap(); - - // Auth fails, connect_client returns, transport drops - task.await.unwrap(); -} - -#[tokio::test] -#[test_log::test] -pub async fn challenge_auth() { - let db = db::create_test_pool().await; - let actors = spawn_test_actors(&db).await; - - let new_key = MlDsa87::key_gen(&mut rand::rng()); - - Box::pin(insert_registered_client( - &db, - &actors, - verifying_key(&new_key), - &metadata("client", Some("desc"), Some("1.0.0")), - )) - .await; - - let (server_transport, mut test_transport) = ChannelTransport::new(); - let props = ClientConnection::new(db.clone(), actors); - let task = tokio::spawn(async move { - let mut server_transport = server_transport; - connect_client(props, &mut server_transport).await; - }); - - // Send challenge request - test_transport - .send(auth::Inbound::AuthChallengeRequest { - pubkey: verifying_key(&new_key).into(), - metadata: metadata("client", Some("desc"), Some("1.0.0")), - }) - .await - .unwrap(); - - // Read the challenge response - let response = test_transport - .recv() - .await - .expect("should receive challenge"); - let challenge = match response { - Ok(resp) => match resp { - auth::Outbound::AuthChallenge { challenge } => challenge, - other @ auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got {other:?}"), - }, - Err(err) => panic!("Expected Ok response, got Err({err:?})"), - }; - - // Sign the challenge and send solution - let signature = sign_client_challenge(&new_key, &challenge); - - test_transport - .send(auth::Inbound::AuthChallengeSolution { signature }) - .await - .unwrap(); - - let response = test_transport - .recv() - .await - .expect("should receive auth success"); - match response { - Ok(auth::Outbound::AuthSuccess) => {} - Ok(other) => panic!("Expected AuthSuccess, got {other:?}"), - Err(err) => panic!("Expected Ok response, got Err({err:?})"), - } - - // Auth completes, session spawned - task.await.unwrap(); -} - -#[tokio::test] -#[test_log::test] -pub async fn metadata_unchanged_does_not_append_history() { - let db = db::create_test_pool().await; - let actors = spawn_test_actors(&db).await; - let new_key = MlDsa87::key_gen(&mut rand::rng()); - let requested = metadata("client", Some("desc"), Some("1.0.0")); - - Box::pin(insert_registered_client( - &db, - &actors, - verifying_key(&new_key), - &requested, - )) - .await; - - let props = ClientConnection::new(db.clone(), actors); - - let (server_transport, mut test_transport) = ChannelTransport::new(); - let task = tokio::spawn(async move { - let mut server_transport = server_transport; - connect_client(props, &mut server_transport).await; - }); - - test_transport - .send(auth::Inbound::AuthChallengeRequest { - pubkey: verifying_key(&new_key).into(), - metadata: requested, - }) - .await - .unwrap(); - - let response = test_transport.recv().await.unwrap().unwrap(); - let challenge = match response { - auth::Outbound::AuthChallenge { challenge } => challenge, - auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got AuthSuccess"), - }; - let signature = sign_client_challenge(&new_key, &challenge); - test_transport - .send(auth::Inbound::AuthChallengeSolution { signature }) - .await - .unwrap(); - let _ = test_transport.recv().await.unwrap(); - task.await.unwrap(); - - { - use arbiter_server::db::schema::{client_metadata, client_metadata_history}; - let mut conn = db.get().await.unwrap(); - let metadata_count: i64 = client_metadata::table - .count() - .get_result(&mut conn) - .await - .unwrap(); - let history_count: i64 = client_metadata_history::table - .count() - .get_result(&mut conn) - .await - .unwrap(); - assert_eq!(metadata_count, 1); - assert_eq!(history_count, 0); - } -} - -#[tokio::test] -#[test_log::test] -pub async fn metadata_change_appends_history_and_repoints_binding() { - let db = db::create_test_pool().await; - let actors = spawn_test_actors(&db).await; - let new_key = MlDsa87::key_gen(&mut rand::rng()); - - Box::pin(insert_registered_client( - &db, - &actors, - verifying_key(&new_key), - &metadata("client", Some("old"), Some("1.0.0")), - )) - .await; - - let props = ClientConnection::new(db.clone(), actors); - - let (server_transport, mut test_transport) = ChannelTransport::new(); - let task = tokio::spawn(async move { - let mut server_transport = server_transport; - connect_client(props, &mut server_transport).await; - }); - - test_transport - .send(auth::Inbound::AuthChallengeRequest { - pubkey: verifying_key(&new_key).into(), - metadata: metadata("client", Some("new"), Some("2.0.0")), - }) - .await - .unwrap(); - - let response = test_transport.recv().await.unwrap().unwrap(); - let challenge = match response { - auth::Outbound::AuthChallenge { challenge } => challenge, - auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got AuthSuccess"), - }; - let signature = sign_client_challenge(&new_key, &challenge); - test_transport - .send(auth::Inbound::AuthChallengeSolution { signature }) - .await - .unwrap(); - drop(test_transport.recv().await.unwrap()); - task.await.unwrap(); - - { - use arbiter_server::db::schema::{ - client_metadata, client_metadata_history, program_client, - }; - let mut conn = db.get().await.unwrap(); - let metadata_count: i64 = client_metadata::table - .count() - .get_result(&mut conn) - .await - .unwrap(); - let history_count: i64 = client_metadata_history::table - .count() - .get_result(&mut conn) - .await - .unwrap(); - let metadata_id = program_client::table - .select(program_client::metadata_id) - .first::(&mut conn) - .await - .unwrap(); - let current = client_metadata::table - .find(metadata_id) - .select(( - client_metadata::name, - client_metadata::description.nullable(), - client_metadata::version.nullable(), - )) - .first::<(String, Option, Option)>(&mut conn) - .await - .unwrap(); - assert_eq!(metadata_count, 2); - assert_eq!(history_count, 1); - assert_eq!( - current, - ( - "client".to_owned(), - Some("new".to_owned()), - Some("2.0.0".to_owned()) - ) - ); - } -} - -#[tokio::test] -#[test_log::test] -pub async fn challenge_auth_rejects_integrity_tag_mismatch() { - let db = db::create_test_pool().await; - let actors = spawn_test_actors(&db).await; - - let new_key = MlDsa87::key_gen(&mut rand::rng()); - let requested = metadata("client", Some("desc"), Some("1.0.0")); - - { - use arbiter_server::db::schema::{client_metadata, program_client}; - let mut conn = db.get().await.unwrap(); - let metadata_id: i32 = insert_into(client_metadata::table) - .values(( - client_metadata::name.eq(&requested.name), - client_metadata::description.eq(&requested.description), - client_metadata::version.eq(&requested.version), - )) - .returning(client_metadata::id) - .get_result(&mut conn) - .await - .unwrap(); - insert_into(program_client::table) - .values(( - program_client::public_key.eq(verifying_key(&new_key).encode().0.to_vec()), - program_client::metadata_id.eq(metadata_id), - )) - .execute(&mut conn) - .await - .unwrap(); - } - - let (server_transport, mut test_transport) = ChannelTransport::new(); - let props = ClientConnection::new(db.clone(), actors); - let task = tokio::spawn(async move { - let mut server_transport = server_transport; - connect_client(props, &mut server_transport).await; - }); - - test_transport - .send(auth::Inbound::AuthChallengeRequest { - pubkey: verifying_key(&new_key).into(), - metadata: requested, - }) - .await - .unwrap(); - - let response = test_transport - .recv() - .await - .expect("should receive auth rejection"); - assert!(matches!(response, Err(auth::Error::IntegrityCheckFailed))); - - task.await.unwrap(); -} +use super::common::ChannelTransport; +use arbiter_crypto::{ + authn::{self, AuthChallenge, CLIENT_CONTEXT}, + safecell::{SafeCell, SafeCellHandle as _}, +}; +use arbiter_proto::{ + ClientMetadata, + transport::{Receiver, Sender}, +}; +use arbiter_server::{ + actors::{GlobalActors, vault::Bootstrap}, + crypto::integrity, + db::{self, schema}, + peers::client::{ClientConnection, ClientCredentials, auth, connect_client}, +}; + +use diesel::{ExpressionMethods as _, NullableExpressionMethods as _, QueryDsl as _, insert_into}; +use diesel_async::RunQueryDsl; +use ml_dsa::{KeyGen, MlDsa87, SigningKey, VerifyingKey, signature::Keypair}; + +fn metadata(name: &str, description: Option<&str>, version: Option<&str>) -> ClientMetadata { + ClientMetadata { + name: name.to_owned(), + description: description.map(str::to_owned), + version: version.map(str::to_owned), + } +} + +fn verifying_key(key: &SigningKey) -> VerifyingKey { + as Keypair>::verifying_key(key) +} + +async fn insert_registered_client( + db: &db::DatabasePool, + actors: &GlobalActors, + pubkey: VerifyingKey, + metadata: &ClientMetadata, +) { + use arbiter_server::db::schema::{client_metadata, program_client}; + + let mut conn = db.get().await.unwrap(); + let metadata_id: i32 = insert_into(client_metadata::table) + .values(( + client_metadata::name.eq(&metadata.name), + client_metadata::description.eq(&metadata.description), + client_metadata::version.eq(&metadata.version), + )) + .returning(client_metadata::id) + .get_result(&mut conn) + .await + .unwrap(); + let client_id: i32 = insert_into(program_client::table) + .values(( + program_client::public_key.eq(pubkey.encode().0.to_vec()), + program_client::metadata_id.eq(metadata_id), + )) + .returning(program_client::id) + .get_result(&mut conn) + .await + .unwrap(); + + integrity::sign_entity( + &mut conn, + &actors.vault, + &ClientCredentials { + pubkey: pubkey.into(), + }, + client_id, + ) + .await + .unwrap(); +} + +fn sign_client_challenge(key: &SigningKey, challenge: &AuthChallenge) -> authn::Signature { + let challenge = challenge.format(); + key.signing_key() + .sign_deterministic(&challenge, CLIENT_CONTEXT) + .unwrap() + .into() +} + +async fn insert_bootstrap_sentinel_operator(db: &db::DatabasePool) { + let mut conn = db.get().await.unwrap(); + let sentinel_key = verifying_key(&MlDsa87::key_gen(&mut rand::rng())) + .encode() + .0 + .to_vec(); + + insert_into(schema::operator_client::table) + .values((schema::operator_client::public_key.eq(sentinel_key),)) + .execute(&mut conn) + .await + .unwrap(); +} + +async fn spawn_test_actors(db: &db::DatabasePool) -> GlobalActors { + insert_bootstrap_sentinel_operator(db).await; + + let actors = GlobalActors::spawn(db.clone()).await.unwrap(); + actors + .vault + .ask(Bootstrap { + seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()), + }) + .await + .unwrap(); + actors +} + +#[tokio::test] +#[test_log::test] +pub async fn unregistered_pubkey_rejected() { + let db = db::create_test_pool().await; + + let (server_transport, mut test_transport) = ChannelTransport::new(); + let actors = spawn_test_actors(&db).await; + let props = ClientConnection::new(db.clone(), actors); + let task = tokio::spawn(async move { + let mut server_transport = server_transport; + connect_client(props, &mut server_transport).await; + }); + + let new_key = MlDsa87::key_gen(&mut rand::rng()); + + test_transport + .send(auth::Inbound::AuthChallengeRequest { + pubkey: verifying_key(&new_key).into(), + metadata: metadata("client", Some("desc"), Some("1.0.0")), + }) + .await + .unwrap(); + + // Auth fails, connect_client returns, transport drops + task.await.unwrap(); +} + +#[tokio::test] +#[test_log::test] +pub async fn challenge_auth() { + let db = db::create_test_pool().await; + let actors = spawn_test_actors(&db).await; + + let new_key = MlDsa87::key_gen(&mut rand::rng()); + + Box::pin(insert_registered_client( + &db, + &actors, + verifying_key(&new_key), + &metadata("client", Some("desc"), Some("1.0.0")), + )) + .await; + + let (server_transport, mut test_transport) = ChannelTransport::new(); + let props = ClientConnection::new(db.clone(), actors); + let task = tokio::spawn(async move { + let mut server_transport = server_transport; + connect_client(props, &mut server_transport).await; + }); + + // Send challenge request + test_transport + .send(auth::Inbound::AuthChallengeRequest { + pubkey: verifying_key(&new_key).into(), + metadata: metadata("client", Some("desc"), Some("1.0.0")), + }) + .await + .unwrap(); + + // Read the challenge response + let response = test_transport + .recv() + .await + .expect("should receive challenge"); + let challenge = match response { + Ok(resp) => match resp { + auth::Outbound::AuthChallenge { challenge } => challenge, + other @ auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got {other:?}"), + }, + Err(err) => panic!("Expected Ok response, got Err({err:?})"), + }; + + // Sign the challenge and send solution + let signature = sign_client_challenge(&new_key, &challenge); + + test_transport + .send(auth::Inbound::AuthChallengeSolution { signature }) + .await + .unwrap(); + + let response = test_transport + .recv() + .await + .expect("should receive auth success"); + match response { + Ok(auth::Outbound::AuthSuccess) => {} + Ok(other) => panic!("Expected AuthSuccess, got {other:?}"), + Err(err) => panic!("Expected Ok response, got Err({err:?})"), + } + + // Auth completes, session spawned + task.await.unwrap(); +} + +#[tokio::test] +#[test_log::test] +pub async fn metadata_unchanged_does_not_append_history() { + let db = db::create_test_pool().await; + let actors = spawn_test_actors(&db).await; + let new_key = MlDsa87::key_gen(&mut rand::rng()); + let requested = metadata("client", Some("desc"), Some("1.0.0")); + + Box::pin(insert_registered_client( + &db, + &actors, + verifying_key(&new_key), + &requested, + )) + .await; + + let props = ClientConnection::new(db.clone(), actors); + + let (server_transport, mut test_transport) = ChannelTransport::new(); + let task = tokio::spawn(async move { + let mut server_transport = server_transport; + connect_client(props, &mut server_transport).await; + }); + + test_transport + .send(auth::Inbound::AuthChallengeRequest { + pubkey: verifying_key(&new_key).into(), + metadata: requested, + }) + .await + .unwrap(); + + let response = test_transport.recv().await.unwrap().unwrap(); + let challenge = match response { + auth::Outbound::AuthChallenge { challenge } => challenge, + auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got AuthSuccess"), + }; + let signature = sign_client_challenge(&new_key, &challenge); + test_transport + .send(auth::Inbound::AuthChallengeSolution { signature }) + .await + .unwrap(); + let _ = test_transport.recv().await.unwrap(); + task.await.unwrap(); + + { + use arbiter_server::db::schema::{client_metadata, client_metadata_history}; + let mut conn = db.get().await.unwrap(); + let metadata_count: i64 = client_metadata::table + .count() + .get_result(&mut conn) + .await + .unwrap(); + let history_count: i64 = client_metadata_history::table + .count() + .get_result(&mut conn) + .await + .unwrap(); + assert_eq!(metadata_count, 1); + assert_eq!(history_count, 0); + } +} + +#[tokio::test] +#[test_log::test] +pub async fn metadata_change_appends_history_and_repoints_binding() { + let db = db::create_test_pool().await; + let actors = spawn_test_actors(&db).await; + let new_key = MlDsa87::key_gen(&mut rand::rng()); + + Box::pin(insert_registered_client( + &db, + &actors, + verifying_key(&new_key), + &metadata("client", Some("old"), Some("1.0.0")), + )) + .await; + + let props = ClientConnection::new(db.clone(), actors); + + let (server_transport, mut test_transport) = ChannelTransport::new(); + let task = tokio::spawn(async move { + let mut server_transport = server_transport; + connect_client(props, &mut server_transport).await; + }); + + test_transport + .send(auth::Inbound::AuthChallengeRequest { + pubkey: verifying_key(&new_key).into(), + metadata: metadata("client", Some("new"), Some("2.0.0")), + }) + .await + .unwrap(); + + let response = test_transport.recv().await.unwrap().unwrap(); + let challenge = match response { + auth::Outbound::AuthChallenge { challenge } => challenge, + auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got AuthSuccess"), + }; + let signature = sign_client_challenge(&new_key, &challenge); + test_transport + .send(auth::Inbound::AuthChallengeSolution { signature }) + .await + .unwrap(); + drop(test_transport.recv().await.unwrap()); + task.await.unwrap(); + + { + use arbiter_server::db::schema::{ + client_metadata, client_metadata_history, program_client, + }; + let mut conn = db.get().await.unwrap(); + let metadata_count: i64 = client_metadata::table + .count() + .get_result(&mut conn) + .await + .unwrap(); + let history_count: i64 = client_metadata_history::table + .count() + .get_result(&mut conn) + .await + .unwrap(); + let metadata_id = program_client::table + .select(program_client::metadata_id) + .first::(&mut conn) + .await + .unwrap(); + let current = client_metadata::table + .find(metadata_id) + .select(( + client_metadata::name, + client_metadata::description.nullable(), + client_metadata::version.nullable(), + )) + .first::<(String, Option, Option)>(&mut conn) + .await + .unwrap(); + assert_eq!(metadata_count, 2); + assert_eq!(history_count, 1); + assert_eq!( + current, + ( + "client".to_owned(), + Some("new".to_owned()), + Some("2.0.0".to_owned()) + ) + ); + } +} + +#[tokio::test] +#[test_log::test] +pub async fn challenge_auth_rejects_integrity_tag_mismatch() { + let db = db::create_test_pool().await; + let actors = spawn_test_actors(&db).await; + + let new_key = MlDsa87::key_gen(&mut rand::rng()); + let requested = metadata("client", Some("desc"), Some("1.0.0")); + + { + use arbiter_server::db::schema::{client_metadata, program_client}; + let mut conn = db.get().await.unwrap(); + let metadata_id: i32 = insert_into(client_metadata::table) + .values(( + client_metadata::name.eq(&requested.name), + client_metadata::description.eq(&requested.description), + client_metadata::version.eq(&requested.version), + )) + .returning(client_metadata::id) + .get_result(&mut conn) + .await + .unwrap(); + insert_into(program_client::table) + .values(( + program_client::public_key.eq(verifying_key(&new_key).encode().0.to_vec()), + program_client::metadata_id.eq(metadata_id), + )) + .execute(&mut conn) + .await + .unwrap(); + } + + let (server_transport, mut test_transport) = ChannelTransport::new(); + let props = ClientConnection::new(db.clone(), actors); + let task = tokio::spawn(async move { + let mut server_transport = server_transport; + connect_client(props, &mut server_transport).await; + }); + + test_transport + .send(auth::Inbound::AuthChallengeRequest { + pubkey: verifying_key(&new_key).into(), + metadata: requested, + }) + .await + .unwrap(); + + let response = test_transport + .recv() + .await + .expect("should receive auth rejection"); + assert!(matches!(response, Err(auth::Error::IntegrityCheckFailed))); + + task.await.unwrap(); +} diff --git a/server/crates/arbiter-server/tests/common/mod.rs b/server/crates/arbiter-server/tests/common/mod.rs index 83a2f81..a717d93 100644 --- a/server/crates/arbiter-server/tests/common/mod.rs +++ b/server/crates/arbiter-server/tests/common/mod.rs @@ -1,90 +1,90 @@ -#![allow( - dead_code, - reason = "Common test utilities that may not be used in every test" -)] -use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; -use arbiter_proto::transport::{Bi, Error, Receiver, Sender}; -use arbiter_server::{ - actors::{GlobalActors, vault::Vault}, - db::{self, schema}, -}; - -use async_trait::async_trait; -use diesel::QueryDsl; -use diesel_async::RunQueryDsl; -use tokio::sync::mpsc; - -pub(crate) async fn bootstrapped_vault(db: &db::DatabasePool) -> Vault { - let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) - .await - .unwrap(); - actor - .bootstrap(SafeCell::new(b"test-seal-key".to_vec())) - .await - .unwrap(); - actor -} - -pub(crate) async fn root_key_history_id(db: &db::DatabasePool) -> i32 { - let mut conn = db.get().await.unwrap(); - let id = schema::arbiter_settings::table - .select(schema::arbiter_settings::root_key_id) - .first::>(&mut conn) - .await - .unwrap(); - id.expect("root_key_id should be set after bootstrap") -} - -pub(crate) struct ChannelTransport { - receiver: mpsc::Receiver, - sender: mpsc::Sender, -} - -impl ChannelTransport { - pub(crate) fn new() -> (Self, ChannelTransport) { - let (tx1, rx1) = mpsc::channel(10); - let (tx2, rx2) = mpsc::channel(10); - ( - Self { - receiver: rx1, - sender: tx2, - }, - ChannelTransport { - receiver: rx2, - sender: tx1, - }, - ) - } -} - -#[async_trait] -impl Sender for ChannelTransport -where - T: Send + Sync + 'static, - Y: Send + Sync + 'static, -{ - async fn send(&mut self, item: Y) -> Result<(), Error> { - self.sender - .send(item) - .await - .map_err(|_| Error::ChannelClosed) - } -} - -#[async_trait] -impl Receiver for ChannelTransport -where - T: Send + Sync + 'static, - Y: Send + Sync + 'static, -{ - async fn recv(&mut self) -> Option { - self.receiver.recv().await - } -} - -impl Bi for ChannelTransport -where - T: Send + Sync + 'static, - Y: Send + Sync + 'static, -{ -} +#![allow( + dead_code, + reason = "Common test utilities that may not be used in every test" +)] +use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; +use arbiter_proto::transport::{Bi, Error, Receiver, Sender}; +use arbiter_server::{ + actors::{GlobalActors, vault::Vault}, + db::{self, schema}, +}; + +use async_trait::async_trait; +use diesel::QueryDsl; +use diesel_async::RunQueryDsl; +use tokio::sync::mpsc; + +pub(crate) async fn bootstrapped_vault(db: &db::DatabasePool) -> Vault { + let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) + .await + .unwrap(); + actor + .bootstrap(SafeCell::new(b"test-seal-key".to_vec())) + .await + .unwrap(); + actor +} + +pub(crate) async fn root_key_history_id(db: &db::DatabasePool) -> i32 { + let mut conn = db.get().await.unwrap(); + let id = schema::arbiter_settings::table + .select(schema::arbiter_settings::root_key_id) + .first::>(&mut conn) + .await + .unwrap(); + id.expect("root_key_id should be set after bootstrap") +} + +pub(crate) struct ChannelTransport { + receiver: mpsc::Receiver, + sender: mpsc::Sender, +} + +impl ChannelTransport { + pub(crate) fn new() -> (Self, ChannelTransport) { + let (tx1, rx1) = mpsc::channel(10); + let (tx2, rx2) = mpsc::channel(10); + ( + Self { + receiver: rx1, + sender: tx2, + }, + ChannelTransport { + receiver: rx2, + sender: tx1, + }, + ) + } +} + +#[async_trait] +impl Sender for ChannelTransport +where + T: Send + Sync + 'static, + Y: Send + Sync + 'static, +{ + async fn send(&mut self, item: Y) -> Result<(), Error> { + self.sender + .send(item) + .await + .map_err(|_| Error::ChannelClosed) + } +} + +#[async_trait] +impl Receiver for ChannelTransport +where + T: Send + Sync + 'static, + Y: Send + Sync + 'static, +{ + async fn recv(&mut self) -> Option { + self.receiver.recv().await + } +} + +impl Bi for ChannelTransport +where + T: Send + Sync + 'static, + Y: Send + Sync + 'static, +{ +} diff --git a/server/crates/arbiter-server/tests/operator.rs b/server/crates/arbiter-server/tests/operator.rs index d6ebe48..7ab4564 100644 --- a/server/crates/arbiter-server/tests/operator.rs +++ b/server/crates/arbiter-server/tests/operator.rs @@ -1,6 +1,6 @@ -mod common; - -#[path = "operator/auth.rs"] -mod auth; -#[path = "operator/unseal.rs"] -mod unseal; +mod common; + +#[path = "operator/auth.rs"] +mod auth; +#[path = "operator/unseal.rs"] +mod unseal; diff --git a/server/crates/arbiter-server/tests/operator/auth.rs b/server/crates/arbiter-server/tests/operator/auth.rs index cc1f8f3..8171a84 100644 --- a/server/crates/arbiter-server/tests/operator/auth.rs +++ b/server/crates/arbiter-server/tests/operator/auth.rs @@ -1,508 +1,508 @@ -use super::common::ChannelTransport; -use arbiter_crypto::{ - authn::{self, AuthChallenge, OPERATOR_CONTEXT}, - safecell::{SafeCell, SafeCellHandle as _}, -}; -use arbiter_proto::transport::{Error as TransportError, Receiver, Sender}; -use arbiter_server::{ - actors::{GlobalActors, bootstrap::GetToken, vault::Bootstrap}, - crypto::integrity, - db::{self, schema}, - peers::operator::{self, Credentials, OperatorConnection, auth, vault_gate}, -}; - -use async_trait::async_trait; -use diesel::{ExpressionMethods as _, QueryDsl, insert_into}; -use diesel_async::RunQueryDsl; -use ml_dsa::{KeyGen, MlDsa87, SigningKey, VerifyingKey, signature::Keypair}; -use tokio::sync::mpsc; - -fn verifying_key(key: &SigningKey) -> VerifyingKey { - as Keypair>::verifying_key(key) -} - -fn sign_operator_challenge( - key: &SigningKey, - challenge: &AuthChallenge, -) -> authn::Signature { - let challenge = challenge.format(); - key.signing_key() - .sign_deterministic(&challenge, OPERATOR_CONTEXT) - .unwrap() - .into() -} - -fn tamper_challenge(challenge: &AuthChallenge) -> AuthChallenge { - let mut challenge = challenge.clone(); - challenge.nonce[0] ^= 1; - challenge -} - -struct NullOobSender; - -#[async_trait] -impl Sender for NullOobSender { - async fn send(&mut self, _item: operator::OutOfBand) -> Result<(), TransportError> { - Ok(()) - } -} - -struct StartServerTransport { - auth_rx: mpsc::Receiver, - auth_tx: mpsc::Sender>, - vault_rx: mpsc::Receiver, - vault_tx: mpsc::Sender>, -} - -struct StartTestTransport { - auth_rx: mpsc::Receiver>, - auth_tx: mpsc::Sender, -} - -fn start_transport_pair() -> (StartServerTransport, StartTestTransport) { - let (auth_in_tx, auth_in_rx) = mpsc::channel(10); - let (auth_out_tx, auth_out_rx) = mpsc::channel(10); - let (_vault_in_tx, vault_in_rx) = mpsc::channel(10); - let (vault_out_tx, _vault_out_rx) = mpsc::channel(10); - - ( - StartServerTransport { - auth_rx: auth_in_rx, - auth_tx: auth_out_tx, - vault_rx: vault_in_rx, - vault_tx: vault_out_tx, - }, - StartTestTransport { - auth_rx: auth_out_rx, - auth_tx: auth_in_tx, - }, - ) -} - -#[async_trait] -impl Receiver for StartServerTransport { - async fn recv(&mut self) -> Option { - self.auth_rx.recv().await - } -} - -#[async_trait] -impl Sender> for StartServerTransport { - async fn send( - &mut self, - item: Result, - ) -> Result<(), TransportError> { - self.auth_tx - .send(item) - .await - .map_err(|_| TransportError::ChannelClosed) - } -} - -impl arbiter_proto::transport::Bi> - for StartServerTransport -{ -} - -#[async_trait] -impl Receiver for StartServerTransport { - async fn recv(&mut self) -> Option { - self.vault_rx.recv().await - } -} - -#[async_trait] -impl Sender> for StartServerTransport { - async fn send( - &mut self, - item: Result, - ) -> Result<(), TransportError> { - self.vault_tx - .send(item) - .await - .map_err(|_| TransportError::ChannelClosed) - } -} - -impl - arbiter_proto::transport::Bi< - vault_gate::Inbound, - Result, - > for StartServerTransport -{ -} - -#[async_trait] -impl Receiver> for StartTestTransport { - async fn recv(&mut self) -> Option> { - self.auth_rx.recv().await - } -} - -#[async_trait] -impl Sender for StartTestTransport { - async fn send(&mut self, item: auth::Inbound) -> Result<(), TransportError> { - self.auth_tx - .send(item) - .await - .map_err(|_| TransportError::ChannelClosed) - } -} - -#[tokio::test] -#[test_log::test] -pub async fn bootstrap_token_auth() { - let db = db::create_test_pool().await; - let actors = GlobalActors::spawn(db.clone()).await.unwrap(); - actors - .vault - .ask(Bootstrap { - seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()), - }) - .await - .unwrap(); - let token = actors.bootstrapper.ask(GetToken).await.unwrap().unwrap(); - - let (mut server_transport, mut test_transport) = ChannelTransport::new(); - let db_for_task = db.clone(); - let task = tokio::spawn(async move { - let mut props = OperatorConnection::new(db_for_task, actors); - auth::authenticate(&mut props, &mut server_transport).await - }); - - let new_key = MlDsa87::key_gen(&mut rand::rng()); - test_transport - .send(auth::Inbound::AuthChallengeRequest { - pubkey: verifying_key(&new_key).into(), - bootstrap_token: Some(token), - }) - .await - .unwrap(); - - let response = test_transport - .recv() - .await - .expect("should receive challenge"); - let challenge = match response { - Ok(auth::Outbound::AuthChallenge { challenge }) => challenge, - other => panic!("Expected AuthChallenge, got {other:?}"), - }; - - let signature = sign_operator_challenge(&new_key, &challenge); - - test_transport - .send(auth::Inbound::AuthChallengeSolution { - signature: signature.to_bytes(), - }) - .await - .unwrap(); - - let response = test_transport - .recv() - .await - .expect("should receive auth result"); - assert!(matches!(response, Ok(auth::Outbound::AuthSuccess))); - - task.await.unwrap().unwrap(); - - let mut conn = db.get().await.unwrap(); - let stored_pubkey: Vec = schema::operator_client::table - .select(schema::operator_client::public_key) - .first::>(&mut conn) - .await - .unwrap(); - assert_eq!(stored_pubkey, verifying_key(&new_key).encode().0.to_vec()); -} - -#[tokio::test] -#[test_log::test] -pub async fn bootstrap_invalid_token_auth() { - let db = db::create_test_pool().await; - let actors = GlobalActors::spawn(db.clone()).await.unwrap(); - - let (mut server_transport, mut test_transport) = ChannelTransport::new(); - let db_for_task = db.clone(); - let task = tokio::spawn(async move { - let mut props = OperatorConnection::new(db_for_task, actors); - auth::authenticate(&mut props, &mut server_transport).await - }); - - let new_key = MlDsa87::key_gen(&mut rand::rng()); - test_transport - .send(auth::Inbound::AuthChallengeRequest { - pubkey: verifying_key(&new_key).into(), - bootstrap_token: Some("invalid_token".to_owned()), - }) - .await - .unwrap(); - - let response = test_transport - .recv() - .await - .expect("should receive challenge"); - let challenge = match response { - Ok(auth::Outbound::AuthChallenge { challenge }) => challenge, - other => panic!("Expected AuthChallenge, got {other:?}"), - }; - - let signature = sign_operator_challenge(&new_key, &challenge); - test_transport - .send(auth::Inbound::AuthChallengeSolution { - signature: signature.to_bytes(), - }) - .await - .unwrap(); - - assert!(matches!( - task.await.unwrap(), - Err(auth::Error::InvalidBootstrapToken) - )); - - let mut conn = db.get().await.unwrap(); - let count: i64 = schema::operator_client::table - .count() - .get_result::(&mut conn) - .await - .unwrap(); - assert_eq!(count, 0); -} - -#[tokio::test] -#[test_log::test] -pub async fn challenge_auth() { - let db = db::create_test_pool().await; - let actors = GlobalActors::spawn(db.clone()).await.unwrap(); - actors - .vault - .ask(Bootstrap { - seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()), - }) - .await - .unwrap(); - - let new_key = MlDsa87::key_gen(&mut rand::rng()); - let pubkey_bytes = authn::PublicKey::from(verifying_key(&new_key)).to_bytes(); - - { - let mut conn = db.get().await.unwrap(); - let id: i32 = insert_into(schema::operator_client::table) - .values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),)) - .returning(schema::operator_client::id) - .get_result(&mut conn) - .await - .unwrap(); - integrity::sign_entity( - &mut conn, - &actors.vault, - &Credentials { - id, - pubkey: verifying_key(&new_key).into(), - }, - id, - ) - .await - .unwrap(); - } - - let (mut server_transport, mut test_transport) = ChannelTransport::new(); - let db_for_task = db.clone(); - let task = tokio::spawn(async move { - let mut props = OperatorConnection::new(db_for_task, actors); - auth::authenticate(&mut props, &mut server_transport).await - }); - - test_transport - .send(auth::Inbound::AuthChallengeRequest { - pubkey: verifying_key(&new_key).into(), - bootstrap_token: None, - }) - .await - .unwrap(); - - let response = test_transport - .recv() - .await - .expect("should receive challenge"); - let challenge = match response { - Ok(resp) => match resp { - auth::Outbound::AuthChallenge { challenge } => challenge, - auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got AuthSuccess"), - }, - Err(err) => panic!("Expected Ok response, got Err({err:?})"), - }; - - let signature = sign_operator_challenge(&new_key, &challenge); - - test_transport - .send(auth::Inbound::AuthChallengeSolution { - signature: signature.to_bytes(), - }) - .await - .unwrap(); - - let response = test_transport - .recv() - .await - .expect("should receive auth result"); - match response { - Ok(auth::Outbound::AuthSuccess) => {} - other => panic!("Expected AuthSuccess, got {other:?}"), - } - - task.await.unwrap().unwrap(); -} - -#[tokio::test] -#[test_log::test] -pub async fn challenge_auth_rejects_integrity_tag_mismatch_when_unsealed() { - let db = db::create_test_pool().await; - let actors = GlobalActors::spawn(db.clone()).await.unwrap(); - - actors - .vault - .ask(Bootstrap { - seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()), - }) - .await - .unwrap(); - - let new_key = MlDsa87::key_gen(&mut rand::rng()); - let pubkey_bytes = authn::PublicKey::from(verifying_key(&new_key)).to_bytes(); - - { - let mut conn = db.get().await.unwrap(); - insert_into(schema::operator_client::table) - .values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),)) - .execute(&mut conn) - .await - .unwrap(); - } - - let (server_transport, mut test_transport) = start_transport_pair(); - let db_for_task = db.clone(); - let task = tokio::spawn(async move { - let mut props = OperatorConnection::new(db_for_task, actors); - operator::start(&mut props, server_transport, Box::new(NullOobSender)).await - }); - - test_transport - .send(auth::Inbound::AuthChallengeRequest { - pubkey: verifying_key(&new_key).into(), - bootstrap_token: None, - }) - .await - .unwrap(); - - let response = test_transport - .recv() - .await - .expect("should receive challenge"); - let challenge = match response { - Ok(resp) => match resp { - auth::Outbound::AuthChallenge { challenge } => challenge, - other @ auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got {other:?}"), - }, - Err(err) => panic!("Expected Ok response, got Err({err:?})"), - }; - - let signature = sign_operator_challenge(&new_key, &challenge); - - test_transport - .send(auth::Inbound::AuthChallengeSolution { - signature: signature.to_bytes(), - }) - .await - .unwrap(); - - let response = test_transport - .recv() - .await - .expect("should receive auth result"); - assert!(matches!(response, Ok(auth::Outbound::AuthSuccess))); - - assert!(matches!( - task.await.unwrap(), - Err(operator::Error::Internal(_)) - )); -} - -#[tokio::test] -#[test_log::test] -pub async fn challenge_auth_rejects_invalid_signature() { - let db = db::create_test_pool().await; - let actors = GlobalActors::spawn(db.clone()).await.unwrap(); - actors - .vault - .ask(Bootstrap { - seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()), - }) - .await - .unwrap(); - - let new_key = MlDsa87::key_gen(&mut rand::rng()); - let pubkey_bytes = authn::PublicKey::from(verifying_key(&new_key)).to_bytes(); - - { - let mut conn = db.get().await.unwrap(); - let id: i32 = insert_into(schema::operator_client::table) - .values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),)) - .returning(schema::operator_client::id) - .get_result(&mut conn) - .await - .unwrap(); - integrity::sign_entity( - &mut conn, - &actors.vault, - &Credentials { - id, - pubkey: verifying_key(&new_key).into(), - }, - id, - ) - .await - .unwrap(); - } - - let (mut server_transport, mut test_transport) = ChannelTransport::new(); - let db_for_task = db.clone(); - let task = tokio::spawn(async move { - let mut props = OperatorConnection::new(db_for_task, actors); - auth::authenticate(&mut props, &mut server_transport).await - }); - - test_transport - .send(auth::Inbound::AuthChallengeRequest { - pubkey: verifying_key(&new_key).into(), - bootstrap_token: None, - }) - .await - .unwrap(); - - let response = test_transport - .recv() - .await - .expect("should receive challenge"); - let challenge = match response { - Ok(resp) => match resp { - auth::Outbound::AuthChallenge { challenge } => challenge, - auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got AuthSuccess"), - }, - Err(err) => panic!("Expected Ok response, got Err({err:?})"), - }; - - let signature = sign_operator_challenge(&new_key, &tamper_challenge(&challenge)); - - test_transport - .send(auth::Inbound::AuthChallengeSolution { - signature: signature.to_bytes(), - }) - .await - .unwrap(); - - let expected_err = task.await.unwrap(); - println!("Received expected error: {expected_err:#?}"); - assert!(matches!( - expected_err, - Err(auth::Error::InvalidChallengeSolution) - )); -} +use super::common::ChannelTransport; +use arbiter_crypto::{ + authn::{self, AuthChallenge, OPERATOR_CONTEXT}, + safecell::{SafeCell, SafeCellHandle as _}, +}; +use arbiter_proto::transport::{Error as TransportError, Receiver, Sender}; +use arbiter_server::{ + actors::{GlobalActors, bootstrap::GetToken, vault::Bootstrap}, + crypto::integrity, + db::{self, schema}, + peers::operator::{self, Credentials, OperatorConnection, auth, vault_gate}, +}; + +use async_trait::async_trait; +use diesel::{ExpressionMethods as _, QueryDsl, insert_into}; +use diesel_async::RunQueryDsl; +use ml_dsa::{KeyGen, MlDsa87, SigningKey, VerifyingKey, signature::Keypair}; +use tokio::sync::mpsc; + +fn verifying_key(key: &SigningKey) -> VerifyingKey { + as Keypair>::verifying_key(key) +} + +fn sign_operator_challenge( + key: &SigningKey, + challenge: &AuthChallenge, +) -> authn::Signature { + let challenge = challenge.format(); + key.signing_key() + .sign_deterministic(&challenge, OPERATOR_CONTEXT) + .unwrap() + .into() +} + +fn tamper_challenge(challenge: &AuthChallenge) -> AuthChallenge { + let mut challenge = challenge.clone(); + challenge.nonce[0] ^= 1; + challenge +} + +struct NullOobSender; + +#[async_trait] +impl Sender for NullOobSender { + async fn send(&mut self, _item: operator::OutOfBand) -> Result<(), TransportError> { + Ok(()) + } +} + +struct StartServerTransport { + auth_rx: mpsc::Receiver, + auth_tx: mpsc::Sender>, + vault_rx: mpsc::Receiver, + vault_tx: mpsc::Sender>, +} + +struct StartTestTransport { + auth_rx: mpsc::Receiver>, + auth_tx: mpsc::Sender, +} + +fn start_transport_pair() -> (StartServerTransport, StartTestTransport) { + let (auth_in_tx, auth_in_rx) = mpsc::channel(10); + let (auth_out_tx, auth_out_rx) = mpsc::channel(10); + let (_vault_in_tx, vault_in_rx) = mpsc::channel(10); + let (vault_out_tx, _vault_out_rx) = mpsc::channel(10); + + ( + StartServerTransport { + auth_rx: auth_in_rx, + auth_tx: auth_out_tx, + vault_rx: vault_in_rx, + vault_tx: vault_out_tx, + }, + StartTestTransport { + auth_rx: auth_out_rx, + auth_tx: auth_in_tx, + }, + ) +} + +#[async_trait] +impl Receiver for StartServerTransport { + async fn recv(&mut self) -> Option { + self.auth_rx.recv().await + } +} + +#[async_trait] +impl Sender> for StartServerTransport { + async fn send( + &mut self, + item: Result, + ) -> Result<(), TransportError> { + self.auth_tx + .send(item) + .await + .map_err(|_| TransportError::ChannelClosed) + } +} + +impl arbiter_proto::transport::Bi> + for StartServerTransport +{ +} + +#[async_trait] +impl Receiver for StartServerTransport { + async fn recv(&mut self) -> Option { + self.vault_rx.recv().await + } +} + +#[async_trait] +impl Sender> for StartServerTransport { + async fn send( + &mut self, + item: Result, + ) -> Result<(), TransportError> { + self.vault_tx + .send(item) + .await + .map_err(|_| TransportError::ChannelClosed) + } +} + +impl + arbiter_proto::transport::Bi< + vault_gate::Inbound, + Result, + > for StartServerTransport +{ +} + +#[async_trait] +impl Receiver> for StartTestTransport { + async fn recv(&mut self) -> Option> { + self.auth_rx.recv().await + } +} + +#[async_trait] +impl Sender for StartTestTransport { + async fn send(&mut self, item: auth::Inbound) -> Result<(), TransportError> { + self.auth_tx + .send(item) + .await + .map_err(|_| TransportError::ChannelClosed) + } +} + +#[tokio::test] +#[test_log::test] +pub async fn bootstrap_token_auth() { + let db = db::create_test_pool().await; + let actors = GlobalActors::spawn(db.clone()).await.unwrap(); + actors + .vault + .ask(Bootstrap { + seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()), + }) + .await + .unwrap(); + let token = actors.bootstrapper.ask(GetToken).await.unwrap().unwrap(); + + let (mut server_transport, mut test_transport) = ChannelTransport::new(); + let db_for_task = db.clone(); + let task = tokio::spawn(async move { + let mut props = OperatorConnection::new(db_for_task, actors); + auth::authenticate(&mut props, &mut server_transport).await + }); + + let new_key = MlDsa87::key_gen(&mut rand::rng()); + test_transport + .send(auth::Inbound::AuthChallengeRequest { + pubkey: verifying_key(&new_key).into(), + bootstrap_token: Some(token), + }) + .await + .unwrap(); + + let response = test_transport + .recv() + .await + .expect("should receive challenge"); + let challenge = match response { + Ok(auth::Outbound::AuthChallenge { challenge }) => challenge, + other => panic!("Expected AuthChallenge, got {other:?}"), + }; + + let signature = sign_operator_challenge(&new_key, &challenge); + + test_transport + .send(auth::Inbound::AuthChallengeSolution { + signature: signature.to_bytes(), + }) + .await + .unwrap(); + + let response = test_transport + .recv() + .await + .expect("should receive auth result"); + assert!(matches!(response, Ok(auth::Outbound::AuthSuccess))); + + task.await.unwrap().unwrap(); + + let mut conn = db.get().await.unwrap(); + let stored_pubkey: Vec = schema::operator_client::table + .select(schema::operator_client::public_key) + .first::>(&mut conn) + .await + .unwrap(); + assert_eq!(stored_pubkey, verifying_key(&new_key).encode().0.to_vec()); +} + +#[tokio::test] +#[test_log::test] +pub async fn bootstrap_invalid_token_auth() { + let db = db::create_test_pool().await; + let actors = GlobalActors::spawn(db.clone()).await.unwrap(); + + let (mut server_transport, mut test_transport) = ChannelTransport::new(); + let db_for_task = db.clone(); + let task = tokio::spawn(async move { + let mut props = OperatorConnection::new(db_for_task, actors); + auth::authenticate(&mut props, &mut server_transport).await + }); + + let new_key = MlDsa87::key_gen(&mut rand::rng()); + test_transport + .send(auth::Inbound::AuthChallengeRequest { + pubkey: verifying_key(&new_key).into(), + bootstrap_token: Some("invalid_token".to_owned()), + }) + .await + .unwrap(); + + let response = test_transport + .recv() + .await + .expect("should receive challenge"); + let challenge = match response { + Ok(auth::Outbound::AuthChallenge { challenge }) => challenge, + other => panic!("Expected AuthChallenge, got {other:?}"), + }; + + let signature = sign_operator_challenge(&new_key, &challenge); + test_transport + .send(auth::Inbound::AuthChallengeSolution { + signature: signature.to_bytes(), + }) + .await + .unwrap(); + + assert!(matches!( + task.await.unwrap(), + Err(auth::Error::InvalidBootstrapToken) + )); + + let mut conn = db.get().await.unwrap(); + let count: i64 = schema::operator_client::table + .count() + .get_result::(&mut conn) + .await + .unwrap(); + assert_eq!(count, 0); +} + +#[tokio::test] +#[test_log::test] +pub async fn challenge_auth() { + let db = db::create_test_pool().await; + let actors = GlobalActors::spawn(db.clone()).await.unwrap(); + actors + .vault + .ask(Bootstrap { + seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()), + }) + .await + .unwrap(); + + let new_key = MlDsa87::key_gen(&mut rand::rng()); + let pubkey_bytes = authn::PublicKey::from(verifying_key(&new_key)).to_bytes(); + + { + let mut conn = db.get().await.unwrap(); + let id: i32 = insert_into(schema::operator_client::table) + .values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),)) + .returning(schema::operator_client::id) + .get_result(&mut conn) + .await + .unwrap(); + integrity::sign_entity( + &mut conn, + &actors.vault, + &Credentials { + id, + pubkey: verifying_key(&new_key).into(), + }, + id, + ) + .await + .unwrap(); + } + + let (mut server_transport, mut test_transport) = ChannelTransport::new(); + let db_for_task = db.clone(); + let task = tokio::spawn(async move { + let mut props = OperatorConnection::new(db_for_task, actors); + auth::authenticate(&mut props, &mut server_transport).await + }); + + test_transport + .send(auth::Inbound::AuthChallengeRequest { + pubkey: verifying_key(&new_key).into(), + bootstrap_token: None, + }) + .await + .unwrap(); + + let response = test_transport + .recv() + .await + .expect("should receive challenge"); + let challenge = match response { + Ok(resp) => match resp { + auth::Outbound::AuthChallenge { challenge } => challenge, + auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got AuthSuccess"), + }, + Err(err) => panic!("Expected Ok response, got Err({err:?})"), + }; + + let signature = sign_operator_challenge(&new_key, &challenge); + + test_transport + .send(auth::Inbound::AuthChallengeSolution { + signature: signature.to_bytes(), + }) + .await + .unwrap(); + + let response = test_transport + .recv() + .await + .expect("should receive auth result"); + match response { + Ok(auth::Outbound::AuthSuccess) => {} + other => panic!("Expected AuthSuccess, got {other:?}"), + } + + task.await.unwrap().unwrap(); +} + +#[tokio::test] +#[test_log::test] +pub async fn challenge_auth_rejects_integrity_tag_mismatch_when_unsealed() { + let db = db::create_test_pool().await; + let actors = GlobalActors::spawn(db.clone()).await.unwrap(); + + actors + .vault + .ask(Bootstrap { + seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()), + }) + .await + .unwrap(); + + let new_key = MlDsa87::key_gen(&mut rand::rng()); + let pubkey_bytes = authn::PublicKey::from(verifying_key(&new_key)).to_bytes(); + + { + let mut conn = db.get().await.unwrap(); + insert_into(schema::operator_client::table) + .values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),)) + .execute(&mut conn) + .await + .unwrap(); + } + + let (server_transport, mut test_transport) = start_transport_pair(); + let db_for_task = db.clone(); + let task = tokio::spawn(async move { + let mut props = OperatorConnection::new(db_for_task, actors); + operator::start(&mut props, server_transport, Box::new(NullOobSender)).await + }); + + test_transport + .send(auth::Inbound::AuthChallengeRequest { + pubkey: verifying_key(&new_key).into(), + bootstrap_token: None, + }) + .await + .unwrap(); + + let response = test_transport + .recv() + .await + .expect("should receive challenge"); + let challenge = match response { + Ok(resp) => match resp { + auth::Outbound::AuthChallenge { challenge } => challenge, + other @ auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got {other:?}"), + }, + Err(err) => panic!("Expected Ok response, got Err({err:?})"), + }; + + let signature = sign_operator_challenge(&new_key, &challenge); + + test_transport + .send(auth::Inbound::AuthChallengeSolution { + signature: signature.to_bytes(), + }) + .await + .unwrap(); + + let response = test_transport + .recv() + .await + .expect("should receive auth result"); + assert!(matches!(response, Ok(auth::Outbound::AuthSuccess))); + + assert!(matches!( + task.await.unwrap(), + Err(operator::Error::Internal(_)) + )); +} + +#[tokio::test] +#[test_log::test] +pub async fn challenge_auth_rejects_invalid_signature() { + let db = db::create_test_pool().await; + let actors = GlobalActors::spawn(db.clone()).await.unwrap(); + actors + .vault + .ask(Bootstrap { + seal_key_raw: SafeCell::new(b"test-seal-key".to_vec()), + }) + .await + .unwrap(); + + let new_key = MlDsa87::key_gen(&mut rand::rng()); + let pubkey_bytes = authn::PublicKey::from(verifying_key(&new_key)).to_bytes(); + + { + let mut conn = db.get().await.unwrap(); + let id: i32 = insert_into(schema::operator_client::table) + .values((schema::operator_client::public_key.eq(pubkey_bytes.clone()),)) + .returning(schema::operator_client::id) + .get_result(&mut conn) + .await + .unwrap(); + integrity::sign_entity( + &mut conn, + &actors.vault, + &Credentials { + id, + pubkey: verifying_key(&new_key).into(), + }, + id, + ) + .await + .unwrap(); + } + + let (mut server_transport, mut test_transport) = ChannelTransport::new(); + let db_for_task = db.clone(); + let task = tokio::spawn(async move { + let mut props = OperatorConnection::new(db_for_task, actors); + auth::authenticate(&mut props, &mut server_transport).await + }); + + test_transport + .send(auth::Inbound::AuthChallengeRequest { + pubkey: verifying_key(&new_key).into(), + bootstrap_token: None, + }) + .await + .unwrap(); + + let response = test_transport + .recv() + .await + .expect("should receive challenge"); + let challenge = match response { + Ok(resp) => match resp { + auth::Outbound::AuthChallenge { challenge } => challenge, + auth::Outbound::AuthSuccess => panic!("Expected AuthChallenge, got AuthSuccess"), + }, + Err(err) => panic!("Expected Ok response, got Err({err:?})"), + }; + + let signature = sign_operator_challenge(&new_key, &tamper_challenge(&challenge)); + + test_transport + .send(auth::Inbound::AuthChallengeSolution { + signature: signature.to_bytes(), + }) + .await + .unwrap(); + + let expected_err = task.await.unwrap(); + println!("Received expected error: {expected_err:#?}"); + assert!(matches!( + expected_err, + Err(auth::Error::InvalidChallengeSolution) + )); +} diff --git a/server/crates/arbiter-server/tests/operator/unseal.rs b/server/crates/arbiter-server/tests/operator/unseal.rs index 365e6ec..36bb225 100644 --- a/server/crates/arbiter-server/tests/operator/unseal.rs +++ b/server/crates/arbiter-server/tests/operator/unseal.rs @@ -1,167 +1,167 @@ -use arbiter_crypto::{ - authn, - safecell::{SafeCell, SafeCellHandle as _}, -}; -use arbiter_server::{ - actors::{ - GlobalActors, - vault::{Bootstrap, Seal}, - }, - db, - peers::operator::{ - Credentials, - vault_gate::{ - Error as VaultGateError, HandleHandshake, HandleUnsealEncryptedKey, VaultGate, - }, - }, -}; - -use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit}; -use kameo::actor::Spawn as _; -use tokio::sync::oneshot; -use x25519_dalek::{EphemeralSecret, PublicKey}; - -async fn setup_sealed_gate( - seal_key: &[u8], -) -> ( - db::DatabasePool, - kameo::actor::ActorRef, - oneshot::Receiver>, -) { - let db = db::create_test_pool().await; - let actors = GlobalActors::spawn(db.clone()).await.unwrap(); - - actors - .vault - .ask(Bootstrap { - seal_key_raw: SafeCell::new(seal_key.to_vec()), - }) - .await - .unwrap(); - actors.vault.ask(Seal).await.unwrap(); - - let (promotion_tx, promotion_rx) = oneshot::channel(); - let pubkey = authn::SigningKey::generate().public_key(); - let auth_creds = Credentials { id: 1, pubkey }; - let gate = VaultGate::spawn(VaultGate::new(auth_creds, actors, db.clone(), promotion_tx)); - - (db, gate, promotion_rx) -} - -async fn client_dh_encrypt( - gate: &kameo::actor::ActorRef, - key_to_send: &[u8], -) -> HandleUnsealEncryptedKey { - let client_secret = EphemeralSecret::random(); - let client_public = PublicKey::from(&client_secret); - - let response = gate - .ask(HandleHandshake { - client_pubkey: client_public, - }) - .await - .unwrap(); - - let server_pubkey = response.server_pubkey; - - let shared_secret = client_secret.diffie_hellman(&server_pubkey); - let cipher = XChaCha20Poly1305::new(shared_secret.as_bytes().into()); - let nonce = XNonce::from([0u8; 24]); - let associated_data = b"unseal"; - let mut ciphertext = key_to_send.to_vec(); - cipher - .encrypt_in_place(&nonce, associated_data, &mut ciphertext) - .unwrap(); - - HandleUnsealEncryptedKey { - nonce: nonce.to_vec(), - ciphertext, - associated_data: associated_data.to_vec(), - } -} - -#[tokio::test] -#[test_log::test] -pub async fn unseal_success() { - let seal_key = b"test-seal-key"; - let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await; - - let encrypted_key = client_dh_encrypt(&gate, seal_key).await; - - let response = gate.ask(encrypted_key).await; - assert!(matches!(response, Ok(()))); -} - -#[tokio::test] -#[test_log::test] -pub async fn unseal_wrong_seal_key() { - let seal_key = b"test-seal-key"; - let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await; - - let encrypted_key = client_dh_encrypt(&gate, b"wrong-key").await; - - let response = gate.ask(encrypted_key).await; - assert!(matches!( - response, - Err(kameo::error::SendError::HandlerError( - VaultGateError::InvalidKey - )) - )); -} - -#[tokio::test] -#[test_log::test] -pub async fn unseal_corrupted_ciphertext() { - let seal_key = b"test-seal-key"; - let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await; - - let client_secret = EphemeralSecret::random(); - let client_public = PublicKey::from(&client_secret); - - gate.ask(HandleHandshake { - client_pubkey: client_public, - }) - .await - .unwrap(); - - let response = gate - .ask(HandleUnsealEncryptedKey { - nonce: vec![0u8; 24], - ciphertext: vec![0u8; 32], - associated_data: vec![], - }) - .await; - - assert!(matches!( - response, - Err(kameo::error::SendError::HandlerError( - VaultGateError::InvalidKey - )) - )); -} - -#[tokio::test] -#[test_log::test] -pub async fn unseal_retry_after_invalid_key() { - let seal_key = b"real-seal-key"; - let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await; - - { - let encrypted_key = client_dh_encrypt(&gate, b"wrong-key").await; - - let response = gate.ask(encrypted_key).await; - assert!(matches!( - response, - Err(kameo::error::SendError::HandlerError( - VaultGateError::InvalidKey - )) - )); - } - - { - let encrypted_key = client_dh_encrypt(&gate, seal_key).await; - - let response = gate.ask(encrypted_key).await; - assert!(matches!(response, Ok(()))); - } -} +use arbiter_crypto::{ + authn, + safecell::{SafeCell, SafeCellHandle as _}, +}; +use arbiter_server::{ + actors::{ + GlobalActors, + vault::{Bootstrap, Seal}, + }, + db, + peers::operator::{ + Credentials, + vault_gate::{ + Error as VaultGateError, HandleHandshake, HandleUnsealEncryptedKey, VaultGate, + }, + }, +}; + +use chacha20poly1305::{AeadInPlace, XChaCha20Poly1305, XNonce, aead::KeyInit}; +use kameo::actor::Spawn as _; +use tokio::sync::oneshot; +use x25519_dalek::{EphemeralSecret, PublicKey}; + +async fn setup_sealed_gate( + seal_key: &[u8], +) -> ( + db::DatabasePool, + kameo::actor::ActorRef, + oneshot::Receiver>, +) { + let db = db::create_test_pool().await; + let actors = GlobalActors::spawn(db.clone()).await.unwrap(); + + actors + .vault + .ask(Bootstrap { + seal_key_raw: SafeCell::new(seal_key.to_vec()), + }) + .await + .unwrap(); + actors.vault.ask(Seal).await.unwrap(); + + let (promotion_tx, promotion_rx) = oneshot::channel(); + let pubkey = authn::SigningKey::generate().public_key(); + let auth_creds = Credentials { id: 1, pubkey }; + let gate = VaultGate::spawn(VaultGate::new(auth_creds, actors, db.clone(), promotion_tx)); + + (db, gate, promotion_rx) +} + +async fn client_dh_encrypt( + gate: &kameo::actor::ActorRef, + key_to_send: &[u8], +) -> HandleUnsealEncryptedKey { + let client_secret = EphemeralSecret::random(); + let client_public = PublicKey::from(&client_secret); + + let response = gate + .ask(HandleHandshake { + client_pubkey: client_public, + }) + .await + .unwrap(); + + let server_pubkey = response.server_pubkey; + + let shared_secret = client_secret.diffie_hellman(&server_pubkey); + let cipher = XChaCha20Poly1305::new(shared_secret.as_bytes().into()); + let nonce = XNonce::from([0u8; 24]); + let associated_data = b"unseal"; + let mut ciphertext = key_to_send.to_vec(); + cipher + .encrypt_in_place(&nonce, associated_data, &mut ciphertext) + .unwrap(); + + HandleUnsealEncryptedKey { + nonce: nonce.to_vec(), + ciphertext, + associated_data: associated_data.to_vec(), + } +} + +#[tokio::test] +#[test_log::test] +pub async fn unseal_success() { + let seal_key = b"test-seal-key"; + let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await; + + let encrypted_key = client_dh_encrypt(&gate, seal_key).await; + + let response = gate.ask(encrypted_key).await; + assert!(matches!(response, Ok(()))); +} + +#[tokio::test] +#[test_log::test] +pub async fn unseal_wrong_seal_key() { + let seal_key = b"test-seal-key"; + let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await; + + let encrypted_key = client_dh_encrypt(&gate, b"wrong-key").await; + + let response = gate.ask(encrypted_key).await; + assert!(matches!( + response, + Err(kameo::error::SendError::HandlerError( + VaultGateError::InvalidKey + )) + )); +} + +#[tokio::test] +#[test_log::test] +pub async fn unseal_corrupted_ciphertext() { + let seal_key = b"test-seal-key"; + let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await; + + let client_secret = EphemeralSecret::random(); + let client_public = PublicKey::from(&client_secret); + + gate.ask(HandleHandshake { + client_pubkey: client_public, + }) + .await + .unwrap(); + + let response = gate + .ask(HandleUnsealEncryptedKey { + nonce: vec![0u8; 24], + ciphertext: vec![0u8; 32], + associated_data: vec![], + }) + .await; + + assert!(matches!( + response, + Err(kameo::error::SendError::HandlerError( + VaultGateError::InvalidKey + )) + )); +} + +#[tokio::test] +#[test_log::test] +pub async fn unseal_retry_after_invalid_key() { + let seal_key = b"real-seal-key"; + let (_db, gate, _promotion_rx) = setup_sealed_gate(seal_key).await; + + { + let encrypted_key = client_dh_encrypt(&gate, b"wrong-key").await; + + let response = gate.ask(encrypted_key).await; + assert!(matches!( + response, + Err(kameo::error::SendError::HandlerError( + VaultGateError::InvalidKey + )) + )); + } + + { + let encrypted_key = client_dh_encrypt(&gate, seal_key).await; + + let response = gate.ask(encrypted_key).await; + assert!(matches!(response, Ok(()))); + } +} diff --git a/server/crates/arbiter-server/tests/vault.rs b/server/crates/arbiter-server/tests/vault.rs index c7640a8..348d579 100644 --- a/server/crates/arbiter-server/tests/vault.rs +++ b/server/crates/arbiter-server/tests/vault.rs @@ -1,8 +1,8 @@ -mod common; - -#[path = "vault/concurrency.rs"] -mod concurrency; -#[path = "vault/lifecycle.rs"] -mod lifecycle; -#[path = "vault/storage.rs"] -mod storage; +mod common; + +#[path = "vault/concurrency.rs"] +mod concurrency; +#[path = "vault/lifecycle.rs"] +mod lifecycle; +#[path = "vault/storage.rs"] +mod storage; diff --git a/server/crates/arbiter-server/tests/vault/concurrency.rs b/server/crates/arbiter-server/tests/vault/concurrency.rs index ee84f4a..dbf8874 100644 --- a/server/crates/arbiter-server/tests/vault/concurrency.rs +++ b/server/crates/arbiter-server/tests/vault/concurrency.rs @@ -1,177 +1,177 @@ -use crate::common; -use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; -use arbiter_server::{ - actors::{ - GlobalActors, - vault::{CreateNew, Error, Vault}, - }, - db::{self, models, schema}, -}; - -use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper, dsl::sql_query}; -use diesel_async::RunQueryDsl; -use kameo::actor::{ActorRef, Spawn as _}; -use std::collections::{HashMap, HashSet}; -use tokio::task::JoinSet; - -async fn write_concurrently( - actor: ActorRef, - prefix: &'static str, - count: usize, -) -> Vec<(i32, Vec)> { - let mut set = JoinSet::new(); - for i in 0..count { - let actor = actor.clone(); - set.spawn(async move { - let plaintext = format!("{prefix}-{i}").into_bytes(); - let id = actor - .ask(CreateNew { - plaintext: SafeCell::new(plaintext.clone()), - }) - .await - .unwrap(); - (id, plaintext) - }); - } - - let mut out = Vec::with_capacity(count); - while let Some(res) = set.join_next().await { - out.push(res.unwrap()); - } - out -} - -#[tokio::test] -#[test_log::test] -async fn concurrent_create_new_no_duplicate_nonces_() { - let db = db::create_test_pool().await; - let actor = Vault::spawn(common::bootstrapped_vault(&db).await); - - let writes = write_concurrently(actor, "nonce-unique", 32).await; - assert_eq!(writes.len(), 32); - - let mut conn = db.get().await.unwrap(); - let rows: Vec = schema::aead_encrypted::table - .select(models::AeadEncrypted::as_select()) - .load(&mut conn) - .await - .unwrap(); - assert_eq!(rows.len(), 32); - - let nonces: Vec<&Vec> = rows.iter().map(|r| &r.current_nonce).collect(); - let unique: HashSet<&Vec> = nonces.iter().copied().collect(); - assert_eq!(nonces.len(), unique.len(), "all nonces must be unique"); -} - -#[tokio::test] -#[test_log::test] -async fn concurrent_create_new_root_nonce_never_moves_backward() { - let db = db::create_test_pool().await; - let actor = Vault::spawn(common::bootstrapped_vault(&db).await); - - write_concurrently(actor, "root-max", 24).await; - - let mut conn = db.get().await.unwrap(); - let rows: Vec = schema::aead_encrypted::table - .select(models::AeadEncrypted::as_select()) - .load(&mut conn) - .await - .unwrap(); - let max_nonce = rows - .iter() - .map(|r| r.current_nonce.clone()) - .max() - .expect("at least one row"); - - let root_row: models::RootKeyHistory = schema::root_key_history::table - .select(models::RootKeyHistory::as_select()) - .first(&mut conn) - .await - .unwrap(); - assert_eq!(root_row.data_encryption_nonce, max_nonce); -} - -#[tokio::test] -#[test_log::test] -async fn insert_failure_does_not_create_partial_row() { - let db = db::create_test_pool().await; - let mut actor = common::bootstrapped_vault(&db).await; - let root_key_history_id = common::root_key_history_id(&db).await; - - let mut conn = db.get().await.unwrap(); - let before_count: i64 = schema::aead_encrypted::table - .count() - .get_result(&mut conn) - .await - .unwrap(); - let before_root_nonce: Vec = schema::root_key_history::table - .filter(schema::root_key_history::id.eq(root_key_history_id)) - .select(schema::root_key_history::data_encryption_nonce) - .first(&mut conn) - .await - .unwrap(); - - sql_query( - "CREATE TRIGGER fail_aead_insert BEFORE INSERT ON aead_encrypted BEGIN SELECT RAISE(ABORT, 'forced test failure'); END;", - ) - .execute(&mut conn) - .await - .unwrap(); - drop(conn); - - let err = actor - .create_new(SafeCell::new(b"should fail".to_vec())) - .await - .unwrap_err(); - assert!(matches!(err, Error::DatabaseTransaction(_))); - - let mut conn = db.get().await.unwrap(); - sql_query("DROP TRIGGER fail_aead_insert;") - .execute(&mut conn) - .await - .unwrap(); - - let after_count: i64 = schema::aead_encrypted::table - .count() - .get_result(&mut conn) - .await - .unwrap(); - assert_eq!( - before_count, after_count, - "failed insert must not create row" - ); - - let after_root_nonce: Vec = schema::root_key_history::table - .filter(schema::root_key_history::id.eq(root_key_history_id)) - .select(schema::root_key_history::data_encryption_nonce) - .first(&mut conn) - .await - .unwrap(); - assert!( - after_root_nonce > before_root_nonce, - "current behavior allows nonce gap on failed insert" - ); -} - -#[tokio::test] -#[test_log::test] -async fn decrypt_roundtrip_after_high_concurrency() { - let db = db::create_test_pool().await; - let actor = Vault::spawn(common::bootstrapped_vault(&db).await); - - let writes = write_concurrently(actor, "roundtrip", 40).await; - let expected: HashMap> = writes.into_iter().collect(); - - let mut decryptor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) - .await - .unwrap(); - decryptor - .try_unseal(SafeCell::new(b"test-seal-key".to_vec())) - .await - .unwrap(); - - for (id, plaintext) in expected { - let mut decrypted = decryptor.decrypt(id).await.unwrap(); - assert_eq!(*decrypted.read(), plaintext); - } -} +use crate::common; +use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; +use arbiter_server::{ + actors::{ + GlobalActors, + vault::{CreateNew, Error, Vault}, + }, + db::{self, models, schema}, +}; + +use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper, dsl::sql_query}; +use diesel_async::RunQueryDsl; +use kameo::actor::{ActorRef, Spawn as _}; +use std::collections::{HashMap, HashSet}; +use tokio::task::JoinSet; + +async fn write_concurrently( + actor: ActorRef, + prefix: &'static str, + count: usize, +) -> Vec<(i32, Vec)> { + let mut set = JoinSet::new(); + for i in 0..count { + let actor = actor.clone(); + set.spawn(async move { + let plaintext = format!("{prefix}-{i}").into_bytes(); + let id = actor + .ask(CreateNew { + plaintext: SafeCell::new(plaintext.clone()), + }) + .await + .unwrap(); + (id, plaintext) + }); + } + + let mut out = Vec::with_capacity(count); + while let Some(res) = set.join_next().await { + out.push(res.unwrap()); + } + out +} + +#[tokio::test] +#[test_log::test] +async fn concurrent_create_new_no_duplicate_nonces_() { + let db = db::create_test_pool().await; + let actor = Vault::spawn(common::bootstrapped_vault(&db).await); + + let writes = write_concurrently(actor, "nonce-unique", 32).await; + assert_eq!(writes.len(), 32); + + let mut conn = db.get().await.unwrap(); + let rows: Vec = schema::aead_encrypted::table + .select(models::AeadEncrypted::as_select()) + .load(&mut conn) + .await + .unwrap(); + assert_eq!(rows.len(), 32); + + let nonces: Vec<&Vec> = rows.iter().map(|r| &r.current_nonce).collect(); + let unique: HashSet<&Vec> = nonces.iter().copied().collect(); + assert_eq!(nonces.len(), unique.len(), "all nonces must be unique"); +} + +#[tokio::test] +#[test_log::test] +async fn concurrent_create_new_root_nonce_never_moves_backward() { + let db = db::create_test_pool().await; + let actor = Vault::spawn(common::bootstrapped_vault(&db).await); + + write_concurrently(actor, "root-max", 24).await; + + let mut conn = db.get().await.unwrap(); + let rows: Vec = schema::aead_encrypted::table + .select(models::AeadEncrypted::as_select()) + .load(&mut conn) + .await + .unwrap(); + let max_nonce = rows + .iter() + .map(|r| r.current_nonce.clone()) + .max() + .expect("at least one row"); + + let root_row: models::RootKeyHistory = schema::root_key_history::table + .select(models::RootKeyHistory::as_select()) + .first(&mut conn) + .await + .unwrap(); + assert_eq!(root_row.data_encryption_nonce, max_nonce); +} + +#[tokio::test] +#[test_log::test] +async fn insert_failure_does_not_create_partial_row() { + let db = db::create_test_pool().await; + let mut actor = common::bootstrapped_vault(&db).await; + let root_key_history_id = common::root_key_history_id(&db).await; + + let mut conn = db.get().await.unwrap(); + let before_count: i64 = schema::aead_encrypted::table + .count() + .get_result(&mut conn) + .await + .unwrap(); + let before_root_nonce: Vec = schema::root_key_history::table + .filter(schema::root_key_history::id.eq(root_key_history_id)) + .select(schema::root_key_history::data_encryption_nonce) + .first(&mut conn) + .await + .unwrap(); + + sql_query( + "CREATE TRIGGER fail_aead_insert BEFORE INSERT ON aead_encrypted BEGIN SELECT RAISE(ABORT, 'forced test failure'); END;", + ) + .execute(&mut conn) + .await + .unwrap(); + drop(conn); + + let err = actor + .create_new(SafeCell::new(b"should fail".to_vec())) + .await + .unwrap_err(); + assert!(matches!(err, Error::DatabaseTransaction(_))); + + let mut conn = db.get().await.unwrap(); + sql_query("DROP TRIGGER fail_aead_insert;") + .execute(&mut conn) + .await + .unwrap(); + + let after_count: i64 = schema::aead_encrypted::table + .count() + .get_result(&mut conn) + .await + .unwrap(); + assert_eq!( + before_count, after_count, + "failed insert must not create row" + ); + + let after_root_nonce: Vec = schema::root_key_history::table + .filter(schema::root_key_history::id.eq(root_key_history_id)) + .select(schema::root_key_history::data_encryption_nonce) + .first(&mut conn) + .await + .unwrap(); + assert!( + after_root_nonce > before_root_nonce, + "current behavior allows nonce gap on failed insert" + ); +} + +#[tokio::test] +#[test_log::test] +async fn decrypt_roundtrip_after_high_concurrency() { + let db = db::create_test_pool().await; + let actor = Vault::spawn(common::bootstrapped_vault(&db).await); + + let writes = write_concurrently(actor, "roundtrip", 40).await; + let expected: HashMap> = writes.into_iter().collect(); + + let mut decryptor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) + .await + .unwrap(); + decryptor + .try_unseal(SafeCell::new(b"test-seal-key".to_vec())) + .await + .unwrap(); + + for (id, plaintext) in expected { + let mut decrypted = decryptor.decrypt(id).await.unwrap(); + assert_eq!(*decrypted.read(), plaintext); + } +} diff --git a/server/crates/arbiter-server/tests/vault/lifecycle.rs b/server/crates/arbiter-server/tests/vault/lifecycle.rs index c4ee7da..f335cad 100644 --- a/server/crates/arbiter-server/tests/vault/lifecycle.rs +++ b/server/crates/arbiter-server/tests/vault/lifecycle.rs @@ -1,141 +1,141 @@ -use crate::common; -use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; -use arbiter_server::{ - actors::{ - GlobalActors, - vault::{Error, Vault}, - }, - crypto::encryption::v1::{Nonce, ROOT_KEY_TAG}, - db::{self, models, schema}, -}; - -use diesel::{QueryDsl, SelectableHelper}; -use diesel_async::RunQueryDsl; - -#[tokio::test] -#[test_log::test] -async fn bootstrap() { - let db = db::create_test_pool().await; - let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) - .await - .unwrap(); - - let seal_key = SafeCell::new(b"test-seal-key".to_vec()); - actor.bootstrap(seal_key).await.unwrap(); - - let mut conn = db.get().await.unwrap(); - let row: models::RootKeyHistory = schema::root_key_history::table - .select(models::RootKeyHistory::as_select()) - .first(&mut conn) - .await - .unwrap(); - - assert_eq!(row.schema_version, 1); - assert_eq!(row.tag, ROOT_KEY_TAG); - assert!(!row.ciphertext.is_empty()); - assert!(!row.salt.is_empty()); - assert_eq!(row.data_encryption_nonce, Nonce::default().to_vec()); -} - -#[tokio::test] -#[test_log::test] -async fn bootstrap_rejects_double() { - let db = db::create_test_pool().await; - let mut actor = common::bootstrapped_vault(&db).await; - - let seal_key2 = SafeCell::new(b"test-seal-key".to_vec()); - let err = actor.bootstrap(seal_key2).await.unwrap_err(); - assert!(matches!(err, Error::AlreadyBootstrapped)); -} - -#[tokio::test] -#[test_log::test] -async fn create_new_before_bootstrap_fails() { - let db = db::create_test_pool().await; - let mut actor = Vault::new(db, GlobalActors::spawn_message_bus()) - .await - .unwrap(); - - let err = actor - .create_new(SafeCell::new(b"data".to_vec())) - .await - .unwrap_err(); - assert!(matches!(err, Error::NotBootstrapped)); -} - -#[tokio::test] -#[test_log::test] -async fn decrypt_before_bootstrap_fails() { - let db = db::create_test_pool().await; - let mut actor = Vault::new(db, GlobalActors::spawn_message_bus()) - .await - .unwrap(); - - let err = actor.decrypt(1).await.unwrap_err(); - assert!(matches!(err, Error::NotBootstrapped)); -} - -#[tokio::test] -#[test_log::test] -async fn new_restores_sealed_state() { - let db = db::create_test_pool().await; - let actor = common::bootstrapped_vault(&db).await; - drop(actor); - - let mut actor2 = Vault::new(db, GlobalActors::spawn_message_bus()) - .await - .unwrap(); - let err = actor2.decrypt(1).await.unwrap_err(); - assert!(matches!(err, Error::Sealed)); -} - -#[tokio::test] -#[test_log::test] -async fn unseal_correct_password() { - let db = db::create_test_pool().await; - let mut actor = common::bootstrapped_vault(&db).await; - - let plaintext = b"survive a restart"; - let aead_id = actor - .create_new(SafeCell::new(plaintext.to_vec())) - .await - .unwrap(); - drop(actor); - - let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) - .await - .unwrap(); - let seal_key = SafeCell::new(b"test-seal-key".to_vec()); - actor.try_unseal(seal_key).await.unwrap(); - - let mut decrypted = actor.decrypt(aead_id).await.unwrap(); - assert_eq!(*decrypted.read(), plaintext); -} - -#[tokio::test] -#[test_log::test] -async fn unseal_wrong_then_correct_password() { - let db = db::create_test_pool().await; - let mut actor = common::bootstrapped_vault(&db).await; - - let plaintext = b"important data"; - let aead_id = actor - .create_new(SafeCell::new(plaintext.to_vec())) - .await - .unwrap(); - drop(actor); - - let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) - .await - .unwrap(); - - let bad_key = SafeCell::new(b"wrong-password".to_vec()); - let err = actor.try_unseal(bad_key).await.unwrap_err(); - assert!(matches!(err, Error::InvalidKey)); - - let good_key = SafeCell::new(b"test-seal-key".to_vec()); - actor.try_unseal(good_key).await.unwrap(); - - let mut decrypted = actor.decrypt(aead_id).await.unwrap(); - assert_eq!(*decrypted.read(), plaintext); -} +use crate::common; +use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; +use arbiter_server::{ + actors::{ + GlobalActors, + vault::{Error, Vault}, + }, + crypto::encryption::v1::{Nonce, ROOT_KEY_TAG}, + db::{self, models, schema}, +}; + +use diesel::{QueryDsl, SelectableHelper}; +use diesel_async::RunQueryDsl; + +#[tokio::test] +#[test_log::test] +async fn bootstrap() { + let db = db::create_test_pool().await; + let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) + .await + .unwrap(); + + let seal_key = SafeCell::new(b"test-seal-key".to_vec()); + actor.bootstrap(seal_key).await.unwrap(); + + let mut conn = db.get().await.unwrap(); + let row: models::RootKeyHistory = schema::root_key_history::table + .select(models::RootKeyHistory::as_select()) + .first(&mut conn) + .await + .unwrap(); + + assert_eq!(row.schema_version, 1); + assert_eq!(row.tag, ROOT_KEY_TAG); + assert!(!row.ciphertext.is_empty()); + assert!(!row.salt.is_empty()); + assert_eq!(row.data_encryption_nonce, Nonce::default().to_vec()); +} + +#[tokio::test] +#[test_log::test] +async fn bootstrap_rejects_double() { + let db = db::create_test_pool().await; + let mut actor = common::bootstrapped_vault(&db).await; + + let seal_key2 = SafeCell::new(b"test-seal-key".to_vec()); + let err = actor.bootstrap(seal_key2).await.unwrap_err(); + assert!(matches!(err, Error::AlreadyBootstrapped)); +} + +#[tokio::test] +#[test_log::test] +async fn create_new_before_bootstrap_fails() { + let db = db::create_test_pool().await; + let mut actor = Vault::new(db, GlobalActors::spawn_message_bus()) + .await + .unwrap(); + + let err = actor + .create_new(SafeCell::new(b"data".to_vec())) + .await + .unwrap_err(); + assert!(matches!(err, Error::NotBootstrapped)); +} + +#[tokio::test] +#[test_log::test] +async fn decrypt_before_bootstrap_fails() { + let db = db::create_test_pool().await; + let mut actor = Vault::new(db, GlobalActors::spawn_message_bus()) + .await + .unwrap(); + + let err = actor.decrypt(1).await.unwrap_err(); + assert!(matches!(err, Error::NotBootstrapped)); +} + +#[tokio::test] +#[test_log::test] +async fn new_restores_sealed_state() { + let db = db::create_test_pool().await; + let actor = common::bootstrapped_vault(&db).await; + drop(actor); + + let mut actor2 = Vault::new(db, GlobalActors::spawn_message_bus()) + .await + .unwrap(); + let err = actor2.decrypt(1).await.unwrap_err(); + assert!(matches!(err, Error::Sealed)); +} + +#[tokio::test] +#[test_log::test] +async fn unseal_correct_password() { + let db = db::create_test_pool().await; + let mut actor = common::bootstrapped_vault(&db).await; + + let plaintext = b"survive a restart"; + let aead_id = actor + .create_new(SafeCell::new(plaintext.to_vec())) + .await + .unwrap(); + drop(actor); + + let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) + .await + .unwrap(); + let seal_key = SafeCell::new(b"test-seal-key".to_vec()); + actor.try_unseal(seal_key).await.unwrap(); + + let mut decrypted = actor.decrypt(aead_id).await.unwrap(); + assert_eq!(*decrypted.read(), plaintext); +} + +#[tokio::test] +#[test_log::test] +async fn unseal_wrong_then_correct_password() { + let db = db::create_test_pool().await; + let mut actor = common::bootstrapped_vault(&db).await; + + let plaintext = b"important data"; + let aead_id = actor + .create_new(SafeCell::new(plaintext.to_vec())) + .await + .unwrap(); + drop(actor); + + let mut actor = Vault::new(db.clone(), GlobalActors::spawn_message_bus()) + .await + .unwrap(); + + let bad_key = SafeCell::new(b"wrong-password".to_vec()); + let err = actor.try_unseal(bad_key).await.unwrap_err(); + assert!(matches!(err, Error::InvalidKey)); + + let good_key = SafeCell::new(b"test-seal-key".to_vec()); + actor.try_unseal(good_key).await.unwrap(); + + let mut decrypted = actor.decrypt(aead_id).await.unwrap(); + assert_eq!(*decrypted.read(), plaintext); +} diff --git a/server/crates/arbiter-server/tests/vault/storage.rs b/server/crates/arbiter-server/tests/vault/storage.rs index c1bd321..2ecd695 100644 --- a/server/crates/arbiter-server/tests/vault/storage.rs +++ b/server/crates/arbiter-server/tests/vault/storage.rs @@ -1,161 +1,161 @@ -use crate::common; -use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; -use arbiter_server::{ - actors::vault::Error, - crypto::encryption::v1::Nonce, - db::{self, models, schema}, -}; - -use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper, dsl::update}; -use diesel_async::RunQueryDsl; -use std::collections::HashSet; - -#[tokio::test] -#[test_log::test] -async fn create_decrypt_roundtrip() { - let db = db::create_test_pool().await; - let mut actor = common::bootstrapped_vault(&db).await; - - let plaintext = b"hello arbiter"; - let aead_id = actor - .create_new(SafeCell::new(plaintext.to_vec())) - .await - .unwrap(); - - let mut decrypted = actor.decrypt(aead_id).await.unwrap(); - assert_eq!(*decrypted.read(), plaintext); -} - -#[tokio::test] -#[test_log::test] -async fn decrypt_nonexistent_returns_not_found() { - let db = db::create_test_pool().await; - let mut actor = common::bootstrapped_vault(&db).await; - - let err = actor.decrypt(9999).await.unwrap_err(); - assert!(matches!(err, Error::NotFound)); -} - -#[tokio::test] -#[test_log::test] -async fn ciphertext_differs_across_entries() { - let db = db::create_test_pool().await; - let mut actor = common::bootstrapped_vault(&db).await; - - let plaintext = b"same content"; - let id1 = actor - .create_new(SafeCell::new(plaintext.to_vec())) - .await - .unwrap(); - let id2 = actor - .create_new(SafeCell::new(plaintext.to_vec())) - .await - .unwrap(); - - let mut conn = db.get().await.unwrap(); - let row1: models::AeadEncrypted = schema::aead_encrypted::table - .filter(schema::aead_encrypted::id.eq(id1)) - .select(models::AeadEncrypted::as_select()) - .first(&mut conn) - .await - .unwrap(); - let row2: models::AeadEncrypted = schema::aead_encrypted::table - .filter(schema::aead_encrypted::id.eq(id2)) - .select(models::AeadEncrypted::as_select()) - .first(&mut conn) - .await - .unwrap(); - - assert_ne!(row1.ciphertext, row2.ciphertext); - - let mut d1 = actor.decrypt(id1).await.unwrap(); - let mut d2 = actor.decrypt(id2).await.unwrap(); - assert_eq!(*d1.read(), plaintext); - assert_eq!(*d2.read(), plaintext); -} - -#[tokio::test] -#[test_log::test] -async fn nonce_never_reused() { - let db = db::create_test_pool().await; - let mut actor = common::bootstrapped_vault(&db).await; - - let n = 5; - for i in 0..n { - actor - .create_new(SafeCell::new(format!("secret {i}").into_bytes())) - .await - .unwrap(); - } - - let mut conn = db.get().await.unwrap(); - let rows: Vec = schema::aead_encrypted::table - .select(models::AeadEncrypted::as_select()) - .load(&mut conn) - .await - .unwrap(); - - assert_eq!(rows.len(), n); - - let nonces: Vec<&Vec> = rows.iter().map(|r| &r.current_nonce).collect(); - let unique: HashSet<&Vec> = nonces.iter().copied().collect(); - assert_eq!(nonces.len(), unique.len(), "all nonces must be unique"); - - for (i, row) in rows.iter().enumerate() { - let mut expected = Nonce::default(); - for _ in 0..=i { - expected.increment(); - } - assert_eq!(row.current_nonce, expected.to_vec(), "nonce {i} mismatch"); - } - - let root_row: models::RootKeyHistory = schema::root_key_history::table - .select(models::RootKeyHistory::as_select()) - .first(&mut conn) - .await - .unwrap(); - let last_nonce = &rows.last().unwrap().current_nonce; - assert_eq!(&root_row.data_encryption_nonce, last_nonce); -} - -#[tokio::test] -#[test_log::test] -async fn broken_db_nonce_format_fails_closed() { - let db = db::create_test_pool().await; - let mut actor = common::bootstrapped_vault(&db).await; - let root_key_history_id = common::root_key_history_id(&db).await; - - let mut conn = db.get().await.unwrap(); - update( - schema::root_key_history::table - .filter(schema::root_key_history::id.eq(root_key_history_id)), - ) - .set(schema::root_key_history::data_encryption_nonce.eq(vec![1, 2, 3])) - .execute(&mut conn) - .await - .unwrap(); - drop(conn); - - let err = actor - .create_new(SafeCell::new(b"must fail".to_vec())) - .await - .unwrap_err(); - assert!(matches!(err, Error::BrokenDatabase)); - - let db = db::create_test_pool().await; - let mut actor = common::bootstrapped_vault(&db).await; - let id = actor - .create_new(SafeCell::new(b"decrypt target".to_vec())) - .await - .unwrap(); - let mut conn = db.get().await.unwrap(); - update(schema::aead_encrypted::table.filter(schema::aead_encrypted::id.eq(id))) - .set(schema::aead_encrypted::current_nonce.eq(vec![7, 8])) - .execute(&mut conn) - .await - .unwrap(); - drop(conn); - - let err = actor.decrypt(id).await.unwrap_err(); - assert!(matches!(err, Error::BrokenDatabase)); -} +use crate::common; +use arbiter_crypto::safecell::{SafeCell, SafeCellHandle as _}; +use arbiter_server::{ + actors::vault::Error, + crypto::encryption::v1::Nonce, + db::{self, models, schema}, +}; + +use diesel::{ExpressionMethods as _, QueryDsl, SelectableHelper, dsl::update}; +use diesel_async::RunQueryDsl; +use std::collections::HashSet; + +#[tokio::test] +#[test_log::test] +async fn create_decrypt_roundtrip() { + let db = db::create_test_pool().await; + let mut actor = common::bootstrapped_vault(&db).await; + + let plaintext = b"hello arbiter"; + let aead_id = actor + .create_new(SafeCell::new(plaintext.to_vec())) + .await + .unwrap(); + + let mut decrypted = actor.decrypt(aead_id).await.unwrap(); + assert_eq!(*decrypted.read(), plaintext); +} + +#[tokio::test] +#[test_log::test] +async fn decrypt_nonexistent_returns_not_found() { + let db = db::create_test_pool().await; + let mut actor = common::bootstrapped_vault(&db).await; + + let err = actor.decrypt(9999).await.unwrap_err(); + assert!(matches!(err, Error::NotFound)); +} + +#[tokio::test] +#[test_log::test] +async fn ciphertext_differs_across_entries() { + let db = db::create_test_pool().await; + let mut actor = common::bootstrapped_vault(&db).await; + + let plaintext = b"same content"; + let id1 = actor + .create_new(SafeCell::new(plaintext.to_vec())) + .await + .unwrap(); + let id2 = actor + .create_new(SafeCell::new(plaintext.to_vec())) + .await + .unwrap(); + + let mut conn = db.get().await.unwrap(); + let row1: models::AeadEncrypted = schema::aead_encrypted::table + .filter(schema::aead_encrypted::id.eq(id1)) + .select(models::AeadEncrypted::as_select()) + .first(&mut conn) + .await + .unwrap(); + let row2: models::AeadEncrypted = schema::aead_encrypted::table + .filter(schema::aead_encrypted::id.eq(id2)) + .select(models::AeadEncrypted::as_select()) + .first(&mut conn) + .await + .unwrap(); + + assert_ne!(row1.ciphertext, row2.ciphertext); + + let mut d1 = actor.decrypt(id1).await.unwrap(); + let mut d2 = actor.decrypt(id2).await.unwrap(); + assert_eq!(*d1.read(), plaintext); + assert_eq!(*d2.read(), plaintext); +} + +#[tokio::test] +#[test_log::test] +async fn nonce_never_reused() { + let db = db::create_test_pool().await; + let mut actor = common::bootstrapped_vault(&db).await; + + let n = 5; + for i in 0..n { + actor + .create_new(SafeCell::new(format!("secret {i}").into_bytes())) + .await + .unwrap(); + } + + let mut conn = db.get().await.unwrap(); + let rows: Vec = schema::aead_encrypted::table + .select(models::AeadEncrypted::as_select()) + .load(&mut conn) + .await + .unwrap(); + + assert_eq!(rows.len(), n); + + let nonces: Vec<&Vec> = rows.iter().map(|r| &r.current_nonce).collect(); + let unique: HashSet<&Vec> = nonces.iter().copied().collect(); + assert_eq!(nonces.len(), unique.len(), "all nonces must be unique"); + + for (i, row) in rows.iter().enumerate() { + let mut expected = Nonce::default(); + for _ in 0..=i { + expected.increment(); + } + assert_eq!(row.current_nonce, expected.to_vec(), "nonce {i} mismatch"); + } + + let root_row: models::RootKeyHistory = schema::root_key_history::table + .select(models::RootKeyHistory::as_select()) + .first(&mut conn) + .await + .unwrap(); + let last_nonce = &rows.last().unwrap().current_nonce; + assert_eq!(&root_row.data_encryption_nonce, last_nonce); +} + +#[tokio::test] +#[test_log::test] +async fn broken_db_nonce_format_fails_closed() { + let db = db::create_test_pool().await; + let mut actor = common::bootstrapped_vault(&db).await; + let root_key_history_id = common::root_key_history_id(&db).await; + + let mut conn = db.get().await.unwrap(); + update( + schema::root_key_history::table + .filter(schema::root_key_history::id.eq(root_key_history_id)), + ) + .set(schema::root_key_history::data_encryption_nonce.eq(vec![1, 2, 3])) + .execute(&mut conn) + .await + .unwrap(); + drop(conn); + + let err = actor + .create_new(SafeCell::new(b"must fail".to_vec())) + .await + .unwrap_err(); + assert!(matches!(err, Error::BrokenDatabase)); + + let db = db::create_test_pool().await; + let mut actor = common::bootstrapped_vault(&db).await; + let id = actor + .create_new(SafeCell::new(b"decrypt target".to_vec())) + .await + .unwrap(); + let mut conn = db.get().await.unwrap(); + update(schema::aead_encrypted::table.filter(schema::aead_encrypted::id.eq(id))) + .set(schema::aead_encrypted::current_nonce.eq(vec![7, 8])) + .execute(&mut conn) + .await + .unwrap(); + drop(conn); + + let err = actor.decrypt(id).await.unwrap_err(); + assert!(matches!(err, Error::BrokenDatabase)); +} diff --git a/server/crates/arbiter-tokens-registry/Cargo.toml b/server/crates/arbiter-tokens-registry/Cargo.toml index 663df13..e3a2581 100644 --- a/server/crates/arbiter-tokens-registry/Cargo.toml +++ b/server/crates/arbiter-tokens-registry/Cargo.toml @@ -1,11 +1,11 @@ -[package] -name = "arbiter-tokens-registry" -version = "0.1.0" -edition = "2024" - -[dependencies] -alloy.workspace = true - -[lib] -test = false -doctest = false +[package] +name = "arbiter-tokens-registry" +version = "0.1.0" +edition = "2024" + +[dependencies] +alloy.workspace = true + +[lib] +test = false +doctest = false diff --git a/server/crates/arbiter-tokens-registry/src/evm/mod.rs b/server/crates/arbiter-tokens-registry/src/evm/mod.rs index 1cf332b..2af7fbb 100644 --- a/server/crates/arbiter-tokens-registry/src/evm/mod.rs +++ b/server/crates/arbiter-tokens-registry/src/evm/mod.rs @@ -1 +1 @@ -pub mod nonfungible; +pub mod nonfungible; diff --git a/server/crates/arbiter-tokens-registry/src/evm/nonfungible.rs b/server/crates/arbiter-tokens-registry/src/evm/nonfungible.rs index 581195d..f43d49b 100644 --- a/server/crates/arbiter-tokens-registry/src/evm/nonfungible.rs +++ b/server/crates/arbiter-tokens-registry/src/evm/nonfungible.rs @@ -1,13 +1,13 @@ -use alloy::primitives::{Address, ChainId, address}; - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TokenInfo { - pub name: &'static str, - pub symbol: &'static str, - pub decimals: u32, - pub contract: Address, - pub chain: ChainId, - pub logo_uri: Option<&'static str>, -} - -include!("tokens.rs"); +use alloy::primitives::{Address, ChainId, address}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TokenInfo { + pub name: &'static str, + pub symbol: &'static str, + pub decimals: u32, + pub contract: Address, + pub chain: ChainId, + pub logo_uri: Option<&'static str>, +} + +include!("tokens.rs"); diff --git a/server/crates/arbiter-tokens-registry/src/evm/tokens.rs b/server/crates/arbiter-tokens-registry/src/evm/tokens.rs index ba59489..4d6e5f0 100644 --- a/server/crates/arbiter-tokens-registry/src/evm/tokens.rs +++ b/server/crates/arbiter-tokens-registry/src/evm/tokens.rs @@ -1,13248 +1,13248 @@ -// Auto-generated from Uniswap token list v18.7.0 -// 1203 tokens -// DO NOT EDIT - regenerate with gen_erc20_registry.py - -pub static TOKEN_1INCH: TokenInfo = TokenInfo { - name: "1inch", - symbol: "1INCH", - decimals: 18, - contract: address!("0x111111111117dC0aa78b770fA6A738034120C302"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), -}; - -pub static ANCIENT8: TokenInfo = TokenInfo { - name: "Ancient8", - symbol: "A8", - decimals: 18, - contract: address!("0x3E5A19c91266aD8cE2477B91585d1856B84062dF"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/39170/standard/A8_Token-04_200x200.png?1720798300"), -}; - -pub static AAVE: TokenInfo = TokenInfo { - name: "Aave", - symbol: "AAVE", - decimals: 18, - contract: address!("0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), -}; - -pub static ARCBLOCK: TokenInfo = TokenInfo { - name: "Arcblock", - symbol: "ABT", - decimals: 18, - contract: address!("0xB98d4C97425d9908E66E53A6fDf673ACcA0BE986"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2341/thumb/arcblock.png?1547036543"), -}; - -pub static ALCHEMY_PAY: TokenInfo = TokenInfo { - name: "Alchemy Pay", - symbol: "ACH", - decimals: 8, - contract: address!("0xEd04915c23f00A313a544955524EB7DBD823143d"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12390/thumb/ACH_%281%29.png?1599691266"), -}; - -pub static ACROSS_PROTOCOL_TOKEN: TokenInfo = TokenInfo { - name: "Across Protocol Token", - symbol: "ACX", - decimals: 18, - contract: address!("0x44108f0223A3C3028F5Fe7AEC7f9bb2E66beF82F"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165"), -}; - -pub static AMBIRE_ADEX: TokenInfo = TokenInfo { - name: "Ambire AdEx", - symbol: "ADX", - decimals: 18, - contract: address!("0xADE00C28244d5CE17D72E40330B1c318cD12B7c3"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540"), -}; - -pub static AERGO: TokenInfo = TokenInfo { - name: "Aergo", - symbol: "AERGO", - decimals: 18, - contract: address!("0x91Af0fBB28ABA7E31403Cb457106Ce79397FD4E6"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/4490/thumb/aergo.png?1647696770"), -}; - -pub static AEVO: TokenInfo = TokenInfo { - name: "Aevo", - symbol: "AEVO", - decimals: 18, - contract: address!("0xB528edBef013aff855ac3c50b381f253aF13b997"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/35893/standard/aevo.png"), -}; - -pub static AGEUR: TokenInfo = TokenInfo { - name: "agEur", - symbol: "agEUR", - decimals: 18, - contract: address!("0x1a7e4e63778B4f12a199C062f3eFdD288afCBce8"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), -}; - -pub static ADVENTURE_GOLD: TokenInfo = TokenInfo { - name: "Adventure Gold", - symbol: "AGLD", - decimals: 18, - contract: address!("0x32353A6C91143bfd6C7d363B546e62a9A2489A20"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/18125/thumb/lpgblc4h_400x400.jpg?1630570955"), -}; - -pub static AIOZ_NETWORK: TokenInfo = TokenInfo { - name: "AIOZ Network", - symbol: "AIOZ", - decimals: 18, - contract: address!("0x626E8036dEB333b408Be468F951bdB42433cBF18"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126"), -}; - -pub static ALCHEMIX: TokenInfo = TokenInfo { - name: "Alchemix", - symbol: "ALCX", - decimals: 18, - contract: address!("0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14113/thumb/Alchemix.png?1614409874"), -}; - -pub static ALEPH_IM: TokenInfo = TokenInfo { - name: "Aleph im", - symbol: "ALEPH", - decimals: 18, - contract: address!("0x27702a26126e0B3702af63Ee09aC4d1A084EF628"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725"), -}; - -pub static ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE: TokenInfo = TokenInfo { - name: "Alethea Artificial Liquid Intelligence", - symbol: "ALI", - decimals: 18, - contract: address!("0x6B0b3a982b4634aC68dD83a4DBF02311cE324181"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848"), -}; - -pub static MY_NEIGHBOR_ALICE: TokenInfo = TokenInfo { - name: "My Neighbor Alice", - symbol: "ALICE", - decimals: 6, - contract: address!("0xAC51066d7bEC65Dc4589368da368b212745d63E8"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14375/thumb/alice_logo.jpg?1615782968"), -}; - -pub static ALLORA: TokenInfo = TokenInfo { - name: "Allora", - symbol: "ALLO", - decimals: 18, - contract: address!("0x8408D45b61f5823298F19a09B53b7339c0280489"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/70609/large/allo-token.png?1763451165"), -}; - -pub static ALPHA_VENTURE_DAO: TokenInfo = TokenInfo { - name: "Alpha Venture DAO", - symbol: "ALPHA", - decimals: 18, - contract: address!("0xa1faa113cbE53436Df28FF0aEe54275c13B40975"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876"), -}; - -pub static ALTLAYER: TokenInfo = TokenInfo { - name: "AltLayer", - symbol: "ALT", - decimals: 18, - contract: address!("0x8457CA5040ad67fdebbCC8EdCE889A335Bc0fbFB"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/34608/standard/Logomark_200x200.png"), -}; - -pub static AMP: TokenInfo = TokenInfo { - name: "Amp", - symbol: "AMP", - decimals: 18, - contract: address!("0xfF20817765cB7f73d4bde2e66e067E58D11095C2"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12409/thumb/amp-200x200.png?1599625397"), -}; - -pub static ANKR: TokenInfo = TokenInfo { - name: "Ankr", - symbol: "ANKR", - decimals: 18, - contract: address!("0x8290333ceF9e6D528dD5618Fb97a76f268f3EDD4"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978"), -}; - -pub static ARAGON: TokenInfo = TokenInfo { - name: "Aragon", - symbol: "ANT", - decimals: 18, - contract: address!("0xa117000000f279D81A1D3cc75430fAA017FA5A2e"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/681/thumb/JelZ58cv_400x400.png?1601449653"), -}; - -pub static APECOIN: TokenInfo = TokenInfo { - name: "ApeCoin", - symbol: "APE", - decimals: 18, - contract: address!("0x4d224452801ACEd8B2F0aebE155379bb5D594381"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/24383/small/apecoin.jpg?1647476455"), -}; - -pub static API3: TokenInfo = TokenInfo { - name: "API3", - symbol: "API3", - decimals: 18, - contract: address!("0x0b38210ea11411557c13457D4dA7dC6ea731B88a"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13256/thumb/api3.jpg?1606751424"), -}; - -pub static APRIORI: TokenInfo = TokenInfo { - name: "aPriori", - symbol: "APR", - decimals: 18, - contract: address!("0x5A9610919f5e81183823A2be4Bd1BeB2B4da2a20"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/70220/large/logo-icon-Gradient.png?1761118006"), -}; - -pub static APU_APUSTAJA: TokenInfo = TokenInfo { - name: "Apu Apustaja", - symbol: "APU", - decimals: 18, - contract: address!("0x594DaaD7D77592a2b97b725A7AD59D7E188b5bFa"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/35986/large/200x200.png?1710308147"), -}; - -pub static ARBITRUM: TokenInfo = TokenInfo { - name: "Arbitrum", - symbol: "ARB", - decimals: 18, - contract: address!("0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1"), - chain: 1, - logo_uri: Some("https://arbitrum.foundation/logo.png"), -}; - -pub static ARKHAM: TokenInfo = TokenInfo { - name: "Arkham", - symbol: "ARKM", - decimals: 18, - contract: address!("0x6E2a43be0B1d33b726f0CA3b8de60b3482b8b050"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/30929/standard/Arkham_Logo_CG.png?1696529771"), -}; - -pub static ARPA_CHAIN: TokenInfo = TokenInfo { - name: "ARPA Chain", - symbol: "ARPA", - decimals: 18, - contract: address!("0xBA50933C268F567BDC86E1aC131BE072C6B0b71a"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357"), -}; - -pub static ASH: TokenInfo = TokenInfo { - name: "ASH", - symbol: "ASH", - decimals: 18, - contract: address!("0x64D91f12Ece7362F91A6f8E7940Cd55F05060b92"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/15714/thumb/omnPqaTY.png?1622820503"), -}; - -pub static ASSEMBLE_PROTOCOL: TokenInfo = TokenInfo { - name: "Assemble Protocol", - symbol: "ASM", - decimals: 18, - contract: address!("0x2565ae0385659badCada1031DB704442E1b69982"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11605/thumb/gpvrlkSq_400x400_%281%29.jpg?1591775789"), -}; - -pub static AIRSWAP: TokenInfo = TokenInfo { - name: "AirSwap", - symbol: "AST", - decimals: 4, - contract: address!("0x27054b13b1B798B345b591a4d22e6562d47eA75a"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1019/thumb/Airswap.png?1630903484"), -}; - -pub static AUTOMATA: TokenInfo = TokenInfo { - name: "Automata", - symbol: "ATA", - decimals: 18, - contract: address!("0xA2120b9e674d3fC3875f415A7DF52e382F141225"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745"), -}; - -pub static AETHIR_TOKEN: TokenInfo = TokenInfo { - name: "Aethir Token", - symbol: "ATH", - decimals: 18, - contract: address!("0xbe0Ed4138121EcFC5c0E56B40517da27E6c5226B"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/36179/large/logogram_circle_dark_green_vb_green_(1).png?1718232706"), -}; - -pub static BOUNCE: TokenInfo = TokenInfo { - name: "Bounce", - symbol: "AUCTION", - decimals: 18, - contract: address!("0xA9B1Eb5908CfC3cdf91F9B8B3a74108598009096"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13860/thumb/1_KtgpRIJzuwfHe0Rl0avP_g.jpeg?1612412025"), -}; - -pub static AUDD: TokenInfo = TokenInfo { - name: "AUDD", - symbol: "AUDD", - decimals: 6, - contract: address!("0x4cCe605eD955295432958d8951D0B176C10720d5"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/33263/large/AUDD-Logo-Blue_512.png?1701319895"), -}; - -pub static AUDIUS: TokenInfo = TokenInfo { - name: "Audius", - symbol: "AUDIO", - decimals: 18, - contract: address!("0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12913/thumb/AudiusCoinLogo_2x.png?1603425727"), -}; - -pub static ARTVERSE_TOKEN: TokenInfo = TokenInfo { - name: "Artverse Token", - symbol: "AVT", - decimals: 18, - contract: address!("0x845576c64f9754CF09d87e45B720E82F3EeF522C"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/19727/thumb/ewnektoB_400x400.png?1635767094"), -}; - -pub static AXELAR: TokenInfo = TokenInfo { - name: "Axelar", - symbol: "AXL", - decimals: 6, - contract: address!("0x467719aD09025FcC6cF6F8311755809d45a5E5f3"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg"), -}; - -pub static AXIE_INFINITY: TokenInfo = TokenInfo { - name: "Axie Infinity", - symbol: "AXS", - decimals: 18, - contract: address!("0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082"), -}; - -pub static AZTEC: TokenInfo = TokenInfo { - name: "Aztec", - symbol: "AZTEC", - decimals: 18, - contract: address!("0xA27EC0006e59f245217Ff08CD52A7E8b169E62D2"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/70681/large/aztec.png?1763091883"), -}; - -pub static BADGER_DAO: TokenInfo = TokenInfo { - name: "Badger DAO", - symbol: "BADGER", - decimals: 18, - contract: address!("0x3472A5A71965499acd81997a54BBA8D852C6E53d"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13287/thumb/badger_dao_logo.jpg?1607054976"), -}; - -pub static BALANCER: TokenInfo = TokenInfo { - name: "Balancer", - symbol: "BAL", - decimals: 18, - contract: address!("0xba100000625a3754423978a60c9317c58a424e3D"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png"), -}; - -pub static BAND_PROTOCOL: TokenInfo = TokenInfo { - name: "Band Protocol", - symbol: "BAND", - decimals: 18, - contract: address!("0xBA11D00c5f74255f56a5E366F4F77f5A186d7f55"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/9545/thumb/band-protocol.png?1568730326"), -}; - -pub static LOMBARD: TokenInfo = TokenInfo { - name: "Lombard", - symbol: "BARD", - decimals: 18, - contract: address!("0xf0DB65D17e30a966C2ae6A21f6BBA71cea6e9754"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/68404/large/bard.png?1755657543"), -}; - -pub static BASIC_ATTENTION_TOKEN: TokenInfo = TokenInfo { - name: "Basic Attention Token", - symbol: "BAT", - decimals: 18, - contract: address!("0x0D8775F648430679A709E98d2b0Cb6250d2887EF"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427"), -}; - -pub static BEAM: TokenInfo = TokenInfo { - name: "Beam", - symbol: "BEAM", - decimals: 18, - contract: address!("0x62D0A8458eD7719FDAF978fe5929C6D342B0bFcE"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/32417/standard/chain-logo.png?1698114384"), -}; - -pub static BICONOMY: TokenInfo = TokenInfo { - name: "Biconomy", - symbol: "BICO", - decimals: 18, - contract: address!("0xF17e65822b568B3903685a7c9F496CF7656Cc6C2"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749"), -}; - -pub static BIG_TIME: TokenInfo = TokenInfo { - name: "Big Time", - symbol: "BIGTIME", - decimals: 18, - contract: address!("0x64Bc2cA1Be492bE7185FAA2c8835d9b824c8a194"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/32251/standard/-6136155493475923781_121.jpg?1696998691"), -}; - -pub static BIO: TokenInfo = TokenInfo { - name: "BIO", - symbol: "BIO", - decimals: 18, - contract: address!("0xcb1592591996765Ec0eFc1f92599A19767ee5ffA"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/53022/large/bio.jpg?1735011002"), -}; - -pub static BITDAO: TokenInfo = TokenInfo { - name: "BitDAO", - symbol: "BIT", - decimals: 18, - contract: address!("0x1A4b46696b2bB4794Eb3D4c26f1c55F9170fa4C5"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/17627/thumb/rI_YptK8.png?1653983088"), -}; - -pub static HARRYPOTTEROBAMASONIC10INU: TokenInfo = TokenInfo { - name: "HarryPotterObamaSonic10Inu", - symbol: "BITCOIN", - decimals: 8, - contract: address!("0x72e4f9F808C49A2a61dE9C5896298920Dc4EEEa9"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224"), -}; - -pub static BLUR: TokenInfo = TokenInfo { - name: "Blur", - symbol: "BLUR", - decimals: 18, - contract: address!("0x5283D291DBCF85356A21bA090E6db59121208b44"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/28453/large/blur.png?1670745921"), -}; - -pub static BLUZELLE: TokenInfo = TokenInfo { - name: "Bluzelle", - symbol: "BLZ", - decimals: 18, - contract: address!("0x5732046A883704404F284Ce41FfADd5b007FD668"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2848/thumb/ColorIcon_3x.png?1622516510"), -}; - -pub static BANCOR_NETWORK_TOKEN: TokenInfo = TokenInfo { - name: "Bancor Network Token", - symbol: "BNT", - decimals: 18, - contract: address!("0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png"), -}; - -pub static BOBA_NETWORK: TokenInfo = TokenInfo { - name: "Boba Network", - symbol: "BOBA", - decimals: 18, - contract: address!("0x42bBFa2e77757C645eeaAd1655E0911a7553Efbc"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/20285/thumb/BOBA.png?1636811576"), -}; - -pub static BOB: TokenInfo = TokenInfo { - name: "BOB", - symbol: "BOBBOB", - decimals: 18, - contract: address!("0xC9746F73cC33a36c2cD55b8aEFD732586946Cedd"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54720/large/BOB_symbol_colour.png?1741195397"), -}; - -pub static BARNBRIDGE: TokenInfo = TokenInfo { - name: "BarnBridge", - symbol: "BOND", - decimals: 18, - contract: address!("0x0391D2021f89DC339F60Fff84546EA23E337750f"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853"), -}; - -pub static BREVIS: TokenInfo = TokenInfo { - name: "Brevis", - symbol: "BREV", - decimals: 18, - contract: address!("0x086F405146Ce90135750Bbec9A063a8B20A8bfFb"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/71219/large/brevis.png?1766454723"), -}; - -pub static BRAINTRUST: TokenInfo = TokenInfo { - name: "Braintrust", - symbol: "BTRST", - decimals: 18, - contract: address!("0x799ebfABE77a6E34311eeEe9825190B9ECe32824"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/18100/thumb/braintrust.PNG?1630475394"), -}; - -pub static BINANCE_USD: TokenInfo = TokenInfo { - name: "Binance USD", - symbol: "BUSD", - decimals: 18, - contract: address!("0x4Fabb145d64652a948d72533023f6E7A623C7C53"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), -}; - -pub static COIN98: TokenInfo = TokenInfo { - name: "Coin98", - symbol: "C98", - decimals: 18, - contract: address!("0xAE12C5930881c53715B369ceC7606B70d8EB229f"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/17117/thumb/logo.png?1626412904"), -}; - -pub static PANCAKESWAP: TokenInfo = TokenInfo { - name: "PancakeSwap", - symbol: "CAKE", - decimals: 18, - contract: address!("0x152649eA73beAb28c5b49B26eb48f7EAD6d4c898"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/12632/large/pancakeswap-cake-logo_%281%29.png?1696512440"), -}; - -pub static COINBASE_WRAPPED_BTC: TokenInfo = TokenInfo { - name: "Coinbase Wrapped BTC", - symbol: "cbBTC", - decimals: 8, - contract: address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/40143/standard/cbbtc.webp"), -}; - -pub static COINBASE_WRAPPED_STAKED_ETH: TokenInfo = TokenInfo { - name: "Coinbase Wrapped Staked ETH", - symbol: "cbETH", - decimals: 18, - contract: address!("0xBe9895146f7AF43049ca1c1AE358B0541Ea49704"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/27008/large/cbeth.png"), -}; - -pub static CELO_NATIVE_ASSET_WORMHOLE: TokenInfo = TokenInfo { - name: "Celo native asset (Wormhole)", - symbol: "CELO", - decimals: 18, - contract: address!("0x3294395e62F4eB6aF3f1Fcf89f5602D90Fb3Ef69"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png"), -}; - -pub static CELER_NETWORK: TokenInfo = TokenInfo { - name: "Celer Network", - symbol: "CELR", - decimals: 18, - contract: address!("0x4F9254C83EB525f9FCf346490bbb3ed28a81C667"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/4379/thumb/Celr.png?1554705437"), -}; - -pub static CENTRIFUGE: TokenInfo = TokenInfo { - name: "Centrifuge", - symbol: "CFG", - decimals: 18, - contract: address!("0xcccCCCcCCC33D538DBC2EE4fEab0a7A1FF4e8A94"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/55913/large/centrifuge.jpg?1747707741"), -}; - -pub static CHROMIA: TokenInfo = TokenInfo { - name: "Chromia", - symbol: "CHR", - decimals: 6, - contract: address!("0x8A2279d4A90B6fe1C4B30fa660cC9f926797bAA2"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/5000/thumb/Chromia.png?1559038018"), -}; - -pub static CHILIZ: TokenInfo = TokenInfo { - name: "Chiliz", - symbol: "CHZ", - decimals: 18, - contract: address!("0x3506424F91fD33084466F402d5D97f05F8e3b4AF"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/8834/thumb/Chiliz.png?1561970540"), -}; - -pub static CLOVER_FINANCE: TokenInfo = TokenInfo { - name: "Clover Finance", - symbol: "CLV", - decimals: 18, - contract: address!("0x80C62FE4487E1351b47Ba49809EBD60ED085bf52"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/15278/thumb/clover.png?1645084454"), -}; - -pub static COMPOUND: TokenInfo = TokenInfo { - name: "Compound", - symbol: "COMP", - decimals: 18, - contract: address!("0xc00e94Cb662C3520282E6f5717214004A7f26888"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), -}; - -pub static CORN: TokenInfo = TokenInfo { - name: "Corn", - symbol: "CORN", - decimals: 18, - contract: address!("0x44f49ff0da2498bCb1D3Dc7C0f999578F67FD8C6"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54471/large/corn.jpg?1739933588"), -}; - -pub static COTI: TokenInfo = TokenInfo { - name: "COTI", - symbol: "COTI", - decimals: 18, - contract: address!("0xDDB3422497E61e13543BeA06989C0789117555c5"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2962/thumb/Coti.png?1559653863"), -}; - -pub static CIRCUITS_OF_VALUE: TokenInfo = TokenInfo { - name: "Circuits of Value", - symbol: "COVAL", - decimals: 8, - contract: address!("0x3D658390460295FB963f54dC0899cfb1c30776Df"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/588/thumb/coval-logo.png?1599493950"), -}; - -pub static COW_PROTOCOL: TokenInfo = TokenInfo { - name: "CoW Protocol", - symbol: "COW", - decimals: 18, - contract: address!("0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/24384/large/CoW-token_logo.png?1719524382"), -}; - -pub static CLEARPOOL: TokenInfo = TokenInfo { - name: "Clearpool", - symbol: "CPOOL", - decimals: 18, - contract: address!("0x66761Fa41377003622aEE3c7675Fc7b5c1C2FaC5"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/19252/large/photo_2022-08-31_12.45.02.jpeg?1696518697"), -}; - -pub static COVALENT: TokenInfo = TokenInfo { - name: "Covalent", - symbol: "CQT", - decimals: 18, - contract: address!("0xD417144312DbF50465b1C641d016962017Ef6240"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14168/thumb/covalent-cqt.png?1624545218"), -}; - -pub static CRONOS: TokenInfo = TokenInfo { - name: "Cronos", - symbol: "CRO", - decimals: 8, - contract: address!("0xA0b73E1Ff0B80914AB6fe0444E65848C4C34450b"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/7310/thumb/oCw2s3GI_400x400.jpeg?1645172042"), -}; - -pub static CRYPTERIUM: TokenInfo = TokenInfo { - name: "Crypterium", - symbol: "CRPT", - decimals: 18, - contract: address!("0x08389495D7456E1951ddF7c3a1314A4bfb646d8B"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1901/thumb/crypt.png?1547036205"), -}; - -pub static CURVE_DAO_TOKEN: TokenInfo = TokenInfo { - name: "Curve DAO Token", - symbol: "CRV", - decimals: 18, - contract: address!("0xD533a949740bb3306d119CC777fa900bA034cd52"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), -}; - -pub static CARTESI: TokenInfo = TokenInfo { - name: "Cartesi", - symbol: "CTSI", - decimals: 18, - contract: address!("0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), -}; - -pub static CRYPTEX_FINANCE: TokenInfo = TokenInfo { - name: "Cryptex Finance", - symbol: "CTX", - decimals: 18, - contract: address!("0x321C2fE4446C7c963dc41Dd58879AF648838f98D"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171"), -}; - -pub static SOMNIUM_SPACE_CUBES: TokenInfo = TokenInfo { - name: "Somnium Space CUBEs", - symbol: "CUBE", - decimals: 8, - contract: address!("0xDf801468a808a32656D2eD2D2d80B72A129739f4"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/10687/thumb/CUBE_icon.png?1617026861"), -}; - -pub static CIVIC: TokenInfo = TokenInfo { - name: "Civic", - symbol: "CVC", - decimals: 8, - contract: address!("0x41e5560054824eA6B0732E656E3Ad64E20e94E45"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556"), -}; - -pub static CONVEX_FINANCE: TokenInfo = TokenInfo { - name: "Convex Finance", - symbol: "CVX", - decimals: 18, - contract: address!("0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/15585/thumb/convex.png?1621256328"), -}; - -pub static COVALENT_X_TOKEN: TokenInfo = TokenInfo { - name: "Covalent X Token", - symbol: "CXT", - decimals: 18, - contract: address!("0x7ABc8A5768E6bE61A6c693a6e4EAcb5B60602C4D"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/39177/large/CXT_Ticker.png?1720829918"), -}; - -pub static DAI_STABLECOIN: TokenInfo = TokenInfo { - name: "Dai Stablecoin", - symbol: "DAI", - decimals: 18, - contract: address!("0x6B175474E89094C44Da98b954EedeAC495271d0F"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), -}; - -pub static MINES_OF_DALARNIA: TokenInfo = TokenInfo { - name: "Mines of Dalarnia", - symbol: "DAR", - decimals: 6, - contract: address!("0x081131434f93063751813C619Ecca9C4dC7862a3"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/19837/thumb/dar.png?1636014223"), -}; - -pub static DERIVADAO: TokenInfo = TokenInfo { - name: "DerivaDAO", - symbol: "DDX", - decimals: 18, - contract: address!("0x3A880652F47bFaa771908C07Dd8673A787dAEd3A"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13453/thumb/ddx_logo.png?1608741641"), -}; - -pub static DENT: TokenInfo = TokenInfo { - name: "Dent", - symbol: "DENT", - decimals: 8, - contract: address!("0x3597bfD533a99c9aa083587B074434E61Eb0A258"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1152/thumb/gLCEA2G.png?1604543239"), -}; - -pub static DEXTOOLS: TokenInfo = TokenInfo { - name: "DexTools", - symbol: "DEXT", - decimals: 18, - contract: address!("0xfB7B4564402E5500dB5bB6d63Ae671302777C75a"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188"), -}; - -pub static DIA: TokenInfo = TokenInfo { - name: "DIA", - symbol: "DIA", - decimals: 18, - contract: address!("0x84cA8bc7997272c7CfB4D0Cd3D55cd942B3c9419"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751"), -}; - -pub static DISTRICT0X: TokenInfo = TokenInfo { - name: "district0x", - symbol: "DNT", - decimals: 18, - contract: address!("0x0AbdAce70D3790235af448C88547603b945604ea"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/849/thumb/district0x.png?1547223762"), -}; - -pub static DOLOMITE: TokenInfo = TokenInfo { - name: "Dolomite", - symbol: "DOLO", - decimals: 18, - contract: address!("0x0F81001eF0A83ecCE5ccebf63EB302c70a39a654"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54710/large/DOLO-small.png?1745398535"), -}; - -pub static DOVU: TokenInfo = TokenInfo { - name: "DOVU", - symbol: "DOVU", - decimals: 8, - contract: address!("0x2aeAbde1aB736c59E9A19BeD67681869eEF39526"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/31930/large/Dovu_Icon_Black_%281%29.png?1696530738"), -}; - -pub static DEFI_PULSE_INDEX: TokenInfo = TokenInfo { - name: "DeFi Pulse Index", - symbol: "DPI", - decimals: 18, - contract: address!("0x1494CA1F11D487c2bBe4543E90080AeBa4BA3C2b"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12465/thumb/defi_pulse_index_set.png?1600051053"), -}; - -pub static DREP: TokenInfo = TokenInfo { - name: "Drep", - symbol: "DREP", - decimals: 18, - contract: address!("0x3Ab6Ed69Ef663bd986Ee59205CCaD8A20F98b4c2"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14578/thumb/KotgsCgS_400x400.jpg?1617094445"), -}; - -pub static DERIVE: TokenInfo = TokenInfo { - name: "Derive", - symbol: "DRV", - decimals: 18, - contract: address!("0xB1D1eae60EEA9525032a6DCb4c1CE336a1dE71BE"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695"), -}; - -pub static DYDX: TokenInfo = TokenInfo { - name: "dYdX", - symbol: "DYDX", - decimals: 18, - contract: address!("0x92D6C1e31e14520e676a687F0a93788B716BEff5"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/17500/thumb/hjnIm9bV.jpg?1628009360"), -}; - -pub static DEFI_YIELD_PROTOCOL: TokenInfo = TokenInfo { - name: "DeFi Yield Protocol", - symbol: "DYP", - decimals: 18, - contract: address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066"), -}; - -pub static EIGENLAYER: TokenInfo = TokenInfo { - name: "EigenLayer", - symbol: "EIGEN", - decimals: 18, - contract: address!("0xec53bF9167f50cDEB3Ae105f56099aaaB9061F83"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/37441/large/eigen.jpg?1728023974"), -}; - -pub static ELASTOS: TokenInfo = TokenInfo { - name: "Elastos", - symbol: "ELA", - decimals: 18, - contract: address!("0xe6fd75ff38Adca4B97FBCD938c86b98772431867"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2780/thumb/Elastos.png?1597048112"), -}; - -pub static DOGELON_MARS: TokenInfo = TokenInfo { - name: "Dogelon Mars", - symbol: "ELON", - decimals: 18, - contract: address!("0x761D38e5ddf6ccf6Cf7c55759d5210750B5D60F3"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413"), -}; - -pub static ETHENA: TokenInfo = TokenInfo { - name: "Ethena", - symbol: "ENA", - decimals: 18, - contract: address!("0x57e114B691Db790C35207b2e685D4A43181e6061"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/36530/standard/ethena.png"), -}; - -pub static ENJIN_COIN: TokenInfo = TokenInfo { - name: "Enjin Coin", - symbol: "ENJ", - decimals: 18, - contract: address!("0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1102/thumb/enjin-coin-logo.png?1547035078"), -}; - -pub static ETHEREUM_NAME_SERVICE: TokenInfo = TokenInfo { - name: "Ethereum Name Service", - symbol: "ENS", - decimals: 18, - contract: address!("0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140"), -}; - -pub static CALDERA: TokenInfo = TokenInfo { - name: "Caldera", - symbol: "ERA", - decimals: 18, - contract: address!("0xE2AD0BF751834f2fbdC62A41014f84d67cA1de2A"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54475/large/Token_Logo.png?1749676251"), -}; - -pub static ETHERNITY_CHAIN: TokenInfo = TokenInfo { - name: "Ethernity Chain", - symbol: "ERN", - decimals: 18, - contract: address!("0xBBc2AE13b23d715c30720F079fcd9B4a74093505"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14238/thumb/LOGO_HIGH_QUALITY.png?1647831402"), -}; - -pub static ESPRESSO: TokenInfo = TokenInfo { - name: "Espresso", - symbol: "ESP", - decimals: 18, - contract: address!("0x031De51F3E8016514Bd0963d0B2AB825A591Db9A"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/67626/large/espresso.jpg?1753324525"), -}; - -pub static ETHER_FI: TokenInfo = TokenInfo { - name: "Ether.fi", - symbol: "ETHFI", - decimals: 18, - contract: address!("0xFe0c30065B384F05761f15d0CC899D4F9F9Cc0eB"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/35958/standard/etherfi.jpeg"), -}; - -pub static EULER: TokenInfo = TokenInfo { - name: "Euler", - symbol: "EUL", - decimals: 18, - contract: address!("0xd9Fcd98c322942075A5C3860693e9f4f03AAE07b"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/26149/thumb/YCvKDfl8_400x400.jpeg?1656041509"), -}; - -pub static EURO_COIN: TokenInfo = TokenInfo { - name: "Euro Coin", - symbol: "EURC", - decimals: 6, - contract: address!("0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420"), -}; - -pub static SCHUMAN_EUR_P: TokenInfo = TokenInfo { - name: "Schuman EUR P", - symbol: "EUROP", - decimals: 6, - contract: address!("0x888883b5F5D21fb10Dfeb70e8f9722B9FB0E5E51"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/52132/large/europ-symbol-rgb.jpg?1732634862"), -}; - -pub static QUANTOZ_EURQ: TokenInfo = TokenInfo { - name: "Quantoz EURQ", - symbol: "EURQ", - decimals: 6, - contract: address!("0x8dF723295214Ea6f21026eeEb4382d475f146F9f"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/51853/large/EURQ_1000px_Color.png?1732071269"), -}; - -pub static STABLR_EURO: TokenInfo = TokenInfo { - name: "StablR Euro", - symbol: "EURR", - decimals: 6, - contract: address!("0x50753CfAf86c094925Bf976f218D043f8791e408"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/53720/large/stablreuro-logo.png?1737125898"), -}; - -pub static HARVEST_FINANCE: TokenInfo = TokenInfo { - name: "Harvest Finance", - symbol: "FARM", - decimals: 18, - contract: address!("0xa0246c9032bC3A600820415aE600c6388619A14D"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180"), -}; - -pub static FETCH_AI: TokenInfo = TokenInfo { - name: "Fetch ai", - symbol: "FET", - decimals: 18, - contract: address!("0xaea46A60368A7bD060eec7DF8CBa43b7EF41Ad85"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136"), -}; - -pub static FIDELITY_DIGITAL_DOLLAR: TokenInfo = TokenInfo { - name: "Fidelity Digital Dollar", - symbol: "FIDD", - decimals: 18, - contract: address!("0x7C135549504245B5eAe64fc0E99Fa5ebabb8e35D"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/102171776/large/FIDD-Green_%28792px%29.png?1769612802"), -}; - -pub static STAFI: TokenInfo = TokenInfo { - name: "Stafi", - symbol: "FIS", - decimals: 18, - contract: address!("0xef3A930e1FfFFAcd2fc13434aC81bD278B0ecC8d"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991"), -}; - -pub static FLOKI: TokenInfo = TokenInfo { - name: "FLOKI", - symbol: "FLOKI", - decimals: 9, - contract: address!("0xcf0C122c6b73ff809C693DB761e7BaeBe62b6a2E"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318"), -}; - -pub static FLUX: TokenInfo = TokenInfo { - name: "Flux", - symbol: "FLUX", - decimals: 18, - contract: address!("0x720CD16b011b987Da3518fbf38c3071d4F0D1495"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x720CD16b011b987Da3518fbf38c3071d4F0D1495/logo.png"), -}; - -pub static FORTA: TokenInfo = TokenInfo { - name: "Forta", - symbol: "FORT", - decimals: 18, - contract: address!("0x41545f8b9472D758bB669ed8EaEEEcD7a9C4Ec29"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/25060/thumb/Forta_lgo_%281%29.png?1655353696"), -}; - -pub static AMPLEFORTH_GOVERNANCE_TOKEN: TokenInfo = TokenInfo { - name: "Ampleforth Governance Token", - symbol: "FORTH", - decimals: 18, - contract: address!("0x77FbA179C79De5B7653F68b5039Af940AdA60ce0"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14917/thumb/photo_2021-04-22_00.00.03.jpeg?1619020835"), -}; - -pub static SHAPESHIFT_FOX_TOKEN: TokenInfo = TokenInfo { - name: "ShapeShift FOX Token", - symbol: "FOX", - decimals: 18, - contract: address!("0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622"), -}; - -pub static FRAX: TokenInfo = TokenInfo { - name: "Frax", - symbol: "FRAX", - decimals: 18, - contract: address!("0x853d955aCEf822Db058eb8505911ED77F175b99e"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), -}; - -pub static FANTOM: TokenInfo = TokenInfo { - name: "Fantom", - symbol: "FTM", - decimals: 18, - contract: address!("0x4E15361FD6b4BB609Fa63C81A2be19d873717870"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016"), -}; - -pub static FUNCTION_X: TokenInfo = TokenInfo { - name: "Function X", - symbol: "FX", - decimals: 18, - contract: address!("0x8c15Ef5b4B21951d50E53E4fbdA8298FFAD25057"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/8186/thumb/47271330_590071468072434_707260356350705664_n.jpg?1556096683"), -}; - -pub static FRAX_SHARE: TokenInfo = TokenInfo { - name: "Frax Share", - symbol: "FXS", - decimals: 18, - contract: address!("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), -}; - -pub static GRAVITY: TokenInfo = TokenInfo { - name: "Gravity", - symbol: "G", - decimals: 18, - contract: address!("0x9C7BEBa8F6eF6643aBd725e45a4E8387eF260649"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/39200/large/gravity.jpg?1721020647"), -}; - -pub static GALXE: TokenInfo = TokenInfo { - name: "Galxe", - symbol: "GAL", - decimals: 18, - contract: address!("0x5fAa989Af96Af85384b8a938c2EdE4A7378D9875"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533"), -}; - -pub static GALA: TokenInfo = TokenInfo { - name: "GALA", - symbol: "GALA", - decimals: 8, - contract: address!("0xd1d2Eb1B1e90B638588728b4130137D262C87cae"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12493/standard/GALA-COINGECKO.png?1696512310"), -}; - -pub static GOLDFINCH: TokenInfo = TokenInfo { - name: "Goldfinch", - symbol: "GFI", - decimals: 18, - contract: address!("0xdab396cCF3d84Cf2D07C4454e10C8A6F5b008D2b"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/19081/thumb/GOLDFINCH.png?1634369662"), -}; - -pub static AAVEGOTCHI: TokenInfo = TokenInfo { - name: "Aavegotchi", - symbol: "GHST", - decimals: 18, - contract: address!("0x3F382DbD960E3a9bbCeaE22651E88158d2791550"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12467/thumb/ghst_200.png?1600750321"), -}; - -pub static GOLEM: TokenInfo = TokenInfo { - name: "Golem", - symbol: "GLM", - decimals: 18, - contract: address!("0x7DD9c5Cba05E151C895FDe1CF355C9A1D5DA6429"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/542/thumb/Golem_Submark_Positive_RGB.png?1606392013"), -}; - -pub static GNOSIS_TOKEN: TokenInfo = TokenInfo { - name: "Gnosis Token", - symbol: "GNO", - decimals: 18, - contract: address!("0x6810e776880C02933D47DB1b9fc05908e5386b96"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png"), -}; - -pub static GODS_UNCHAINED: TokenInfo = TokenInfo { - name: "Gods Unchained", - symbol: "GODS", - decimals: 18, - contract: address!("0xccC8cb5229B0ac8069C51fd58367Fd1e622aFD97"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/17139/thumb/10631.png?1635718182"), -}; - -pub static THE_GRAPH: TokenInfo = TokenInfo { - name: "The Graph", - symbol: "GRT", - decimals: 18, - contract: address!("0xc944E90C64B2c07662A292be6244BDf05Cda44a7"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566"), -}; - -pub static GITCOIN: TokenInfo = TokenInfo { - name: "Gitcoin", - symbol: "GTC", - decimals: 18, - contract: address!("0xDe30da39c46104798bB5aA3fe8B9e0e1F348163F"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929"), -}; - -pub static GEMINI_DOLLAR: TokenInfo = TokenInfo { - name: "Gemini Dollar", - symbol: "GUSD", - decimals: 2, - contract: address!("0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/5992/thumb/gemini-dollar-gusd.png?1536745278"), -}; - -pub static ETHGAS: TokenInfo = TokenInfo { - name: "ETHGas", - symbol: "GWEI", - decimals: 18, - contract: address!("0x2798b1cC5A993085E8A9D46e80499F1B63f42204"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/71375/large/ethgas_token_200.png?1769055039"), -}; - -pub static GYEN: TokenInfo = TokenInfo { - name: "GYEN", - symbol: "GYEN", - decimals: 6, - contract: address!("0xC08512927D12348F6620a698105e1BAac6EcD911"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343"), -}; - -pub static HASHFLOW: TokenInfo = TokenInfo { - name: "Hashflow", - symbol: "HFT", - decimals: 18, - contract: address!("0xb3999F658C0391d94A37f7FF328F3feC942BcADC"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/26136/large/hashflow-icon-cmc.png"), -}; - -pub static HIGHSTREET: TokenInfo = TokenInfo { - name: "Highstreet", - symbol: "HIGH", - decimals: 18, - contract: address!("0x71Ab77b7dbB4fa7e017BC15090b2163221420282"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470"), -}; - -pub static HOPR: TokenInfo = TokenInfo { - name: "HOPR", - symbol: "HOPR", - decimals: 18, - contract: address!("0xF5581dFeFD8Fb0e4aeC526bE659CFaB1f8c781dA"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14061/thumb/Shared_HOPR_logo_512px.png?1614073468"), -}; - -pub static IDEX: TokenInfo = TokenInfo { - name: "IDEX", - symbol: "IDEX", - decimals: 18, - contract: address!("0xB705268213D593B8FD88d3FDEFF93AFF5CbDcfAE"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2565/thumb/logomark-purple-286x286.png?1638362736"), -}; - -pub static ILLUVIUM: TokenInfo = TokenInfo { - name: "Illuvium", - symbol: "ILV", - decimals: 18, - contract: address!("0x767FE9EDC9E0dF98E07454847909b5E959D7ca0E"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14468/large/ILV.JPG"), -}; - -pub static IMMUNEFI: TokenInfo = TokenInfo { - name: "ImmuneFi", - symbol: "IMU", - decimals: 18, - contract: address!("0xb48c6B24f36307c7A1f2a9281E978a9ef2902BA5"), - chain: 1, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/39429.png"), -}; - -pub static IMMUTABLE_X: TokenInfo = TokenInfo { - name: "Immutable X", - symbol: "IMX", - decimals: 18, - contract: address!("0xF57e7e7C23978C3cAEC3C3548E3D615c346e79fF"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/17233/thumb/imx.png?1636691817"), -}; - -pub static INDEX_COOPERATIVE: TokenInfo = TokenInfo { - name: "Index Cooperative", - symbol: "INDEX", - decimals: 18, - contract: address!("0x0954906da0Bf32d5479e25f46056d22f08464cab"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12729/thumb/index.png?1634894321"), -}; - -pub static INJECTIVE: TokenInfo = TokenInfo { - name: "Injective", - symbol: "INJ", - decimals: 18, - contract: address!("0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237"), -}; - -pub static INVERSE_FINANCE: TokenInfo = TokenInfo { - name: "Inverse Finance", - symbol: "INV", - decimals: 18, - contract: address!("0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14205/thumb/inverse_finance.jpg?1614921871"), -}; - -pub static INFINEX: TokenInfo = TokenInfo { - name: "Infinex", - symbol: "INX", - decimals: 18, - contract: address!("0xdeF1b2D939EdC0E4d35806c59b3166F790175afe"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/70868/large/infinex.png?1764322875"), -}; - -pub static IOTEX: TokenInfo = TokenInfo { - name: "IoTeX", - symbol: "IOTX", - decimals: 18, - contract: address!("0x6fB3e0A217407EFFf7Ca062D46c26E5d60a14d69"), - chain: 1, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/2777.png"), -}; - -pub static IRYS: TokenInfo = TokenInfo { - name: "Irys", - symbol: "IRYS", - decimals: 18, - contract: address!("0x50f41F589aFACa2EF41FDF590FE7b90cD26DEe64"), - chain: 1, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/38978.png"), -}; - -pub static GEOJAM: TokenInfo = TokenInfo { - name: "Geojam", - symbol: "JAM", - decimals: 18, - contract: address!("0x23894DC9da6c94ECb439911cAF7d337746575A72"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/24648/thumb/ey40AzBN_400x400.jpg?1648507272"), -}; - -pub static JASMYCOIN: TokenInfo = TokenInfo { - name: "JasmyCoin", - symbol: "JASMY", - decimals: 18, - contract: address!("0x7420B4b9a0110cdC71fB720908340C03F9Bc03EC"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13876/thumb/JASMY200x200.jpg?1612473259"), -}; - -pub static JUPITER: TokenInfo = TokenInfo { - name: "Jupiter", - symbol: "JUP", - decimals: 18, - contract: address!("0x4B1E80cAC91e2216EEb63e29B957eB91Ae9C2Be8"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/10351/thumb/logo512.png?1632480932"), -}; - -pub static KEEP_NETWORK: TokenInfo = TokenInfo { - name: "Keep Network", - symbol: "KEEP", - decimals: 18, - contract: address!("0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/3373/thumb/IuNzUb5b_400x400.jpg?1589526336"), -}; - -pub static KERNELDAO: TokenInfo = TokenInfo { - name: "KernelDAO", - symbol: "KERNEL", - decimals: 18, - contract: address!("0x3f80B1c54Ae920Be41a77f8B902259D48cf24cCf"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54326/large/Kernel_token_logo_2x.png?1739827205"), -}; - -pub static SELFKEY: TokenInfo = TokenInfo { - name: "SelfKey", - symbol: "KEY", - decimals: 18, - contract: address!("0x4CC19356f2D37338b9802aa8E8fc58B0373296E7"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2034/thumb/selfkey.png?1548608934"), -}; - -pub static KITE: TokenInfo = TokenInfo { - name: "Kite", - symbol: "KITE", - decimals: 18, - contract: address!("0x904567252D8F48555b7447c67dCA23F0372E16be"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/70426/large/KITE-ICON.png?1762328605"), -}; - -pub static KYBER_NETWORK_CRYSTAL: TokenInfo = TokenInfo { - name: "Kyber Network Crystal", - symbol: "KNC", - decimals: 18, - contract: address!("0xdd974D5C2e2928deA5F71b9825b8b646686BD200"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png"), -}; - -pub static KEEP3RV1: TokenInfo = TokenInfo { - name: "Keep3rV1", - symbol: "KP3R", - decimals: 18, - contract: address!("0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12966/thumb/kp3r_logo.jpg?1607057458"), -}; - -pub static KRYLL: TokenInfo = TokenInfo { - name: "KRYLL", - symbol: "KRL", - decimals: 18, - contract: address!("0x464eBE77c293E473B48cFe96dDCf88fcF7bFDAC0"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979"), -}; - -pub static KUJIRA: TokenInfo = TokenInfo { - name: "Kujira", - symbol: "KUJI", - decimals: 6, - contract: address!("0x96543ef8d2C75C26387c1a319ae69c0BEE6f3fe7"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png"), -}; - -pub static LAYER3: TokenInfo = TokenInfo { - name: "Layer3", - symbol: "L3", - decimals: 18, - contract: address!("0x88909D489678dD17aA6D9609F89B0419Bf78FD9a"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/37768/large/Square.png"), -}; - -pub static LAGRANGE: TokenInfo = TokenInfo { - name: "Lagrange", - symbol: "LA", - decimals: 18, - contract: address!("0x0fc2a55d5BD13033f1ee0cdd11f60F7eFe66f467"), - chain: 1, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/36510.png"), -}; - -pub static LCX: TokenInfo = TokenInfo { - name: "LCX", - symbol: "LCX", - decimals: 18, - contract: address!("0x037A54AaB062628C9Bbae1FDB1583c195585fe41"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/9985/thumb/zRPSu_0o_400x400.jpg?1574327008"), -}; - -pub static LIDO_DAO: TokenInfo = TokenInfo { - name: "Lido DAO", - symbol: "LDO", - decimals: 18, - contract: address!("0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644"), -}; - -pub static LINEA: TokenInfo = TokenInfo { - name: "Linea", - symbol: "LINEA", - decimals: 18, - contract: address!("0x1789e0043623282D5DCc7F213d703C6D8BAfBB04"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/68507/large/linea-logo.jpeg?1756025484"), -}; - -pub static CHAINLINK_TOKEN: TokenInfo = TokenInfo { - name: "ChainLink Token", - symbol: "LINK", - decimals: 18, - contract: address!("0x514910771AF9Ca656af840dff83E8264EcF986CA"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), -}; - -pub static LITENTRY: TokenInfo = TokenInfo { - name: "Litentry", - symbol: "LIT", - decimals: 18, - contract: address!("0xb59490aB09A0f526Cc7305822aC65f2Ab12f9723"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13825/large/logo_200x200.png"), -}; - -pub static LIGHTER: TokenInfo = TokenInfo { - name: "Lighter", - symbol: "LIT", - decimals: 18, - contract: address!("0x232CE3bd40fCd6f80f3d55A522d03f25Df784Ee2"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/71121/large/lighter.png?1765888098"), -}; - -pub static LEAGUE_OF_KINGDOMS: TokenInfo = TokenInfo { - name: "League of Kingdoms", - symbol: "LOKA", - decimals: 18, - contract: address!("0x61E90A50137E1F645c9eF4a0d3A4f01477738406"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/22572/thumb/loka_64pix.png?1642643271"), -}; - -pub static LOOM_NETWORK: TokenInfo = TokenInfo { - name: "Loom Network", - symbol: "LOOM", - decimals: 18, - contract: address!("0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0/logo.png"), -}; - -pub static LIVEPEER: TokenInfo = TokenInfo { - name: "Livepeer", - symbol: "LPT", - decimals: 18, - contract: address!("0x58b6A8A3302369DAEc383334672404Ee733aB239"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/7137/thumb/logo-circle-green.png?1619593365"), -}; - -pub static LIQUITY: TokenInfo = TokenInfo { - name: "Liquity", - symbol: "LQTY", - decimals: 18, - contract: address!("0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180"), -}; - -pub static LOOPRINGCOIN_V2: TokenInfo = TokenInfo { - name: "LoopringCoin V2", - symbol: "LRC", - decimals: 18, - contract: address!("0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png"), -}; - -pub static BLOCKLORDS: TokenInfo = TokenInfo { - name: "BLOCKLORDS", - symbol: "LRDS", - decimals: 18, - contract: address!("0xd0a6053f087E87a25dC60701ba6E663b1a548E85"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/34775/standard/LRDS_PNG.png"), -}; - -pub static LIQUID_STAKED_ETH: TokenInfo = TokenInfo { - name: "Liquid Staked ETH", - symbol: "LSETH", - decimals: 18, - contract: address!("0x8c1BEd5b9a0928467c9B1341Da1D7BD5e10b6549"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/28848/large/LsETH-receipt-token-circle.png?1696527824"), -}; - -pub static LISK: TokenInfo = TokenInfo { - name: "Lisk", - symbol: "LSK", - decimals: 18, - contract: address!("0x6033F7f88332B8db6ad452B7C6D5bB643990aE3f"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/385/large/Lisk_logo.png?1722338450"), -}; - -pub static LIQUITY_USD: TokenInfo = TokenInfo { - name: "Liquity USD", - symbol: "LUSD", - decimals: 18, - contract: address!("0x5f98805A4E8be255a32880FDeC7F6728C6568bA0"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327"), -}; - -pub static DECENTRALAND: TokenInfo = TokenInfo { - name: "Decentraland", - symbol: "MANA", - decimals: 18, - contract: address!("0x0F5D2fB29fb7d3CFeE444a200298f468908cC942"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745"), -}; - -pub static MASK_NETWORK: TokenInfo = TokenInfo { - name: "Mask Network", - symbol: "MASK", - decimals: 18, - contract: address!("0x69af81e73A73B40adF4f3d4223Cd9b1ECE623074"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316"), -}; - -pub static MATH: TokenInfo = TokenInfo { - name: "MATH", - symbol: "MATH", - decimals: 18, - contract: address!("0x08d967bb0134F2d07f7cfb6E246680c53927DD30"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590"), -}; - -pub static POLYGON: TokenInfo = TokenInfo { - name: "Polygon", - symbol: "MATIC", - decimals: 18, - contract: address!("0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), -}; - -pub static MERIT_CIRCLE: TokenInfo = TokenInfo { - name: "Merit Circle", - symbol: "MC", - decimals: 18, - contract: address!("0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/19304/thumb/Db4XqML.png?1634972154"), -}; - -pub static MOSS_CARBON_CREDIT: TokenInfo = TokenInfo { - name: "Moss Carbon Credit", - symbol: "MCO2", - decimals: 18, - contract: address!("0xfC98e825A2264D890F9a1e68ed50E1526abCcacD"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14414/thumb/ENtxnThA_400x400.jpg?1615948522"), -}; - -pub static MEASURABLE_DATA_TOKEN: TokenInfo = TokenInfo { - name: "Measurable Data Token", - symbol: "MDT", - decimals: 18, - contract: address!("0x814e0908b12A99FeCf5BC101bB5d0b8B5cDf7d26"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2441/thumb/mdt_logo.png?1569813574"), -}; - -pub static MEMECOIN: TokenInfo = TokenInfo { - name: "Memecoin", - symbol: "MEME", - decimals: 18, - contract: address!("0xb131f4A55907B10d1F0A50d8ab8FA09EC342cd74"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/32528/large/memecoin_(2).png"), -}; - -pub static METIS: TokenInfo = TokenInfo { - name: "Metis", - symbol: "METIS", - decimals: 18, - contract: address!("0x9E32b13ce7f2E80A01932B42553652E053D6ed8e"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312"), -}; - -pub static MAGIC_INTERNET_MONEY: TokenInfo = TokenInfo { - name: "Magic Internet Money", - symbol: "MIM", - decimals: 18, - contract: address!("0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612"), -}; - -pub static MIRROR_PROTOCOL: TokenInfo = TokenInfo { - name: "Mirror Protocol", - symbol: "MIR", - decimals: 18, - contract: address!("0x09a3EcAFa817268f77BE1283176B946C4ff2E608"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13295/thumb/mirror_logo_transparent.png?1611554658"), -}; - -pub static MAKER: TokenInfo = TokenInfo { - name: "Maker", - symbol: "MKR", - decimals: 18, - contract: address!("0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png"), -}; - -pub static MELON: TokenInfo = TokenInfo { - name: "Melon", - symbol: "MLN", - decimals: 18, - contract: address!("0xec67005c4E498Ec7f55E092bd1d35cbC47C91892"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295"), -}; - -pub static MANTLE: TokenInfo = TokenInfo { - name: "Mantle", - symbol: "MNT", - decimals: 18, - contract: address!("0x3c3a81e81dc49A522A592e7622A7E711c06bf354"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/30980/large/Mantle-Logo-mark.png?1739213200"), -}; - -pub static MOG_COIN: TokenInfo = TokenInfo { - name: "Mog Coin", - symbol: "MOG", - decimals: 18, - contract: address!("0xaaeE1A9723aaDB7afA2810263653A34bA2C21C7a"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/31059/large/MOG_LOGO_200x200.png"), -}; - -pub static MONAVALE: TokenInfo = TokenInfo { - name: "Monavale", - symbol: "MONA", - decimals: 18, - contract: address!("0x275f5Ad03be0Fa221B4C6649B8AeE09a42D9412A"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13298/thumb/monavale_logo.jpg?1607232721"), -}; - -pub static MORPHO_TOKEN: TokenInfo = TokenInfo { - name: "Morpho Token", - symbol: "MORPHO", - decimals: 18, - contract: address!("0x58D97B57BB95320F9a05dC918Aef65434969c2B2"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/29837/large/Morpho-token-icon.png?1726771230"), -}; - -pub static MOVEMENT: TokenInfo = TokenInfo { - name: "Movement", - symbol: "MOVE", - decimals: 8, - contract: address!("0x3073f7aAA4DB83f95e9FFf17424F71D4751a3073"), - chain: 1, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/32452.png"), -}; - -pub static MAPLE: TokenInfo = TokenInfo { - name: "Maple", - symbol: "MPL", - decimals: 18, - contract: address!("0x33349B282065b0284d756F0577FB39c158F935e6"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14097/thumb/photo_2021-05-03_14.20.41.jpeg?1620022863"), -}; - -pub static METAL: TokenInfo = TokenInfo { - name: "Metal", - symbol: "MTL", - decimals: 8, - contract: address!("0xF433089366899D83a9f26A773D59ec7eCF30355e"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/763/thumb/Metal.png?1592195010"), -}; - -pub static MULTICHAIN: TokenInfo = TokenInfo { - name: "Multichain", - symbol: "MULTI", - decimals: 18, - contract: address!("0x65Ef703f5594D2573eb71Aaf55BC0CB548492df4"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238"), -}; - -pub static MSTABLE_USD: TokenInfo = TokenInfo { - name: "mStable USD", - symbol: "MUSD", - decimals: 18, - contract: address!("0xe2f2a5C287993345a840Db3B0845fbC70f5935a5"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11576/thumb/mStable_USD.png?1595591803"), -}; - -pub static MUSE_DAO: TokenInfo = TokenInfo { - name: "Muse DAO", - symbol: "MUSE", - decimals: 18, - contract: address!("0xB6Ca7399B4F9CA56FC27cBfF44F4d2e4Eef1fc81"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13230/thumb/muse_logo.png?1606460453"), -}; - -pub static GENSOKISHI_METAVERSE: TokenInfo = TokenInfo { - name: "GensoKishi Metaverse", - symbol: "MV", - decimals: 18, - contract: address!("0xAE788F80F2756A86aa2F410C651F2aF83639B95b"), - chain: 1, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/17704.png"), -}; - -pub static MXC: TokenInfo = TokenInfo { - name: "MXC", - symbol: "MXC", - decimals: 18, - contract: address!("0x5Ca381bBfb58f0092df149bD3D243b08B9a8386e"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/4604/thumb/mxc.png?1655534336"), -}; - -pub static POLYSWARM: TokenInfo = TokenInfo { - name: "PolySwarm", - symbol: "NCT", - decimals: 18, - contract: address!("0x9E46A38F5DaaBe8683E10793b06749EEF7D733d1"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2843/thumb/ImcYCVfX_400x400.jpg?1628519767"), -}; - -pub static NEIRO: TokenInfo = TokenInfo { - name: "Neiro", - symbol: "Neiro", - decimals: 9, - contract: address!("0x812Ba41e071C7b7fA4EBcFB62dF5F45f6fA853Ee"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/39488/large/neiro.jpg?1731449567"), -}; - -pub static NEWTON: TokenInfo = TokenInfo { - name: "Newton", - symbol: "NEWT", - decimals: 18, - contract: address!("0xD0eC028a3D21533Fdd200838F39c85B03679285D"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/66819/large/newton.jpg?1750642513"), -}; - -pub static NKN: TokenInfo = TokenInfo { - name: "NKN", - symbol: "NKN", - decimals: 18, - contract: address!("0x5Cf04716BA20127F1E2297AdDCf4B5035000c9eb"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/3375/thumb/nkn.png?1548329212"), -}; - -pub static NUMERAIRE: TokenInfo = TokenInfo { - name: "Numeraire", - symbol: "NMR", - decimals: 18, - contract: address!("0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png"), -}; - -pub static NOMINA: TokenInfo = TokenInfo { - name: "Nomina", - symbol: "NOM", - decimals: 18, - contract: address!("0x6e6F6d696e61decd6605bD4a57836c5DB6923340"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/69687/large/nomina_400x400.jpg?1759312531"), -}; - -pub static NUCYPHER: TokenInfo = TokenInfo { - name: "NuCypher", - symbol: "NU", - decimals: 18, - contract: address!("0x4fE83213D56308330EC302a8BD641f1d0113A4Cc"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/3318/thumb/photo1198982838879365035.jpg?1547037916"), -}; - -pub static OCEAN_PROTOCOL: TokenInfo = TokenInfo { - name: "Ocean Protocol", - symbol: "OCEAN", - decimals: 18, - contract: address!("0x967da4048cD07aB37855c090aAF366e4ce1b9F48"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686"), -}; - -pub static ORIGIN_PROTOCOL: TokenInfo = TokenInfo { - name: "Origin Protocol", - symbol: "OGN", - decimals: 18, - contract: address!("0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878"), -}; - -pub static OMG_NETWORK: TokenInfo = TokenInfo { - name: "OMG Network", - symbol: "OMG", - decimals: 18, - contract: address!("0xd26114cd6EE289AccF82350c8d8487fedB8A0C07"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/776/thumb/OMG_Network.jpg?1591167168"), -}; - -pub static OMNI_NETWORK: TokenInfo = TokenInfo { - name: "Omni Network", - symbol: "OMNI", - decimals: 18, - contract: address!("0x36E66fbBce51e4cD5bd3C62B637Eb411b18949D4"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/36465/standard/Symbol-Color.png?1711511095"), -}; - -pub static ONDO_FINANCE: TokenInfo = TokenInfo { - name: "Ondo Finance", - symbol: "ONDO", - decimals: 18, - contract: address!("0xfAbA6f8e4a5E8Ab82F62fe7C39859FA577269BE3"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/26580/standard/ONDO.png?1696525656"), -}; - -pub static ORCA_ALLIANCE: TokenInfo = TokenInfo { - name: "ORCA Alliance", - symbol: "ORCA", - decimals: 18, - contract: address!("0x6F59e0461Ae5E2799F1fB3847f05a63B16d0DbF8"), - chain: 1, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/5183.png"), -}; - -pub static ORION_PROTOCOL: TokenInfo = TokenInfo { - name: "Orion Protocol", - symbol: "ORN", - decimals: 8, - contract: address!("0x0258F474786DdFd37ABCE6df6BBb1Dd5dfC4434a"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11841/thumb/orion_logo.png?1594943318"), -}; - -pub static ORCHID: TokenInfo = TokenInfo { - name: "Orchid", - symbol: "OXT", - decimals: 18, - contract: address!("0x4575f41308EC1483f3d399aa9a2826d74Da13Deb"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4575f41308EC1483f3d399aa9a2826d74Da13Deb/logo.png"), -}; - -pub static PAYPEREX: TokenInfo = TokenInfo { - name: "PayperEx", - symbol: "PAX", - decimals: 18, - contract: address!("0xc1D204d77861dEf49b6E769347a883B15EC397Ff"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1601/thumb/pax.png?1547035800"), -}; - -pub static PAX_GOLD: TokenInfo = TokenInfo { - name: "PAX Gold", - symbol: "PAXG", - decimals: 18, - contract: address!("0x45804880De22913dAFE09f4980848ECE6EcbAf78"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/9519/thumb/paxg.PNG?1568542565"), -}; - -pub static PLAYDAPP: TokenInfo = TokenInfo { - name: "PlayDapp", - symbol: "PDA", - decimals: 18, - contract: address!("0x0D3CbED3f69EE050668ADF3D9Ea57241cBa33A2B"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14316/standard/PDA-symbol.png?1710234068"), -}; - -pub static PENDLE: TokenInfo = TokenInfo { - name: "Pendle", - symbol: "PENDLE", - decimals: 18, - contract: address!("0x808507121B80c02388fAd14726482e061B8da827"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728"), -}; - -pub static PEPE: TokenInfo = TokenInfo { - name: "Pepe", - symbol: "PEPE", - decimals: 18, - contract: address!("0x6982508145454Ce325dDbE47a25d4ec3d2311933"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725"), -}; - -pub static PERPETUAL_PROTOCOL: TokenInfo = TokenInfo { - name: "Perpetual Protocol", - symbol: "PERP", - decimals: 18, - contract: address!("0xbC396689893D065F41bc2C6EcbeE5e0085233447"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), -}; - -pub static PIRATE_NATION: TokenInfo = TokenInfo { - name: "Pirate Nation", - symbol: "PIRATE", - decimals: 18, - contract: address!("0x7613C48E0cd50E42dD9Bf0f6c235063145f6f8DC"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/38524/standard/_Pirate_Transparent_200x200.png"), -}; - -pub static PLUTON: TokenInfo = TokenInfo { - name: "Pluton", - symbol: "PLU", - decimals: 18, - contract: address!("0xD8912C10681D8B21Fd3742244f44658dBA12264E"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1241/thumb/pluton.png?1548331624"), -}; - -pub static PLUME: TokenInfo = TokenInfo { - name: "Plume", - symbol: "PLUME", - decimals: 18, - contract: address!("0x4C1746A800D224393fE2470C70A35717eD4eA5F1"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/53623/large/plume-token.png?1736896935"), -}; - -pub static POLYGON_ECOSYSTEM_TOKEN: TokenInfo = TokenInfo { - name: "Polygon Ecosystem Token", - symbol: "POL", - decimals: 18, - contract: address!("0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/32440/large/polygon.png?1698233684"), -}; - -pub static POLKASTARTER: TokenInfo = TokenInfo { - name: "Polkastarter", - symbol: "POLS", - decimals: 18, - contract: address!("0x83e6f1E41cdd28eAcEB20Cb649155049Fac3D5Aa"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702"), -}; - -pub static POLYMATH: TokenInfo = TokenInfo { - name: "Polymath", - symbol: "POLY", - decimals: 18, - contract: address!("0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034"), -}; - -pub static MARLIN: TokenInfo = TokenInfo { - name: "Marlin", - symbol: "POND", - decimals: 18, - contract: address!("0x57B946008913B82E4dF85f501cbAeD910e58D26C"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/8903/thumb/POND_200x200.png?1622515451"), -}; - -pub static PORTAL: TokenInfo = TokenInfo { - name: "Portal", - symbol: "PORTAL", - decimals: 18, - contract: address!("0x1Bbe973BeF3a977Fc51CbED703E8ffDEfE001Fed"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/35436/standard/portal.jpeg"), -}; - -pub static POWER_LEDGER: TokenInfo = TokenInfo { - name: "Power Ledger", - symbol: "POWR", - decimals: 6, - contract: address!("0x595832F8FC6BF59c85C527fEC3740A1b7a361269"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1104/thumb/power-ledger.png?1547035082"), -}; - -pub static PRIME: TokenInfo = TokenInfo { - name: "Prime", - symbol: "PRIME", - decimals: 18, - contract: address!("0xb23d80f5FefcDDaa212212F028021B41DEd428CF"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222"), -}; - -pub static PROPY: TokenInfo = TokenInfo { - name: "Propy", - symbol: "PRO", - decimals: 8, - contract: address!("0x226bb599a12C826476e3A771454697EA52E9E220"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/869/thumb/propy.png?1548332100"), -}; - -pub static SUCCINCT: TokenInfo = TokenInfo { - name: "Succinct", - symbol: "PROVE", - decimals: 18, - contract: address!("0x6BEF15D938d4E72056AC92Ea4bDD0D76B1C4ad29"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/67905/large/succinct-logo.png?1754228574"), -}; - -pub static PARSIQ: TokenInfo = TokenInfo { - name: "PARSIQ", - symbol: "PRQ", - decimals: 18, - contract: address!("0x362bc847A3a9637d3af6624EeC853618a43ed7D2"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280"), -}; - -pub static PSTAKE_FINANCE: TokenInfo = TokenInfo { - name: "pSTAKE Finance", - symbol: "PSTAKE", - decimals: 18, - contract: address!("0xfB5c6815cA3AC72Ce9F5006869AE67f18bF77006"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/23931/thumb/PSTAKE_Dark.png?1645709930"), -}; - -pub static PUFFER_FINANCE: TokenInfo = TokenInfo { - name: "Puffer Finance", - symbol: "PUFFER", - decimals: 18, - contract: address!("0x4d1C297d39C5c1277964D0E3f8Aa901493664530"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/50630/large/puffer.jpg?1728545297"), -}; - -pub static PAYPAL_USD: TokenInfo = TokenInfo { - name: "PayPal USD", - symbol: "PYUSD", - decimals: 6, - contract: address!("0x6c3ea9036406852006290770BEdFcAbA0e23A0e8"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/31212/large/PYUSD_Logo_%282%29.png?1691458314"), -}; - -pub static QUANT: TokenInfo = TokenInfo { - name: "Quant", - symbol: "QNT", - decimals: 18, - contract: address!("0x4a220E6096B25EADb88358cb44068A3248254675"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/3370/thumb/5ZOu7brX_400x400.jpg?1612437252"), -}; - -pub static QREDO: TokenInfo = TokenInfo { - name: "Qredo", - symbol: "QRDO", - decimals: 8, - contract: address!("0x4123a133ae3c521FD134D7b13A2dEC35b56c2463"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/17541/thumb/qrdo.png?1630637735"), -}; - -pub static QUANTSTAMP: TokenInfo = TokenInfo { - name: "Quantstamp", - symbol: "QSP", - decimals: 18, - contract: address!("0x99ea4dB9EE77ACD40B119BD1dC4E33e1C070b80d"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1219/thumb/0_E0kZjb4dG4hUnoDD_.png?1604815917"), -}; - -pub static QUICKSWAP: TokenInfo = TokenInfo { - name: "Quickswap", - symbol: "QUICK", - decimals: 18, - contract: address!("0x6c28AeF8977c9B773996d0e8376d2EE379446F2f"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13970/thumb/1_pOU6pBMEmiL-ZJVb0CYRjQ.png?1613386659"), -}; - -pub static RADICLE: TokenInfo = TokenInfo { - name: "Radicle", - symbol: "RAD", - decimals: 18, - contract: address!("0x31c8EAcBFFdD875c74b94b077895Bd78CF1E64A3"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14013/thumb/radicle.png?1614402918"), -}; - -pub static RAI_REFLEX_INDEX: TokenInfo = TokenInfo { - name: "Rai Reflex Index", - symbol: "RAI", - decimals: 18, - contract: address!("0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334"), -}; - -pub static SUPERRARE: TokenInfo = TokenInfo { - name: "SuperRare", - symbol: "RARE", - decimals: 18, - contract: address!("0xba5BDe662c17e2aDFF1075610382B9B691296350"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/17753/thumb/RARE.jpg?1629220534"), -}; - -pub static RARIBLE: TokenInfo = TokenInfo { - name: "Rarible", - symbol: "RARI", - decimals: 18, - contract: address!("0xFca59Cd816aB1eaD66534D82bc21E7515cE441CF"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11845/thumb/Rari.png?1594946953"), -}; - -pub static RUBIC: TokenInfo = TokenInfo { - name: "Rubic", - symbol: "RBC", - decimals: 18, - contract: address!("0xA4EED63db85311E22dF4473f87CcfC3DaDCFA3E3"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12629/thumb/200x200.png?1607952509"), -}; - -pub static RIBBON_FINANCE: TokenInfo = TokenInfo { - name: "Ribbon Finance", - symbol: "RBN", - decimals: 18, - contract: address!("0x6123B0049F904d730dB3C36a31167D9d4121fA6B"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/15823/thumb/RBN_64x64.png?1633529723"), -}; - -pub static REDSTONE: TokenInfo = TokenInfo { - name: "Redstone", - symbol: "RED", - decimals: 18, - contract: address!("0xc43C6bfeDA065fE2c4c11765Bf838789bd0BB5dE"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/53640/large/RedStone_Logo_New_White.png?1740640919"), -}; - -pub static REPUBLIC_TOKEN: TokenInfo = TokenInfo { - name: "Republic Token", - symbol: "REN", - decimals: 18, - contract: address!("0x408e41876cCCDC0F92210600ef50372656052a38"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png"), -}; - -pub static REPUTATION_AUGUR_V1: TokenInfo = TokenInfo { - name: "Reputation Augur v1", - symbol: "REP", - decimals: 18, - contract: address!("0x1985365e9f78359a9B6AD760e32412f4a445E862"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1985365e9f78359a9B6AD760e32412f4a445E862/logo.png"), -}; - -pub static REPUTATION_AUGUR_V2: TokenInfo = TokenInfo { - name: "Reputation Augur v2", - symbol: "REPv2", - decimals: 18, - contract: address!("0x221657776846890989a759BA2973e427DfF5C9bB"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x221657776846890989a759BA2973e427DfF5C9bB/logo.png"), -}; - -pub static REQUEST: TokenInfo = TokenInfo { - name: "Request", - symbol: "REQ", - decimals: 18, - contract: address!("0x8f8221aFbB33998d8584A2B05749bA73c37a938a"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1031/thumb/Request_icon_green.png?1643250951"), -}; - -pub static REVV: TokenInfo = TokenInfo { - name: "REVV", - symbol: "REVV", - decimals: 18, - contract: address!("0x557B933a7C2c45672B610F8954A3deB39a51A8Ca"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12373/thumb/REVV_TOKEN_Refined_2021_%281%29.png?1627652390"), -}; - -pub static RENZO: TokenInfo = TokenInfo { - name: "Renzo", - symbol: "REZ", - decimals: 18, - contract: address!("0x3B50805453023a91a8bf641e279401a0b23FA6F9"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/37327/standard/renzo_200x200.png?1714025012"), -}; - -pub static RARI_GOVERNANCE_TOKEN: TokenInfo = TokenInfo { - name: "Rari Governance Token", - symbol: "RGT", - decimals: 18, - contract: address!("0xD291E7a03283640FDc51b121aC401383A46cC623"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014"), -}; - -pub static IEXEC_RLC: TokenInfo = TokenInfo { - name: "iExec RLC", - symbol: "RLC", - decimals: 9, - contract: address!("0x607F4C5BB672230e8672085532f7e901544a7375"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1604543202"), -}; - -pub static RAYLS: TokenInfo = TokenInfo { - name: "Rayls", - symbol: "RLS", - decimals: 18, - contract: address!("0xB5F7b021a78f470d31D762C1DDA05ea549904fbd"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/70091/large/cgrLS.png?1760541265"), -}; - -pub static RLUSD: TokenInfo = TokenInfo { - name: "RLUSD", - symbol: "RLUSD", - decimals: 18, - contract: address!("0x8292Bb45bf1Ee4d140127049757C2E0fF06317eD"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/39651/large/RLUSD_200x200_(1).png?1727376633"), -}; - -pub static RALLY: TokenInfo = TokenInfo { - name: "Rally", - symbol: "RLY", - decimals: 18, - contract: address!("0xf1f955016EcbCd7321c7266BccFB96c68ea5E49b"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12843/thumb/image.png?1611212077"), -}; - -pub static RENDER_TOKEN: TokenInfo = TokenInfo { - name: "Render Token", - symbol: "RNDR", - decimals: 18, - contract: address!("0x6De037ef9aD2725EB40118Bb1702EBb27e4Aeb24"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11636/thumb/rndr.png?1638840934"), -}; - -pub static ROBO_TOKEN: TokenInfo = TokenInfo { - name: "ROBO Token", - symbol: "ROBO", - decimals: 18, - contract: address!("0x32b4d049fE4c888D2b92eEcaf729F44DF6B1F36E"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/102172005/large/ROBO.png?1770925648"), -}; - -pub static ROOK: TokenInfo = TokenInfo { - name: "Rook", - symbol: "ROOK", - decimals: 18, - contract: address!("0xfA5047c9c78B8877af97BDcb85Db743fD7313d4a"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13005/thumb/keeper_dao_logo.jpg?1604316506"), -}; - -pub static ROCKET_POOL_PROTOCOL: TokenInfo = TokenInfo { - name: "Rocket Pool Protocol", - symbol: "RPL", - decimals: 18, - contract: address!("0xD33526068D116cE69F19A9ee46F0bd304F21A51f"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/2090/large/rocket_pool_%28RPL%29.png?1696503058"), -}; - -pub static RESERVE_RIGHTS: TokenInfo = TokenInfo { - name: "Reserve Rights", - symbol: "RSR", - decimals: 18, - contract: address!("0x320623b8E4fF03373931769A31Fc52A4E78B5d70"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856"), -}; - -pub static SAFE: TokenInfo = TokenInfo { - name: "Safe", - symbol: "SAFE", - decimals: 18, - contract: address!("0x5aFE3855358E112B5647B952709E6165e1c1eEEe"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/27032/standard/Artboard_1_copy_8circle-1.png?1696526084"), -}; - -pub static THE_SANDBOX: TokenInfo = TokenInfo { - name: "The Sandbox", - symbol: "SAND", - decimals: 18, - contract: address!("0x3845badAde8e6dFF049820680d1F14bD3903a5d0"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1597397942"), -}; - -pub static STADER: TokenInfo = TokenInfo { - name: "Stader", - symbol: "SD", - decimals: 18, - contract: address!("0x30D20208d987713f46DFD34EF128Bb16C404D10f"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png"), -}; - -pub static SENTIENT: TokenInfo = TokenInfo { - name: "Sentient", - symbol: "SENT", - decimals: 18, - contract: address!("0x56A3BA04E95d34268A19b2a4474DC979baBDaf76"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/70508/large/SENTIENT-Icon-BlushForce-L.png?1762267532"), -}; - -pub static SHIBA_INU: TokenInfo = TokenInfo { - name: "Shiba Inu", - symbol: "SHIB", - decimals: 18, - contract: address!("0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11939/thumb/shiba.png?1622619446"), -}; - -pub static SHPING: TokenInfo = TokenInfo { - name: "Shping", - symbol: "SHPING", - decimals: 18, - contract: address!("0x7C84e62859D0715eb77d1b1C4154Ecd6aBB21BEC"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2588/thumb/r_yabKKi_400x400.jpg?1639470164"), -}; - -pub static SKALE: TokenInfo = TokenInfo { - name: "SKALE", - symbol: "SKL", - decimals: 18, - contract: address!("0x00c83aeCC790e8a4453e5dD3B0B4b3680501a7A7"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13245/thumb/SKALE_token_300x300.png?1606789574"), -}; - -pub static SKY_GOVERNANCE_TOKEN: TokenInfo = TokenInfo { - name: "SKY Governance Token", - symbol: "SKY", - decimals: 18, - contract: address!("0x56072C95FAA701256059aa122697B133aDEd9279"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/39925/large/sky.jpg?1724827980"), -}; - -pub static SMOOTH_LOVE_POTION: TokenInfo = TokenInfo { - name: "Smooth Love Potion", - symbol: "SLP", - decimals: 0, - contract: address!("0xCC8Fa225D80b9c7D42F96e9570156c65D6cAAa25"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/10366/thumb/SLP.png?1578640057"), -}; - -pub static STATUS: TokenInfo = TokenInfo { - name: "Status", - symbol: "SNT", - decimals: 18, - contract: address!("0x744d70FDBE2Ba4CF95131626614a1763DF805B9E"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778"), -}; - -pub static SYNTHETIX_NETWORK_TOKEN: TokenInfo = TokenInfo { - name: "Synthetix Network Token", - symbol: "SNX", - decimals: 18, - contract: address!("0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), -}; - -pub static UNISOCKS: TokenInfo = TokenInfo { - name: "Unisocks", - symbol: "SOCKS", - decimals: 18, - contract: address!("0x23B608675a2B2fB1890d3ABBd85c5775c51691d5"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/10717/thumb/qFrcoiM.png?1582525244"), -}; - -pub static SOL_WORMHOLE: TokenInfo = TokenInfo { - name: "SOL Wormhole ", - symbol: "SOL", - decimals: 9, - contract: address!("0xD31a59c85aE9D8edEFeC411D448f90841571b89c"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), -}; - -pub static SPELL_TOKEN: TokenInfo = TokenInfo { - name: "Spell Token", - symbol: "SPELL", - decimals: 18, - contract: address!("0x090185f2135308BaD17527004364eBcC2D37e5F6"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862"), -}; - -pub static SPARK: TokenInfo = TokenInfo { - name: "Spark", - symbol: "SPK", - decimals: 18, - contract: address!("0xc20059e0317DE91738d13af027DfC4a50781b066"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/38637/large/Spark-Logomark-RGB.png?1744878896"), -}; - -pub static SPX6900: TokenInfo = TokenInfo { - name: "SPX6900", - symbol: "SPX", - decimals: 8, - contract: address!("0xE0f63A424a4439cBE457D80E4f4b51aD25b2c56C"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083"), -}; - -pub static STARGATE_FINANCE: TokenInfo = TokenInfo { - name: "Stargate Finance", - symbol: "STG", - decimals: 18, - contract: address!("0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518"), -}; - -pub static STORJ_TOKEN: TokenInfo = TokenInfo { - name: "Storj Token", - symbol: "STORJ", - decimals: 8, - contract: address!("0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png"), -}; - -pub static STARKNET: TokenInfo = TokenInfo { - name: "Starknet", - symbol: "STRK", - decimals: 18, - contract: address!("0xCa14007Eff0dB1f8135f4C25B34De49AB0d42766"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/26433/standard/starknet.png?1696525507"), -}; - -pub static STOX: TokenInfo = TokenInfo { - name: "Stox", - symbol: "STX", - decimals: 18, - contract: address!("0x006BeA43Baa3f7A6f765F14f10A1a1b08334EF45"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1230/thumb/stox-token.png?1547035256"), -}; - -pub static SUKU: TokenInfo = TokenInfo { - name: "SUKU", - symbol: "SUKU", - decimals: 18, - contract: address!("0x0763fdCCF1aE541A5961815C0872A8c5Bc6DE4d7"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11969/thumb/UmfW5S6f_400x400.jpg?1596602238"), -}; - -pub static SUPERFARM: TokenInfo = TokenInfo { - name: "SuperFarm", - symbol: "SUPER", - decimals: 18, - contract: address!("0xe53EC727dbDEB9E2d5456c3be40cFF031AB40A55"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899"), -}; - -pub static SYNTH_SUSD: TokenInfo = TokenInfo { - name: "Synth sUSD", - symbol: "sUSD", - decimals: 18, - contract: address!("0x57Ab1ec28D129707052df4dF418D58a2D46d5f51"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765"), -}; - -pub static SUSHI: TokenInfo = TokenInfo { - name: "Sushi", - symbol: "SUSHI", - decimals: 18, - contract: address!("0x6B3595068778DD592e39A122f4f5a5cF09C90fE2"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), -}; - -pub static SWELL: TokenInfo = TokenInfo { - name: "Swell", - symbol: "SWELL", - decimals: 18, - contract: address!("0x0a6E7Ba5042B38349e437ec6Db6214AEC7B35676"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/28777/large/swell1.png?1727899715"), -}; - -pub static SWFTCOIN: TokenInfo = TokenInfo { - name: "SWFTCOIN", - symbol: "SWFTC", - decimals: 8, - contract: address!("0x0bb217E40F8a5Cb79Adf04E1aAb60E5abd0dfC1e"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2346/thumb/SWFTCoin.jpg?1618392022"), -}; - -pub static SWIPE: TokenInfo = TokenInfo { - name: "Swipe", - symbol: "SXP", - decimals: 18, - contract: address!("0x8CE9137d39326AD0cD6491fb5CC0CbA0e089b6A9"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/9368/thumb/swipe.png?1566792311"), -}; - -pub static SPACE_AND_TIME: TokenInfo = TokenInfo { - name: "Space and Time", - symbol: "SXT", - decimals: 18, - contract: address!("0xE6Bfd33F52d82Ccb5b37E16D3dD81f9FFDAbB195"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/55424/large/sxt-token_circle.jpg?1745935919"), -}; - -pub static SYLO: TokenInfo = TokenInfo { - name: "Sylo", - symbol: "SYLO", - decimals: 18, - contract: address!("0xf293d23BF2CDc05411Ca0edDD588eb1977e8dcd4"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/6430/thumb/SYLO.svg?1589527756"), -}; - -pub static SYNAPSE: TokenInfo = TokenInfo { - name: "Synapse", - symbol: "SYN", - decimals: 18, - contract: address!("0x0f2D719407FdBeFF09D87557AbB7232601FD9F29"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049"), -}; - -pub static SYRUP_TOKEN: TokenInfo = TokenInfo { - name: "Syrup Token", - symbol: "SYRUP", - decimals: 18, - contract: address!("0x643C4E15d7d62Ad0aBeC4a9BD4b001aA3Ef52d66"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/51232/standard/IMG_7420.png?1730831572"), -}; - -pub static THRESHOLD_NETWORK: TokenInfo = TokenInfo { - name: "Threshold Network", - symbol: "T", - decimals: 18, - contract: address!("0xCdF7028ceAB81fA0C6971208e83fa7872994beE5"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340"), -}; - -pub static TBTC: TokenInfo = TokenInfo { - name: "tBTC", - symbol: "tBTC", - decimals: 18, - contract: address!("0x18084fbA666a33d37592fA2633fD49a74DD93a88"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png"), -}; - -pub static TERM_FINANCE: TokenInfo = TokenInfo { - name: "Term Finance", - symbol: "TERM", - decimals: 18, - contract: address!("0xC3d21f79C3120A4fFda7A535f8005a7c297799bF"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/38142/large/terms.png?1716630303"), -}; - -pub static THEORIQ: TokenInfo = TokenInfo { - name: "Theoriq", - symbol: "THQ", - decimals: 18, - contract: address!("0xafFbe9a60F1F45E057FD9b6DC70004Bb0Ccc8b99"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/67759/large/thq.jpg?1753757049"), -}; - -pub static CHRONOTECH: TokenInfo = TokenInfo { - name: "ChronoTech", - symbol: "TIME", - decimals: 8, - contract: address!("0x485d17A6f1B8780392d53D64751824253011A260"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/604/thumb/time-32x32.png?1627130666"), -}; - -pub static ALIEN_WORLDS: TokenInfo = TokenInfo { - name: "Alien Worlds", - symbol: "TLM", - decimals: 4, - contract: address!("0x888888848B652B3E3a0f34c96E00EEC0F3a23F72"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14676/thumb/kY-C4o7RThfWrDQsLCAG4q4clZhBDDfJQVhWUEKxXAzyQYMj4Jmq1zmFwpRqxhAJFPOa0AsW_PTSshoPuMnXNwq3rU7Imp15QimXTjlXMx0nC088mt1rIwRs75GnLLugWjSllxgzvQ9YrP4tBgclK4_rb17hjnusGj_c0u2fx0AvVokjSNB-v2poTj0xT9BZRCbzRE3-lF1.jpg?1617700061"), -}; - -pub static TOKEMAK: TokenInfo = TokenInfo { - name: "Tokemak", - symbol: "TOKE", - decimals: 18, - contract: address!("0x2e9d63788249371f1DFC918a52f8d799F4a38C94"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/17495/thumb/tokemak-avatar-200px-black.png?1628131614"), -}; - -pub static TOKENFI: TokenInfo = TokenInfo { - name: "TokenFi", - symbol: "TOKEN", - decimals: 9, - contract: address!("0x4507cEf57C46789eF8d1a19EA45f4216bae2B528"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/32507/large/MAIN_TokenFi_logo_icon.png?1698918427"), -}; - -pub static TE_FOOD: TokenInfo = TokenInfo { - name: "TE FOOD", - symbol: "TONE", - decimals: 18, - contract: address!("0x2Ab6Bb8408ca3199B8Fa6C92d5b455F820Af03c4"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/2325/thumb/tec.png?1547036538"), -}; - -pub static ORIGINTRAIL: TokenInfo = TokenInfo { - name: "OriginTrail", - symbol: "TRAC", - decimals: 18, - contract: address!("0xaA7a9CA87d3694B5755f213B5D04094b8d0F0A6F"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/1877/thumb/TRAC.jpg?1635134367"), -}; - -pub static TELLOR: TokenInfo = TokenInfo { - name: "Tellor", - symbol: "TRB", - decimals: 18, - contract: address!("0x88dF592F8eb5D7Bd38bFeF7dEb0fBc02cf3778a0"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686"), -}; - -pub static TREEHOUSE_TOKEN: TokenInfo = TokenInfo { - name: "Treehouse Token", - symbol: "TREE", - decimals: 18, - contract: address!("0x77146784315Ba81904d654466968e3a7c196d1f3"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/67664/large/TREE_logo.png?1753601041"), -}; - -pub static TRIA: TokenInfo = TokenInfo { - name: "Tria", - symbol: "TRIA", - decimals: 18, - contract: address!("0x228bEC415adE4b61D7CaF0adf8C91EAc587BA369"), - chain: 1, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/39382.png"), -}; - -pub static TRIBE: TokenInfo = TokenInfo { - name: "Tribe", - symbol: "TRIBE", - decimals: 18, - contract: address!("0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/14575/thumb/tribe.PNG?1617487954"), -}; - -pub static TRUEFI: TokenInfo = TokenInfo { - name: "TrueFi", - symbol: "TRU", - decimals: 8, - contract: address!("0x4C19596f5aAfF459fA38B0f7eD92F11AE6543784"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13180/thumb/truefi_glyph_color.png?1617610941"), -}; - -pub static TURBO: TokenInfo = TokenInfo { - name: "Turbo", - symbol: "TURBO", - decimals: 18, - contract: address!("0xA35923162C49cF95e6BF26623385eb431ad920D3"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/30117/large/TurboMark-QL_200.png?1708079597"), -}; - -pub static THE_VIRTUA_KOLECT: TokenInfo = TokenInfo { - name: "The Virtua Kolect", - symbol: "TVK", - decimals: 18, - contract: address!("0xd084B83C305daFD76AE3E1b4E1F1fe2eCcCb3988"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13330/thumb/virtua_original.png?1656043619"), -}; - -pub static UMA_VOTING_TOKEN_V1: TokenInfo = TokenInfo { - name: "UMA Voting Token v1", - symbol: "UMA", - decimals: 18, - contract: address!("0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), -}; - -pub static UNIFI_PROTOCOL_DAO: TokenInfo = TokenInfo { - name: "Unifi Protocol DAO", - symbol: "UNFI", - decimals: 18, - contract: address!("0x441761326490cACF7aF299725B6292597EE822c2"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/13152/thumb/logo-2.png?1605748967"), -}; - -pub static UNISWAP: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), - chain: 1, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static PAWTOCOL: TokenInfo = TokenInfo { - name: "Pawtocol", - symbol: "UPI", - decimals: 18, - contract: address!("0x70D2b7C19352bB76e4409858FF5746e500f2B67c"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12186/thumb/pawtocol.jpg?1597962008"), -}; - -pub static WORLD_LIBERTY_FINANCIAL_USD: TokenInfo = TokenInfo { - name: "World Liberty Financial USD", - symbol: "USD1", - decimals: 18, - contract: address!("0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54977/large/USD1_1000x1000_transparent.png?1749297002"), -}; - -pub static USDCOIN: TokenInfo = TokenInfo { - name: "USDCoin", - symbol: "USDC", - decimals: 6, - contract: address!("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), -}; - -pub static GLOBAL_DOLLAR: TokenInfo = TokenInfo { - name: "Global Dollar", - symbol: "USDG", - decimals: 6, - contract: address!("0xe343167631d89B6Ffc58B88d6b7fB0228795491D"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/51281/large/GDN_USDG_Token_200x200.png"), -}; - -pub static PAX_DOLLAR: TokenInfo = TokenInfo { - name: "Pax Dollar", - symbol: "USDP", - decimals: 18, - contract: address!("0x8E870D67F660D95d5be530380D0eC0bd388289E1"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/6013/standard/Pax_Dollar.png?1696506427"), -}; - -pub static QUANTOZ_USDQ: TokenInfo = TokenInfo { - name: "Quantoz USDQ", - symbol: "USDQ", - decimals: 6, - contract: address!("0xc83e27f270cce0A3A3A29521173a83F402c1768b"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/51852/large/USDQ_1000px_Color.png?1732071232"), -}; - -pub static STABLR_USD: TokenInfo = TokenInfo { - name: "StablR USD", - symbol: "USDR", - decimals: 6, - contract: address!("0x7B43E3875440B44613DC3bC08E7763e6Da63C8f8"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/53721/large/stablrusd-logo.png?1737126629"), -}; - -pub static USDS_STABLECOIN: TokenInfo = TokenInfo { - name: "USDS Stablecoin", - symbol: "USDS", - decimals: 18, - contract: address!("0xdC035D45d973E3EC169d2276DDab16f1e407384F"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/39926/large/usds.webp?1726666683"), -}; - -pub static TETHER_USD: TokenInfo = TokenInfo { - name: "Tether USD", - symbol: "USDT", - decimals: 6, - contract: address!("0xdAC17F958D2ee523a2206206994597C13D831ec7"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), -}; - -pub static USUAL: TokenInfo = TokenInfo { - name: "USUAL", - symbol: "USUAL", - decimals: 18, - contract: address!("0xC4441c2BE5d8fA8126822B9929CA0b81Ea0DE38E"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/51091/large/USUAL.jpg?1730035787"), -}; - -pub static VANRY: TokenInfo = TokenInfo { - name: "VANRY", - symbol: "VANRY", - decimals: 18, - contract: address!("0x8DE5B80a0C1B02Fe4976851D030B36122dbb8624"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/33466/large/apple-touch-icon.png?1701942541"), -}; - -pub static VOYAGER_TOKEN: TokenInfo = TokenInfo { - name: "Voyager Token", - symbol: "VGX", - decimals: 8, - contract: address!("0x3C4B6E6e1eA3D4863700D7F76b36B7f3D3f13E3d"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/794/thumb/Voyager-vgx.png?1575693595"), -}; - -pub static WRAPPED_AMPLEFORTH: TokenInfo = TokenInfo { - name: "Wrapped Ampleforth", - symbol: "WAMPL", - decimals: 18, - contract: address!("0xEDB171C18cE90B633DB442f2A6F72874093b49Ef"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/20825/thumb/photo_2021-11-25_02-05-11.jpg?1637811951"), -}; - -pub static WRAPPED_ANALOG_ONE_TOKEN: TokenInfo = TokenInfo { - name: "Wrapped Analog One Token", - symbol: "WANLOG", - decimals: 12, - contract: address!("0xf983da3ca66964C02628189Ea8Ca99fa9E24f66c"), - chain: 1, - logo_uri: Some("https://assets.kraken.com/marketing/web/icons-uni-webp/s_anlog.webp?i=kds"), -}; - -pub static WRAPPED_BTC: TokenInfo = TokenInfo { - name: "Wrapped BTC", - symbol: "WBTC", - decimals: 8, - contract: address!("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), -}; - -pub static WRAPPED_CENTRIFUGE: TokenInfo = TokenInfo { - name: "Wrapped Centrifuge", - symbol: "WCFG", - decimals: 18, - contract: address!("0xc221b7E65FfC80DE234bbB6667aBDd46593D34F0"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/17106/thumb/WCFG.jpg?1626266462"), -}; - -pub static WALLETCONNECT_TOKEN: TokenInfo = TokenInfo { - name: "WalletConnect Token", - symbol: "WCT", - decimals: 18, - contract: address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/50390/large/wc-token1.png?1727569464"), -}; - -pub static WRAPPED_ETHER: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static WORLD_LIBERTY_FINANCIAL: TokenInfo = TokenInfo { - name: "World Liberty Financial", - symbol: "WLFI", - decimals: 18, - contract: address!("0xdA5e1988097297dCdc1f90D4dFE7909e847CBeF6"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/50767/large/wlfi.png?1756438915"), -}; - -pub static WOO_NETWORK: TokenInfo = TokenInfo { - name: "WOO Network", - symbol: "WOO", - decimals: 18, - contract: address!("0x4691937a7508860F876c9c0a2a617E7d9E945D4B"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), -}; - -pub static ANOMA: TokenInfo = TokenInfo { - name: "Anoma", - symbol: "XAN", - decimals: 18, - contract: address!("0xCEDbEA37C8872c4171259Cdfd5255CB8923Cf8e7"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/69380/large/Anoma_Logo_Roundel_RGB_Colour-01.png?1758356672"), -}; - -pub static TETHER_GOLD: TokenInfo = TokenInfo { - name: "Tether Gold", - symbol: "XAUT", - decimals: 6, - contract: address!("0x68749665FF8D2d112Fa859AA293F07A622782F38"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/10481/large/Tether_Gold.png?1696510471"), -}; - -pub static CHAIN: TokenInfo = TokenInfo { - name: "Chain", - symbol: "XCN", - decimals: 18, - contract: address!("0xA2cd3D43c775978A96BdBf12d733D5A1ED94fb18"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054"), -}; - -pub static XSGD: TokenInfo = TokenInfo { - name: "XSGD", - symbol: "XSGD", - decimals: 6, - contract: address!("0x70e8dE73cE538DA2bEEd35d14187F6959a8ecA96"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623"), -}; - -pub static XYO_NETWORK: TokenInfo = TokenInfo { - name: "XYO Network", - symbol: "XYO", - decimals: 18, - contract: address!("0x55296f69f40Ea6d20E478533C15A6B08B654E758"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819"), -}; - -pub static YIELD_BASIS: TokenInfo = TokenInfo { - name: "Yield Basis", - symbol: "YB", - decimals: 18, - contract: address!("0x01791F726B4103694969820be083196cC7c045fF"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54871/large/yieldbasis_400x400.png?1760514173"), -}; - -pub static YEARN_FINANCE: TokenInfo = TokenInfo { - name: "yearn finance", - symbol: "YFI", - decimals: 18, - contract: address!("0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), -}; - -pub static DFI_MONEY: TokenInfo = TokenInfo { - name: "DFI money", - symbol: "YFII", - decimals: 18, - contract: address!("0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/11902/thumb/YFII-logo.78631676.png?1598677348"), -}; - -pub static YIELD_GUILD_GAMES: TokenInfo = TokenInfo { - name: "Yield Guild Games", - symbol: "YGG", - decimals: 18, - contract: address!("0x25f8087EAD173b73D6e8B84329989A8eEA16CF73"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/17358/thumb/le1nzlO6_400x400.jpg?1632465691"), -}; - -pub static ZAMA: TokenInfo = TokenInfo { - name: "Zama", - symbol: "ZAMA", - decimals: 18, - contract: address!("0xA12CC123ba206d4031D1c7f6223D1C2Ec249f4f3"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/70921/large/zama.png?1764591992"), -}; - -pub static ZETACHAIN: TokenInfo = TokenInfo { - name: "Zetachain", - symbol: "Zeta", - decimals: 18, - contract: address!("0xf091867EC603A6628eD83D274E835539D82e9cc8"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/26718/standard/Twitter_icon.png?1696525788"), -}; - -pub static BOUNDLESS: TokenInfo = TokenInfo { - name: "Boundless", - symbol: "ZKC", - decimals: 18, - contract: address!("0x000006c2A22ff4A44ff1f5d0F2ed65F781F55555"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/68462/large/boundless.png?1755826792"), -}; - -pub static ZKPASS: TokenInfo = TokenInfo { - name: "zkPass", - symbol: "ZKP", - decimals: 18, - contract: address!("0xe1Be424F442D0687129128C6c38aAce44F8c8Dbc"), - chain: 1, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/70273/large/zkpass.png?1761379373"), -}; - -pub static LAYERZERO: TokenInfo = TokenInfo { - name: "LayerZero", - symbol: "ZRO", - decimals: 18, - contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), - chain: 1, - logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), -}; - -pub static TOKEN_0X_PROTOCOL_TOKEN: TokenInfo = TokenInfo { - name: "0x Protocol Token", - symbol: "ZRX", - decimals: 18, - contract: address!("0xE41d2489571d322189246DaFA5ebDe1F4699F498"), - chain: 1, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), -}; - -pub static DAI_STABLECOIN_3_CE07538D: TokenInfo = TokenInfo { - name: "Dai Stablecoin", - symbol: "DAI", - decimals: 18, - contract: address!("0xaD6D458402F60fD3Bd25163575031ACDce07538D"), - chain: 3, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xaD6D458402F60fD3Bd25163575031ACDce07538D/logo.png"), -}; - -pub static UNISWAP_3_4201F984: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), - chain: 3, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static WRAPPED_ETHER_3_AA0CD5AB: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0xc778417E063141139Fce010982780140Aa0cD5Ab"), - chain: 3, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc778417E063141139Fce010982780140Aa0cD5Ab/logo.png"), -}; - -pub static DAI_STABLECOIN_4_A8FC4735: TokenInfo = TokenInfo { - name: "Dai Stablecoin", - symbol: "DAI", - decimals: 18, - contract: address!("0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735"), - chain: 4, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735/logo.png"), -}; - -pub static MAKER_4_359AAD85: TokenInfo = TokenInfo { - name: "Maker", - symbol: "MKR", - decimals: 18, - contract: address!("0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85"), - chain: 4, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85/logo.png"), -}; - -pub static UNISWAP_4_4201F984: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), - chain: 4, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static WRAPPED_ETHER_4_AA0CD5AB: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0xc778417E063141139Fce010982780140Aa0cD5Ab"), - chain: 4, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc778417E063141139Fce010982780140Aa0cD5Ab/logo.png"), -}; - -pub static UNISWAP_5_4201F984: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), - chain: 5, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static WRAPPED_ETHER_5_2B2208D6: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"), - chain: 5, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6/logo.png"), -}; - -pub static TOKEN_1INCH_10_94736426: TokenInfo = TokenInfo { - name: "1inch", - symbol: "1INCH", - decimals: 18, - contract: address!("0xAd42D013ac31486B73b6b059e748172994736426"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), -}; - -pub static AAVE_10_950C9278: TokenInfo = TokenInfo { - name: "Aave", - symbol: "AAVE", - decimals: 18, - contract: address!("0x76FB31fb4af56892A25e32cFC43De717950c9278"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), -}; - -pub static ACROSS_PROTOCOL_TOKEN_10_FDD1B76B: TokenInfo = TokenInfo { - name: "Across Protocol Token", - symbol: "ACX", - decimals: 18, - contract: address!("0xFf733b2A3557a7ed6697007ab5D11B79FdD1b76B"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165"), -}; - -pub static ARPA_CHAIN_10_C9BFA31E: TokenInfo = TokenInfo { - name: "ARPA Chain", - symbol: "ARPA", - decimals: 18, - contract: address!("0x334cc734866E97D8452Ae6261d68Fd9bc9BFa31E"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357"), -}; - -pub static BALANCER_10_E9379921: TokenInfo = TokenInfo { - name: "Balancer", - symbol: "BAL", - decimals: 18, - contract: address!("0xFE8B128bA8C78aabC59d4c64cEE7fF28e9379921"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png"), -}; - -pub static BICONOMY_10_C0FB1C9D: TokenInfo = TokenInfo { - name: "Biconomy", - symbol: "BICO", - decimals: 18, - contract: address!("0xd6909e9e702024eb93312B989ee46794c0fB1C9D"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749"), -}; - -pub static BOBA_NETWORK_10_CB88854D: TokenInfo = TokenInfo { - name: "Boba Network", - symbol: "BOBA", - decimals: 18, - contract: address!("0x07ad578FF86B135bE19A12759064b802Cb88854D"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/20285/thumb/BOBA.png?1636811576"), -}; - -pub static BARNBRIDGE_10_3F276747: TokenInfo = TokenInfo { - name: "BarnBridge", - symbol: "BOND", - decimals: 18, - contract: address!("0x3e7eF8f50246f725885102E8238CBba33F276747"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853"), -}; - -pub static BRAINTRUST_10_E141254E: TokenInfo = TokenInfo { - name: "Braintrust", - symbol: "BTRST", - decimals: 18, - contract: address!("0xEd50aCE88bd42B45cB0F49be15395021E141254e"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/18100/thumb/braintrust.PNG?1630475394"), -}; - -pub static BINANCE_USD_10_39D2DB39: TokenInfo = TokenInfo { - name: "Binance USD", - symbol: "BUSD", - decimals: 18, - contract: address!("0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), -}; - -pub static COINBASE_WRAPPED_STAKED_ETH_10_78DCF3B2: TokenInfo = TokenInfo { - name: "Coinbase Wrapped Staked ETH", - symbol: "cbETH", - decimals: 18, - contract: address!("0xadDb6A0412DE1BA0F936DCaeb8Aaa24578dcF3B2"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/27008/large/cbeth.png"), -}; - -pub static CELO_NATIVE_ASSET_WORMHOLE_10_B9B5C349: TokenInfo = TokenInfo { - name: "Celo native asset (Wormhole)", - symbol: "CELO", - decimals: 18, - contract: address!("0x9b88D293b7a791E40d36A39765FFd5A1B9b5c349"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png"), -}; - -pub static CURVE_DAO_TOKEN_10_0605FB53: TokenInfo = TokenInfo { - name: "Curve DAO Token", - symbol: "CRV", - decimals: 18, - contract: address!("0x0994206dfE8De6Ec6920FF4D779B0d950605Fb53"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), -}; - -pub static CARTESI_10_071295BF: TokenInfo = TokenInfo { - name: "Cartesi", - symbol: "CTSI", - decimals: 18, - contract: address!("0xEc6adef5E1006bb305bB1975333e8fc4071295bf"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), -}; - -pub static CYBER: TokenInfo = TokenInfo { - name: "CYBER", - symbol: "CYBER", - decimals: 18, - contract: address!("0x14778860E937f509e651192a90589dE711Fb88a9"), - chain: 10, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/31274/large/token.png?1715826754"), -}; - -pub static DAI_STABLECOIN_10_C9000DA1: TokenInfo = TokenInfo { - name: "Dai Stablecoin", - symbol: "DAI", - decimals: 18, - contract: address!("0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), -}; - -pub static DERIVE_10_72BBA100: TokenInfo = TokenInfo { - name: "Derive", - symbol: "DRV", - decimals: 18, - contract: address!("0x33800De7E817A70A694F31476313A7c572BBa100"), - chain: 10, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695"), -}; - -pub static ETHEREUM_NAME_SERVICE_10_5E890A00: TokenInfo = TokenInfo { - name: "Ethereum Name Service", - symbol: "ENS", - decimals: 18, - contract: address!("0x65559aA14915a70190438eF90104769e5E890A00"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140"), -}; - -pub static STAFI_10_911BAD41: TokenInfo = TokenInfo { - name: "Stafi", - symbol: "FIS", - decimals: 18, - contract: address!("0xD8737CA46aa6285dE7B8777a8e3db232911baD41"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991"), -}; - -pub static SHAPESHIFT_FOX_TOKEN_10_37CED174: TokenInfo = TokenInfo { - name: "ShapeShift FOX Token", - symbol: "FOX", - decimals: 18, - contract: address!("0xF1a0DA3367BC7aa04F8D94BA57B862ff37CeD174"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622"), -}; - -pub static FRAX_10_9A53F475: TokenInfo = TokenInfo { - name: "Frax", - symbol: "FRAX", - decimals: 18, - contract: address!("0x2E3D870790dC77A83DD1d18184Acc7439A53f475"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), -}; - -pub static FRAX_SHARE_10_1C2205BE: TokenInfo = TokenInfo { - name: "Frax Share", - symbol: "FXS", - decimals: 18, - contract: address!("0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), -}; - -pub static GITCOIN_10_46445B08: TokenInfo = TokenInfo { - name: "Gitcoin", - symbol: "GTC", - decimals: 18, - contract: address!("0x1EBA7a6a72c894026Cd654AC5CDCF83A46445B08"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929"), -}; - -pub static GYEN_10_D9B6D5F7: TokenInfo = TokenInfo { - name: "GYEN", - symbol: "GYEN", - decimals: 6, - contract: address!("0x589d35656641d6aB57A545F08cf473eCD9B6D5F7"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343"), -}; - -pub static KRYLL_10_C9022021: TokenInfo = TokenInfo { - name: "KRYLL", - symbol: "KRL", - decimals: 18, - contract: address!("0x2ed6222CB75E353b8789bec7Bb443b7eC9022021"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979"), -}; - -pub static KUJIRA_10_5671E7CA: TokenInfo = TokenInfo { - name: "Kujira", - symbol: "KUJI", - decimals: 6, - contract: address!("0x3A18dcC9745eDcD1Ef33ecB93b0b6eBA5671e7Ca"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png"), -}; - -pub static LIDO_DAO_10_2596735F: TokenInfo = TokenInfo { - name: "Lido DAO", - symbol: "LDO", - decimals: 18, - contract: address!("0xFdb794692724153d1488CcdBE0C56c252596735F"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644"), -}; - -pub static CHAINLINK_TOKEN_10_38FFA7F6: TokenInfo = TokenInfo { - name: "ChainLink Token", - symbol: "LINK", - decimals: 18, - contract: address!("0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), -}; - -pub static LOOPRINGCOIN_V2_10_1464907E: TokenInfo = TokenInfo { - name: "LoopringCoin V2", - symbol: "LRC", - decimals: 18, - contract: address!("0xFEaA9194F9F8c1B65429E31341a103071464907E"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png"), -}; - -pub static LIQUITY_USD_10_9B7B2819: TokenInfo = TokenInfo { - name: "Liquity USD", - symbol: "LUSD", - decimals: 18, - contract: address!("0xc40F949F8a4e094D1b49a23ea9241D289B7b2819"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327"), -}; - -pub static MASK_NETWORK_10_BDF63798: TokenInfo = TokenInfo { - name: "Mask Network", - symbol: "MASK", - decimals: 18, - contract: address!("0x3390108E913824B8eaD638444cc52B9aBdF63798"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316"), -}; - -pub static MAKER_10_27F2FCB5: TokenInfo = TokenInfo { - name: "Maker", - symbol: "MKR", - decimals: 18, - contract: address!("0xab7bAdEF82E9Fe11f6f33f87BC9bC2AA27F2fCB5"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png"), -}; - -pub static OCEAN_PROTOCOL_10_B8B49F9E: TokenInfo = TokenInfo { - name: "Ocean Protocol", - symbol: "OCEAN", - decimals: 18, - contract: address!("0x2561aa2bB1d2Eb6629EDd7b0938d7679B8b49f9E"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686"), -}; - -pub static OPTIMISM: TokenInfo = TokenInfo { - name: "Optimism", - symbol: "OP", - decimals: 18, - contract: address!("0x4200000000000000000000000000000000000042"), - chain: 10, - logo_uri: Some("https://ethereum-optimism.github.io/data/OP/logo.png"), -}; - -pub static PENDLE_10_796E66E1: TokenInfo = TokenInfo { - name: "Pendle", - symbol: "PENDLE", - decimals: 18, - contract: address!("0xBC7B1Ff1c6989f006a1185318eD4E7b5796e66E1"), - chain: 10, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728"), -}; - -pub static PEPE_10_9DDB16F5: TokenInfo = TokenInfo { - name: "Pepe", - symbol: "PEPE", - decimals: 18, - contract: address!("0xC1c167CC44f7923cd0062c4370Df962f9DDB16f5"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725"), -}; - -pub static PERPETUAL_PROTOCOL_10_976840E0: TokenInfo = TokenInfo { - name: "Perpetual Protocol", - symbol: "PERP", - decimals: 18, - contract: address!("0x9e1028F5F1D5eDE59748FFceE5532509976840E0"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), -}; - -pub static RAI_REFLEX_INDEX_10_7705448B: TokenInfo = TokenInfo { - name: "Rai Reflex Index", - symbol: "RAI", - decimals: 18, - contract: address!("0x7FB688CCf682d58f86D7e38e03f9D22e7705448B"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334"), -}; - -pub static RARI_GOVERNANCE_TOKEN_10_DCEC711A: TokenInfo = TokenInfo { - name: "Rari Governance Token", - symbol: "RGT", - decimals: 18, - contract: address!("0xB548f63D4405466B36C0c0aC3318a22fDcec711a"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014"), -}; - -pub static ROCKET_POOL_PROTOCOL_10_C14D1401: TokenInfo = TokenInfo { - name: "Rocket Pool Protocol", - symbol: "RPL", - decimals: 18, - contract: address!("0xC81D1F0EB955B0c020E5d5b264E1FF72c14d1401"), - chain: 10, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/2090/large/rocket_pool_%28RPL%29.png?1696503058"), -}; - -pub static STATUS_10_64CFB6B2: TokenInfo = TokenInfo { - name: "Status", - symbol: "SNT", - decimals: 18, - contract: address!("0x650AF3C15AF43dcB218406d30784416D64Cfb6B2"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778"), -}; - -pub static SYNTHETIX_NETWORK_TOKEN_10_3D7599B4: TokenInfo = TokenInfo { - name: "Synthetix Network Token", - symbol: "SNX", - decimals: 18, - contract: address!("0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), -}; - -pub static SOL_WORMHOLE_10_7FA664F1: TokenInfo = TokenInfo { - name: "SOL Wormhole ", - symbol: "SOL", - decimals: 9, - contract: address!("0xba1Cf949c382A32a09A17B2AdF3587fc7fA664f1"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), -}; - -pub static SUKU_10_0B9E50A4: TokenInfo = TokenInfo { - name: "SUKU", - symbol: "SUKU", - decimals: 18, - contract: address!("0xEf6301DA234fC7b0545c6E877D3359FE0B9E50a4"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/11969/thumb/UmfW5S6f_400x400.jpg?1596602238"), -}; - -pub static SYNTH_SUSD_10_751EC8D9: TokenInfo = TokenInfo { - name: "Synth sUSD", - symbol: "sUSD", - decimals: 18, - contract: address!("0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765"), -}; - -pub static SUSHI_10_0F60112B: TokenInfo = TokenInfo { - name: "Sushi", - symbol: "SUSHI", - decimals: 18, - contract: address!("0x3eaEb77b03dBc0F6321AE1b72b2E9aDb0F60112B"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), -}; - -pub static THRESHOLD_NETWORK_10_8C734EA7: TokenInfo = TokenInfo { - name: "Threshold Network", - symbol: "T", - decimals: 18, - contract: address!("0x747e42Eb0591547a0ab429B3627816208c734EA7"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340"), -}; - -pub static TELLOR_10_E3CEB888: TokenInfo = TokenInfo { - name: "Tellor", - symbol: "TRB", - decimals: 18, - contract: address!("0xaf8cA653Fa2772d58f4368B0a71980e9E3cEB888"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686"), -}; - -pub static UMA_VOTING_TOKEN_V1_10_855A77EA: TokenInfo = TokenInfo { - name: "UMA Voting Token v1", - symbol: "UMA", - decimals: 18, - contract: address!("0xE7798f023fC62146e8Aa1b36Da45fb70855a77Ea"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), -}; - -pub static UNISWAP_10_0E816691: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0x6fd9d7AD17242c41f7131d257212c54A0e816691"), - chain: 10, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static USDCOIN_10_D097FF85: TokenInfo = TokenInfo { - name: "USDCoin", - symbol: "USDC", - decimals: 6, - contract: address!("0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"), - chain: 10, - logo_uri: Some("https://ethereum-optimism.github.io/data/USDC/logo.png"), -}; - -pub static USDCOIN_BRIDGED_FROM_ETHEREUM: TokenInfo = TokenInfo { - name: "USDCoin (Bridged from Ethereum)", - symbol: "USDC.e", - decimals: 6, - contract: address!("0x7F5c764cBc14f9669B88837ca1490cCa17c31607"), - chain: 10, - logo_uri: Some("https://ethereum-optimism.github.io/data/USDC/logo.png"), -}; - -pub static TETHER_USD_10_8CE58E58: TokenInfo = TokenInfo { - name: "Tether USD", - symbol: "USDT", - decimals: 6, - contract: address!("0x94b008aA00579c1307B0EF2c499aD98a8ce58e58"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), -}; - -pub static VELODROME_FINANCE: TokenInfo = TokenInfo { - name: "Velodrome Finance", - symbol: "VELO", - decimals: 18, - contract: address!("0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/12538/standard/Logo_200x_200.png?1696512350"), -}; - -pub static WRAPPED_BTC_10_BF0A2095: TokenInfo = TokenInfo { - name: "Wrapped BTC", - symbol: "WBTC", - decimals: 8, - contract: address!("0x68f180fcCe6836688e9084f035309E29Bf0A2095"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), -}; - -pub static WALLETCONNECT_TOKEN_10_DD927945: TokenInfo = TokenInfo { - name: "WalletConnect Token", - symbol: "WCT", - decimals: 18, - contract: address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945"), - chain: 10, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/50390/large/wc-token1.png?1727569464"), -}; - -pub static WRAPPED_ETHER_10_00000006: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0x4200000000000000000000000000000000000006"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static WORLDCOIN: TokenInfo = TokenInfo { - name: "Worldcoin", - symbol: "WLD", - decimals: 18, - contract: address!("0xdC6fF44d5d932Cbd77B52E5612Ba0529DC6226F1"), - chain: 10, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/31069/large/worldcoin.jpeg?1696529903"), -}; - -pub static WOO_NETWORK_10_51A5E527: TokenInfo = TokenInfo { - name: "WOO Network", - symbol: "WOO", - decimals: 18, - contract: address!("0x871f2F2ff935FD1eD867842FF2a7bfD051A5E527"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), -}; - -pub static XYO_NETWORK_10_DBD81FC8: TokenInfo = TokenInfo { - name: "XYO Network", - symbol: "XYO", - decimals: 18, - contract: address!("0x9db118D43069B73B8a252bF0be49d50Edbd81fc8"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819"), -}; - -pub static YEARN_FINANCE_10_FEE9107B: TokenInfo = TokenInfo { - name: "yearn finance", - symbol: "YFI", - decimals: 18, - contract: address!("0x9046D36440290FfDE54FE0DD84Db8b1CfEE9107B"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), -}; - -pub static LAYERZERO_10_F13271CD: TokenInfo = TokenInfo { - name: "LayerZero", - symbol: "ZRO", - decimals: 18, - contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), - chain: 10, - logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), -}; - -pub static TOKEN_0X_PROTOCOL_TOKEN_10_FA3C2F33: TokenInfo = TokenInfo { - name: "0x Protocol Token", - symbol: "ZRX", - decimals: 18, - contract: address!("0xD1917629B3E6A72E6772Aab5dBe58Eb7FA3C2F33"), - chain: 10, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), -}; - -pub static DAI_STABLECOIN_42_B64CA6AA: TokenInfo = TokenInfo { - name: "Dai Stablecoin", - symbol: "DAI", - decimals: 18, - contract: address!("0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa"), - chain: 42, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa/logo.png"), -}; - -pub static MAKER_42_71A4FFCD: TokenInfo = TokenInfo { - name: "Maker", - symbol: "MKR", - decimals: 18, - contract: address!("0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD"), - chain: 42, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD/logo.png"), -}; - -pub static UNISWAP_42_4201F984: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), - chain: 42, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static WRAPPED_ETHER_42_C2CF029C: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0xd0A1E359811322d97991E03f863a0C30C2cF029C"), - chain: 42, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xd0A1E359811322d97991E03f863a0C30C2cF029C/logo.png"), -}; - -pub static TOKEN_1INCH_56_4120C302: TokenInfo = TokenInfo { - name: "1inch", - symbol: "1INCH", - decimals: 18, - contract: address!("0x111111111117dC0aa78b770fA6A738034120C302"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), -}; - -pub static AAVE_56_7E58F802: TokenInfo = TokenInfo { - name: "Aave", - symbol: "AAVE", - decimals: 18, - contract: address!("0xfb6115445Bff7b52FeB98650C87f44907E58f802"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), -}; - -pub static ALCHEMY_PAY_56_7003056D: TokenInfo = TokenInfo { - name: "Alchemy Pay", - symbol: "ACH", - decimals: 8, - contract: address!("0xBc7d6B50616989655AfD682fb42743507003056D"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12390/thumb/ACH_%281%29.png?1599691266"), -}; - -pub static AMBIRE_ADEX_56_A7077819: TokenInfo = TokenInfo { - name: "Ambire AdEx", - symbol: "ADX", - decimals: 18, - contract: address!("0x6bfF4Fb161347ad7de4A625AE5aa3A1CA7077819"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540"), -}; - -pub static AGEUR_56_D5FE5F89: TokenInfo = TokenInfo { - name: "agEur", - symbol: "agEUR", - decimals: 18, - contract: address!("0x12f31B73D812C6Bb0d735a218c086d44D5fe5f89"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), -}; - -pub static AIOZ_NETWORK_56_9FC3741D: TokenInfo = TokenInfo { - name: "AIOZ Network", - symbol: "AIOZ", - decimals: 18, - contract: address!("0x33d08D8C7a168333a85285a68C0042b39fC3741D"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126"), -}; - -pub static ALEPH_IM_56_DE9038C4: TokenInfo = TokenInfo { - name: "Aleph im", - symbol: "ALEPH", - decimals: 18, - contract: address!("0x82D2f8E02Afb160Dd5A480a617692e62de9038C4"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725"), -}; - -pub static MY_NEIGHBOR_ALICE_56_745D63E8: TokenInfo = TokenInfo { - name: "My Neighbor Alice", - symbol: "ALICE", - decimals: 6, - contract: address!("0xAC51066d7bEC65Dc4589368da368b212745d63E8"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/14375/thumb/alice_logo.jpg?1615782968"), -}; - -pub static ALPHA_VENTURE_DAO_56_13B40975: TokenInfo = TokenInfo { - name: "Alpha Venture DAO", - symbol: "ALPHA", - decimals: 18, - contract: address!("0xa1faa113cbE53436Df28FF0aEe54275c13B40975"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876"), -}; - -pub static ANKR_56_531B08E3: TokenInfo = TokenInfo { - name: "Ankr", - symbol: "ANKR", - decimals: 18, - contract: address!("0xf307910A4c7bbc79691fD374889b36d8531B08e3"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978"), -}; - -pub static ARPA_CHAIN_56_FA2D6F7E: TokenInfo = TokenInfo { - name: "ARPA Chain", - symbol: "ARPA", - decimals: 18, - contract: address!("0x6F769E65c14Ebd1f68817F5f1DcDb61Cfa2D6f7e"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357"), -}; - -pub static ASTER: TokenInfo = TokenInfo { - name: "Aster", - symbol: "ASTER", - decimals: 18, - contract: address!("0x000Ae314E2A2172a039B26378814C252734f556A"), - chain: 56, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/69040/large/_ASTER.png?1757326782"), -}; - -pub static AUTOMATA_56_2F141225: TokenInfo = TokenInfo { - name: "Automata", - symbol: "ATA", - decimals: 18, - contract: address!("0xA2120b9e674d3fC3875f415A7DF52e382F141225"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745"), -}; - -pub static AXELAR_56_C96F1F65: TokenInfo = TokenInfo { - name: "Axelar", - symbol: "AXL", - decimals: 6, - contract: address!("0x8b1f4432F943c465A973FeDC6d7aa50Fc96f1f65"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg"), -}; - -pub static AXIE_INFINITY_56_D4D2F8A0: TokenInfo = TokenInfo { - name: "Axie Infinity", - symbol: "AXS", - decimals: 18, - contract: address!("0x715D400F88C167884bbCc41C5FeA407ed4D2f8A0"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082"), -}; - -pub static BLUZELLE_56_DA0ACDA2: TokenInfo = TokenInfo { - name: "Bluzelle", - symbol: "BLZ", - decimals: 18, - contract: address!("0x935a544Bf5816E3A7C13DB2EFe3009Ffda0aCdA2"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/2848/thumb/ColorIcon_3x.png?1622516510"), -}; - -pub static BINANCE_USD_56_DD087D56: TokenInfo = TokenInfo { - name: "Binance USD", - symbol: "BUSD", - decimals: 18, - contract: address!("0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), -}; - -pub static COIN98_56_90F1C3A6: TokenInfo = TokenInfo { - name: "Coin98", - symbol: "C98", - decimals: 18, - contract: address!("0xaEC945e04baF28b135Fa7c640f624f8D90F1C3a6"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/17117/thumb/logo.png?1626412904"), -}; - -pub static CHROMIA_56_32B224FE: TokenInfo = TokenInfo { - name: "Chromia", - symbol: "CHR", - decimals: 6, - contract: address!("0xf9CeC8d50f6c8ad3Fb6dcCEC577e05aA32B224FE"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/5000/thumb/Chromia.png?1559038018"), -}; - -pub static CLOVER_FINANCE_56_367A4E4D: TokenInfo = TokenInfo { - name: "Clover Finance", - symbol: "CLV", - decimals: 18, - contract: address!("0x09E889BB4D5b474f561db0491C38702F367A4e4d"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/15278/thumb/clover.png?1645084454"), -}; - -pub static COMPOUND_56_8CAD67E8: TokenInfo = TokenInfo { - name: "Compound", - symbol: "COMP", - decimals: 18, - contract: address!("0x52CE071Bd9b1C4B00A0b92D298c512478CaD67e8"), - chain: 56, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), -}; - -pub static CIRCUITS_OF_VALUE_56_2B141464: TokenInfo = TokenInfo { - name: "Circuits of Value", - symbol: "COVAL", - decimals: 8, - contract: address!("0xd15CeE1DEaFBad6C0B3Fd7489677Cc102B141464"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/588/thumb/coval-logo.png?1599493950"), -}; - -pub static CARTESI_56_2D033EF2: TokenInfo = TokenInfo { - name: "Cartesi", - symbol: "CTSI", - decimals: 18, - contract: address!("0x8dA443F84fEA710266C8eB6bC34B71702d033EF2"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), -}; - -pub static DAI_STABLECOIN_56_58B1DBC3: TokenInfo = TokenInfo { - name: "Dai Stablecoin", - symbol: "DAI", - decimals: 18, - contract: address!("0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3"), - chain: 56, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), -}; - -pub static MINES_OF_DALARNIA_56_D45CD978: TokenInfo = TokenInfo { - name: "Mines of Dalarnia", - symbol: "DAR", - decimals: 6, - contract: address!("0x23CE9e926048273eF83be0A3A8Ba9Cb6D45cd978"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/19837/thumb/dar.png?1636014223"), -}; - -pub static DEXTOOLS_56_C29896E3: TokenInfo = TokenInfo { - name: "DexTools", - symbol: "DEXT", - decimals: 18, - contract: address!("0xe91a8D2c584Ca93C7405F15c22CdFE53C29896E3"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188"), -}; - -pub static DIA_56_7E0901DD: TokenInfo = TokenInfo { - name: "DIA", - symbol: "DIA", - decimals: 18, - contract: address!("0x99956D38059cf7bEDA96Ec91Aa7BB2477E0901DD"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751"), -}; - -pub static DREP_56_01A705FF: TokenInfo = TokenInfo { - name: "Drep", - symbol: "DREP", - decimals: 18, - contract: address!("0xEC583f25A049CC145dA9A256CDbE9B6201a705Ff"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/14578/thumb/KotgsCgS_400x400.jpg?1617094445"), -}; - -pub static DEFI_YIELD_PROTOCOL_56_91BCEF17: TokenInfo = TokenInfo { - name: "DeFi Yield Protocol", - symbol: "DYP", - decimals: 18, - contract: address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066"), -}; - -pub static DOGELON_MARS_56_D9BE2540: TokenInfo = TokenInfo { - name: "Dogelon Mars", - symbol: "ELON", - decimals: 18, - contract: address!("0x7bd6FaBD64813c48545C9c0e312A0099d9be2540"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413"), -}; - -pub static HARVEST_FINANCE_56_A5D33743: TokenInfo = TokenInfo { - name: "Harvest Finance", - symbol: "FARM", - decimals: 18, - contract: address!("0x4B5C23cac08a567ecf0c1fFcA8372A45a5D33743"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180"), -}; - -pub static FETCH_AI_56_8691FA7F: TokenInfo = TokenInfo { - name: "Fetch ai", - symbol: "FET", - decimals: 18, - contract: address!("0x031b41e504677879370e9DBcF937283A8691Fa7f"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136"), -}; - -pub static FLOKI_56_5363D37E: TokenInfo = TokenInfo { - name: "FLOKI", - symbol: "FLOKI", - decimals: 9, - contract: address!("0xfb5B838b6cfEEdC2873aB27866079AC55363D37E"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318"), -}; - -pub static FRAX_56_53E89F40: TokenInfo = TokenInfo { - name: "Frax", - symbol: "FRAX", - decimals: 18, - contract: address!("0x90C97F71E18723b0Cf0dfa30ee176Ab653E89F40"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), -}; - -pub static FANTOM_56_AF29DCFE: TokenInfo = TokenInfo { - name: "Fantom", - symbol: "FTM", - decimals: 18, - contract: address!("0xAD29AbB318791D579433D831ed122aFeAf29dcfe"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016"), -}; - -pub static FRAX_SHARE_56_5EADB9EE: TokenInfo = TokenInfo { - name: "Frax Share", - symbol: "FXS", - decimals: 18, - contract: address!("0xe48A3d7d0Bc88d552f730B62c006bC925eadB9eE"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), -}; - -pub static GALXE_56_40497AA5: TokenInfo = TokenInfo { - name: "Galxe", - symbol: "GAL", - decimals: 18, - contract: address!("0xe4Cc45Bb5DBDA06dB6183E8bf016569f40497Aa5"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533"), -}; - -pub static ETHGAS_56_B72F7D49: TokenInfo = TokenInfo { - name: "ETHGas", - symbol: "GWEI", - decimals: 18, - contract: address!("0x30117E4bC17d7B044194b76A38365C53b72F7D49"), - chain: 56, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/71375/large/ethgas_token_200.png?1769055039"), -}; - -pub static HASHFLOW_56_35883E47: TokenInfo = TokenInfo { - name: "Hashflow", - symbol: "HFT", - decimals: 18, - contract: address!("0x44Ec807ce2F4a6F2737A92e985f318d035883e47"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/26136/large/hashflow-icon-cmc.png"), -}; - -pub static HIGHSTREET_56_1FFEED63: TokenInfo = TokenInfo { - name: "Highstreet", - symbol: "HIGH", - decimals: 18, - contract: address!("0x5f4Bde007Dc06b867f86EBFE4802e34A1fFEEd63"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470"), -}; - -pub static INJECTIVE_56_EBE4D495: TokenInfo = TokenInfo { - name: "Injective", - symbol: "INJ", - decimals: 18, - contract: address!("0xa2B726B1145A4773F68593CF171187d8EBe4d495"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237"), -}; - -pub static JUPITER_56_8E140CE7: TokenInfo = TokenInfo { - name: "Jupiter", - symbol: "JUP", - decimals: 18, - contract: address!("0x0231f91e02DebD20345Ae8AB7D71A41f8E140cE7"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/10351/thumb/logo512.png?1632480932"), -}; - -pub static KUJIRA_56_7C9FB5CC: TokenInfo = TokenInfo { - name: "Kujira", - symbol: "KUJI", - decimals: 6, - contract: address!("0x073690e6CE25bE816E68F32dCA3e11067c9FB5Cc"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png"), -}; - -pub static CHAINLINK_TOKEN_56_111A51BD: TokenInfo = TokenInfo { - name: "ChainLink Token", - symbol: "LINK", - decimals: 18, - contract: address!("0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD"), - chain: 56, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), -}; - -pub static MASK_NETWORK_56_F4D568A3: TokenInfo = TokenInfo { - name: "Mask Network", - symbol: "MASK", - decimals: 18, - contract: address!("0x2eD9a5C8C13b93955103B9a7C167B67Ef4d568a3"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316"), -}; - -pub static MATH_56_98A36983: TokenInfo = TokenInfo { - name: "MATH", - symbol: "MATH", - decimals: 18, - contract: address!("0xF218184Af829Cf2b0019F8E6F0b2423498a36983"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590"), -}; - -pub static POLYGON_56_5ED682BD: TokenInfo = TokenInfo { - name: "Polygon", - symbol: "MATIC", - decimals: 18, - contract: address!("0xCC42724C6683B7E57334c4E856f4c9965ED682bD"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), -}; - -pub static MERIT_CIRCLE_56_4EF9E5D6: TokenInfo = TokenInfo { - name: "Merit Circle", - symbol: "MC", - decimals: 18, - contract: address!("0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/19304/thumb/Db4XqML.png?1634972154"), -}; - -pub static METIS_56_B0820639: TokenInfo = TokenInfo { - name: "Metis", - symbol: "METIS", - decimals: 18, - contract: address!("0xe552Fb52a4F19e44ef5A967632DBc320B0820639"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312"), -}; - -pub static MAGIC_INTERNET_MONEY_56_19F433BA: TokenInfo = TokenInfo { - name: "Magic Internet Money", - symbol: "MIM", - decimals: 18, - contract: address!("0xfE19F0B51438fd612f6FD59C1dbB3eA319f433Ba"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612"), -}; - -pub static MIRROR_PROTOCOL_56_10D8C2C9: TokenInfo = TokenInfo { - name: "Mirror Protocol", - symbol: "MIR", - decimals: 18, - contract: address!("0x5B6DcF557E2aBE2323c48445E8CC948910d8c2c9"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/13295/thumb/mirror_logo_transparent.png?1611554658"), -}; - -pub static MULTICHAIN_56_3C8764E3: TokenInfo = TokenInfo { - name: "Multichain", - symbol: "MULTI", - decimals: 18, - contract: address!("0x9Fb9a33956351cf4fa040f65A13b835A3C8764E3"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238"), -}; - -pub static PERPETUAL_PROTOCOL_56_84C7C6F5: TokenInfo = TokenInfo { - name: "Perpetual Protocol", - symbol: "PERP", - decimals: 18, - contract: address!("0x4e7f408be2d4E9D60F49A64B89Bb619c84C7c6F5"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), -}; - -pub static POLKASTARTER_56_0887F570: TokenInfo = TokenInfo { - name: "Polkastarter", - symbol: "POLS", - decimals: 18, - contract: address!("0x7e624FA0E1c4AbFD309cC15719b7E2580887f570"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702"), -}; - -pub static PARSIQ_56_93D2A577: TokenInfo = TokenInfo { - name: "PARSIQ", - symbol: "PRQ", - decimals: 18, - contract: address!("0xd21d29B38374528675C34936bf7d5Dd693D2a577"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280"), -}; - -pub static PSTAKE_FINANCE_56_F58A7C0C: TokenInfo = TokenInfo { - name: "pSTAKE Finance", - symbol: "PSTAKE", - decimals: 18, - contract: address!("0x4C882ec256823eE773B25b414d36F92ef58a7c0C"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/23931/thumb/PSTAKE_Dark.png?1645709930"), -}; - -pub static REVV_56_8D702A93: TokenInfo = TokenInfo { - name: "REVV", - symbol: "REVV", - decimals: 18, - contract: address!("0x833F307aC507D47309fD8CDD1F835BeF8D702a93"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12373/thumb/REVV_TOKEN_Refined_2021_%281%29.png?1627652390"), -}; - -pub static STADER_56_0B5481E8: TokenInfo = TokenInfo { - name: "Stader", - symbol: "SD", - decimals: 18, - contract: address!("0x3BC5AC0dFdC871B365d159f728dd1B9A0B5481E8"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png"), -}; - -pub static SOL_WORMHOLE_56_D3AEA76E: TokenInfo = TokenInfo { - name: "SOL Wormhole ", - symbol: "SOL", - decimals: 9, - contract: address!("0xfA54fF1a158B5189Ebba6ae130CEd6bbd3aEA76e"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), -}; - -pub static STARGATE_FINANCE_56_9631D62B: TokenInfo = TokenInfo { - name: "Stargate Finance", - symbol: "STG", - decimals: 18, - contract: address!("0xB0D502E938ed5f4df2E681fE6E419ff29631d62b"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518"), -}; - -pub static SUPERFARM_56_CC4F0D4D: TokenInfo = TokenInfo { - name: "SuperFarm", - symbol: "SUPER", - decimals: 18, - contract: address!("0x51BA0b044d96C3aBfcA52B64D733603CCC4F0d4D"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899"), -}; - -pub static SUSHI_56_FC9124C4: TokenInfo = TokenInfo { - name: "Sushi", - symbol: "SUSHI", - decimals: 18, - contract: address!("0x947950BcC74888a40Ffa2593C5798F11Fc9124C4"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), -}; - -pub static SWFTCOIN_56_55DFBAD3: TokenInfo = TokenInfo { - name: "SWFTCOIN", - symbol: "SWFTC", - decimals: 18, - contract: address!("0xE64E30276C2F826FEbd3784958d6Da7B55DfbaD3"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/2346/thumb/SWFTCoin.jpg?1618392022"), -}; - -pub static SWIPE_56_FABA485A: TokenInfo = TokenInfo { - name: "Swipe", - symbol: "SXP", - decimals: 18, - contract: address!("0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/9368/thumb/swipe.png?1566792311"), -}; - -pub static SYNAPSE_56_1F9E9484: TokenInfo = TokenInfo { - name: "Synapse", - symbol: "SYN", - decimals: 18, - contract: address!("0xa4080f1778e69467E905B8d6F72f6e441f9e9484"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049"), -}; - -pub static CHRONOTECH_56_DE5D7F68: TokenInfo = TokenInfo { - name: "ChronoTech", - symbol: "TIME", - decimals: 8, - contract: address!("0x3b198e26E473b8faB2085b37978e36c9DE5D7f68"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/604/thumb/time-32x32.png?1627130666"), -}; - -pub static ALIEN_WORLDS_56_EBD57C95: TokenInfo = TokenInfo { - name: "Alien Worlds", - symbol: "TLM", - decimals: 4, - contract: address!("0x2222227E22102Fe3322098e4CBfE18cFebD57c95"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/14676/thumb/kY-C4o7RThfWrDQsLCAG4q4clZhBDDfJQVhWUEKxXAzyQYMj4Jmq1zmFwpRqxhAJFPOa0AsW_PTSshoPuMnXNwq3rU7Imp15QimXTjlXMx0nC088mt1rIwRs75GnLLugWjSllxgzvQ9YrP4tBgclK4_rb17hjnusGj_c0u2fx0AvVokjSNB-v2poTj0xT9BZRCbzRE3-lF1.jpg?1617700061"), -}; - -pub static UNIFI_PROTOCOL_DAO_56_6B814D8B: TokenInfo = TokenInfo { - name: "Unifi Protocol DAO", - symbol: "UNFI", - decimals: 18, - contract: address!("0x728C5baC3C3e370E372Fc4671f9ef6916b814d8B"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/13152/thumb/logo-2.png?1605748967"), -}; - -pub static UNISWAP_56_A02CE9B1: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0xBf5140A22578168FD562DCcF235E5D43A02ce9B1"), - chain: 56, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static PAWTOCOL_56_94334EE4: TokenInfo = TokenInfo { - name: "Pawtocol", - symbol: "UPI", - decimals: 18, - contract: address!("0x0D35A2B85c5A63188d566D104bEbf7C694334Ee4"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12186/thumb/pawtocol.jpg?1597962008"), -}; - -pub static USDCOIN_56_32CD580D: TokenInfo = TokenInfo { - name: "USDCoin", - symbol: "USDC", - decimals: 18, - contract: address!("0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d"), - chain: 56, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), -}; - -pub static TETHER_USD_56_B3197955: TokenInfo = TokenInfo { - name: "Tether USD", - symbol: "USDT", - decimals: 18, - contract: address!("0x55d398326f99059fF775485246999027B3197955"), - chain: 56, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), -}; - -pub static WRAPPED_BNB: TokenInfo = TokenInfo { - name: "Wrapped BNB", - symbol: "WBNB", - decimals: 18, - contract: address!("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"), - chain: 56, - logo_uri: Some("https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/smartchain/assets/0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c/logo.png"), -}; - -pub static WRAPPED_ETHER_56_59F933F8: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0x2170Ed0880ac9A755fd29B2688956BD959F933F8"), - chain: 56, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static WOO_NETWORK_56_9E945D4B: TokenInfo = TokenInfo { - name: "WOO Network", - symbol: "WOO", - decimals: 18, - contract: address!("0x4691937a7508860F876c9c0a2a617E7d9E945D4B"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), -}; - -pub static CHAIN_56_DF88A05B: TokenInfo = TokenInfo { - name: "Chain", - symbol: "XCN", - decimals: 18, - contract: address!("0x7324c7C0d95CEBC73eEa7E85CbAac0dBdf88a05b"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054"), -}; - -pub static LAYERZERO_56_F13271CD: TokenInfo = TokenInfo { - name: "LayerZero", - symbol: "ZRO", - decimals: 18, - contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), - chain: 56, - logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), -}; - -pub static TOKEN_1INCH_130_A9ACD06E: TokenInfo = TokenInfo { - name: "1inch", - symbol: "1INCH", - decimals: 18, - contract: address!("0xbe41cde1C5e75a7b6c2c70466629878aa9ACd06E"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), -}; - -pub static ANCIENT8_130_FEF7759A: TokenInfo = TokenInfo { - name: "Ancient8", - symbol: "A8", - decimals: 18, - contract: address!("0x44D618C366D7bC85945Bfc922ACad5B1feF7759A"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/39170/standard/A8_Token-04_200x200.png?1720798300"), -}; - -pub static AAVE_130_BEEAAE1E: TokenInfo = TokenInfo { - name: "Aave", - symbol: "AAVE", - decimals: 18, - contract: address!("0x02a24C380dA560E4032Dc6671d8164cfbEEAAE1e"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), -}; - -pub static ARCBLOCK_130_FE5675BC: TokenInfo = TokenInfo { - name: "Arcblock", - symbol: "ABT", - decimals: 18, - contract: address!("0xDDCe42b89215548beCaA160048460747Fe5675bC"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2341/thumb/arcblock.png?1547036543"), -}; - -pub static ALCHEMY_PAY_130_E66ECF77: TokenInfo = TokenInfo { - name: "Alchemy Pay", - symbol: "ACH", - decimals: 8, - contract: address!("0xb8A8e137A2dAa25EF1B3577b6598fE8Be66Ecf77"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12390/thumb/ACH_%281%29.png?1599691266"), -}; - -pub static ACROSS_PROTOCOL_TOKEN_130_62BBB32C: TokenInfo = TokenInfo { - name: "Across Protocol Token", - symbol: "ACX", - decimals: 18, - contract: address!("0x34424B3352af905e41078a4029b61EDe62BbB32C"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165"), -}; - -pub static AMBIRE_ADEX_130_A299A500: TokenInfo = TokenInfo { - name: "Ambire AdEx", - symbol: "ADX", - decimals: 18, - contract: address!("0x3e1C572d8b069fc2f14ac4f8bdCE6e8eA299A500"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540"), -}; - -pub static AERGO_130_F15873B5: TokenInfo = TokenInfo { - name: "Aergo", - symbol: "AERGO", - decimals: 18, - contract: address!("0xfd38ac2316f6d3631a86065aDb3292f6f15873B5"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/4490/thumb/aergo.png?1647696770"), -}; - -pub static AEVO_130_60D60F8B: TokenInfo = TokenInfo { - name: "Aevo", - symbol: "AEVO", - decimals: 18, - contract: address!("0x54FA9210cCB765639b7Fd532f25bCb1060D60F8B"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/35893/standard/aevo.png"), -}; - -pub static AGEUR_130_C681A118: TokenInfo = TokenInfo { - name: "agEur", - symbol: "agEUR", - decimals: 18, - contract: address!("0xA4eeF95995F40aD0b3D63a474293Fc7CC681A118"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), -}; - -pub static ADVENTURE_GOLD_130_412721CF: TokenInfo = TokenInfo { - name: "Adventure Gold", - symbol: "AGLD", - decimals: 18, - contract: address!("0x14421614587A2A3e9C3Aa3131Fc396aF412721CF"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/18125/thumb/lpgblc4h_400x400.jpg?1630570955"), -}; - -pub static AIOZ_NETWORK_130_6CF99B1A: TokenInfo = TokenInfo { - name: "AIOZ Network", - symbol: "AIOZ", - decimals: 18, - contract: address!("0x5F891E74947b0FC400128E5E85333d7a6cF99b1A"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126"), -}; - -pub static ALCHEMIX_130_5AEBDCD6: TokenInfo = TokenInfo { - name: "Alchemix", - symbol: "ALCX", - decimals: 18, - contract: address!("0xbf194C82A5Bb9180f9280c1832f886a65Aebdcd6"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14113/thumb/Alchemix.png?1614409874"), -}; - -pub static ALEPH_IM_130_4C15BB5C: TokenInfo = TokenInfo { - name: "Aleph im", - symbol: "ALEPH", - decimals: 18, - contract: address!("0xa3E646211a456e08829C33fcE21cC3DC4c15Bb5c"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725"), -}; - -pub static ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_130_EEC73780: TokenInfo = TokenInfo { - name: "Alethea Artificial Liquid Intelligence", - symbol: "ALI", - decimals: 18, - contract: address!("0x2a87dd1e1F849ed88C18565AFDa98e2EEEc73780"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848"), -}; - -pub static MY_NEIGHBOR_ALICE_130_8860960A: TokenInfo = TokenInfo { - name: "My Neighbor Alice", - symbol: "ALICE", - decimals: 6, - contract: address!("0xBb72B8031F590748d8910Aad7e25F8B18860960a"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14375/thumb/alice_logo.jpg?1615782968"), -}; - -pub static ALPHA_VENTURE_DAO_130_CEBD78D3: TokenInfo = TokenInfo { - name: "Alpha Venture DAO", - symbol: "ALPHA", - decimals: 18, - contract: address!("0x44c3E7c49C4Bb6f4f5eCD87E035176dFceBD78d3"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876"), -}; - -pub static ALTLAYER_130_B3589153: TokenInfo = TokenInfo { - name: "AltLayer", - symbol: "ALT", - decimals: 18, - contract: address!("0x6D5De04F1a3E0e554B9A15059d03e20cb3589153"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/34608/standard/Logomark_200x200.png"), -}; - -pub static AMP_130_2BBC967F: TokenInfo = TokenInfo { - name: "Amp", - symbol: "AMP", - decimals: 18, - contract: address!("0x4D6B8ecb576dF9BB4bF6E6764A469a762bBc967F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12409/thumb/amp-200x200.png?1599625397"), -}; - -pub static ANKR_130_EFF97622: TokenInfo = TokenInfo { - name: "Ankr", - symbol: "ANKR", - decimals: 18, - contract: address!("0xf081Fc8E0878D7eBe6ec381E5d7279d6EFf97622"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978"), -}; - -pub static ARAGON_130_D4A31308: TokenInfo = TokenInfo { - name: "Aragon", - symbol: "ANT", - decimals: 18, - contract: address!("0x865d184885200B8e86eb2a3Da8b3B4a7d4A31308"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/681/thumb/JelZ58cv_400x400.png?1601449653"), -}; - -pub static APECOIN_130_314046CF: TokenInfo = TokenInfo { - name: "ApeCoin", - symbol: "APE", - decimals: 18, - contract: address!("0xD1b8423FdE5F37464FadE603f80903cB314046cf"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/24383/small/apecoin.jpg?1647476455"), -}; - -pub static API3_130_F678961B: TokenInfo = TokenInfo { - name: "API3", - symbol: "API3", - decimals: 18, - contract: address!("0xA63122b27308EED0C1D83DD355ADdaA7f678961b"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13256/thumb/api3.jpg?1606751424"), -}; - -pub static APU_APUSTAJA_130_63B9E379: TokenInfo = TokenInfo { - name: "Apu Apustaja", - symbol: "APU", - decimals: 18, - contract: address!("0xcDfcE5eb357E8976A80Be84E94a03BA963b9e379"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/35986/large/200x200.png?1710308147"), -}; - -pub static ARBITRUM_130_18A4B40D: TokenInfo = TokenInfo { - name: "Arbitrum", - symbol: "ARB", - decimals: 18, - contract: address!("0x5cC70a9DF8E293aFFb14DFCa1e7F851418a4b40d"), - chain: 130, - logo_uri: Some("https://arbitrum.foundation/logo.png"), -}; - -pub static ARKHAM_130_442EF089: TokenInfo = TokenInfo { - name: "Arkham", - symbol: "ARKM", - decimals: 18, - contract: address!("0x59F16BaA7A22f49c32680661e0041A53442Ef089"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/30929/standard/Arkham_Logo_CG.png?1696529771"), -}; - -pub static ARPA_CHAIN_130_88E30B45: TokenInfo = TokenInfo { - name: "ARPA Chain", - symbol: "ARPA", - decimals: 18, - contract: address!("0xE911A809F87490406AB34fad701aabCA88e30b45"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357"), -}; - -pub static ASH_130_5A30D7FB: TokenInfo = TokenInfo { - name: "ASH", - symbol: "ASH", - decimals: 18, - contract: address!("0x4b355De6Ea44711f0353Ed89545705395a30d7Fb"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/15714/thumb/omnPqaTY.png?1622820503"), -}; - -pub static ASSEMBLE_PROTOCOL_130_5BA0ADA7: TokenInfo = TokenInfo { - name: "Assemble Protocol", - symbol: "ASM", - decimals: 18, - contract: address!("0x1e196D83e2c562de0b1f270Eb72220335bA0ADa7"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11605/thumb/gpvrlkSq_400x400_%281%29.jpg?1591775789"), -}; - -pub static AIRSWAP_130_8C09AE56: TokenInfo = TokenInfo { - name: "AirSwap", - symbol: "AST", - decimals: 4, - contract: address!("0x7F3F14A49FE5D5009E4e0a09e76cB8468C09Ae56"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1019/thumb/Airswap.png?1630903484"), -}; - -pub static AUTOMATA_130_D890C4B2: TokenInfo = TokenInfo { - name: "Automata", - symbol: "ATA", - decimals: 18, - contract: address!("0xBAAa314d2f5Af29B00867a612F24F816d890C4B2"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745"), -}; - -pub static AETHIR_TOKEN_130_FEE183AB: TokenInfo = TokenInfo { - name: "Aethir Token", - symbol: "ATH", - decimals: 18, - contract: address!("0xa249732271cbA6E06Be4ac8B20f0D465FeE183Ab"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/36179/large/logogram_circle_dark_green_vb_green_(1).png?1718232706"), -}; - -pub static BOUNCE_130_91BEF68E: TokenInfo = TokenInfo { - name: "Bounce", - symbol: "AUCTION", - decimals: 18, - contract: address!("0x82F90996a4F67Eb388116B3C6F35B6Ea91BeF68E"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13860/thumb/1_KtgpRIJzuwfHe0Rl0avP_g.jpeg?1612412025"), -}; - -pub static AUDIUS_130_3C81684B: TokenInfo = TokenInfo { - name: "Audius", - symbol: "AUDIO", - decimals: 18, - contract: address!("0x48b8441dE79cEE3604b805093B41028d3c81684B"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12913/thumb/AudiusCoinLogo_2x.png?1603425727"), -}; - -pub static ARTVERSE_TOKEN_130_00939999: TokenInfo = TokenInfo { - name: "Artverse Token", - symbol: "AVT", - decimals: 18, - contract: address!("0x38DBf47e2a012a4b83823f15E3F3352A00939999"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/19727/thumb/ewnektoB_400x400.png?1635767094"), -}; - -pub static AXELAR_130_A4CBF2C9: TokenInfo = TokenInfo { - name: "Axelar", - symbol: "AXL", - decimals: 6, - contract: address!("0xbF678793522638F7439aFE3B94d2D2A3a4cBF2C9"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg"), -}; - -pub static AXIE_INFINITY_130_D188F927: TokenInfo = TokenInfo { - name: "Axie Infinity", - symbol: "AXS", - decimals: 18, - contract: address!("0xDA63AdA216d2079B54F2047B2FdC2576D188f927"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082"), -}; - -pub static BADGER_DAO_130_17388406: TokenInfo = TokenInfo { - name: "Badger DAO", - symbol: "BADGER", - decimals: 18, - contract: address!("0xc2a564b44b441D03f09f5B6B2b358B4a17388406"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13287/thumb/badger_dao_logo.jpg?1607054976"), -}; - -pub static BALANCER_130_34A8ADDF: TokenInfo = TokenInfo { - name: "Balancer", - symbol: "BAL", - decimals: 18, - contract: address!("0x01625E26274Ed828Ac1d47694c97221b34a8ADdF"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png"), -}; - -pub static BAND_PROTOCOL_130_6A8857D5: TokenInfo = TokenInfo { - name: "Band Protocol", - symbol: "BAND", - decimals: 18, - contract: address!("0xa264F2b88C630f260AbDcAb577eAB7266A8857d5"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/9545/thumb/band-protocol.png?1568730326"), -}; - -pub static BASIC_ATTENTION_TOKEN_130_508EA589: TokenInfo = TokenInfo { - name: "Basic Attention Token", - symbol: "BAT", - decimals: 18, - contract: address!("0x4e373C99199773f9D92d32B8c8Bc0C81508ea589"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427"), -}; - -pub static BEAM_130_F9500824: TokenInfo = TokenInfo { - name: "Beam", - symbol: "BEAM", - decimals: 18, - contract: address!("0xe5ECB192f1aE5839eD49886F36dFA670f9500824"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/32417/standard/chain-logo.png?1698114384"), -}; - -pub static BICONOMY_130_1D0588E7: TokenInfo = TokenInfo { - name: "Biconomy", - symbol: "BICO", - decimals: 18, - contract: address!("0x604Ff88ADC02325EFb7f93DB3E442dc81D0588E7"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749"), -}; - -pub static BIG_TIME_130_D2FA7CDC: TokenInfo = TokenInfo { - name: "Big Time", - symbol: "BIGTIME", - decimals: 18, - contract: address!("0x17f3AfE72cAa6b9090801b60607918b6D2Fa7cdc"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/32251/standard/-6136155493475923781_121.jpg?1696998691"), -}; - -pub static BITDAO_130_FB523A5C: TokenInfo = TokenInfo { - name: "BitDAO", - symbol: "BIT", - decimals: 18, - contract: address!("0xA4Cb2aaf7503641B441e80fC353e6748fb523A5C"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/17627/thumb/rI_YptK8.png?1653983088"), -}; - -pub static HARRYPOTTEROBAMASONIC10INU_130_9B3D706F: TokenInfo = TokenInfo { - name: "HarryPotterObamaSonic10Inu", - symbol: "BITCOIN", - decimals: 8, - contract: address!("0x41f6e69166e81A9583DBc96604B01D2E9B3D706f"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224"), -}; - -pub static BLUR_130_2B9255EA: TokenInfo = TokenInfo { - name: "Blur", - symbol: "BLUR", - decimals: 18, - contract: address!("0x942fC6b61686e06fB411cB1bCf5d16DC2b9255eA"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/28453/large/blur.png?1670745921"), -}; - -pub static BLUZELLE_130_8EF471EE: TokenInfo = TokenInfo { - name: "Bluzelle", - symbol: "BLZ", - decimals: 18, - contract: address!("0xe7b3Ca9d9Db06E1867781fd1C5F02E6c8eF471ee"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2848/thumb/ColorIcon_3x.png?1622516510"), -}; - -pub static BANCOR_NETWORK_TOKEN_130_472C5A62: TokenInfo = TokenInfo { - name: "Bancor Network Token", - symbol: "BNT", - decimals: 18, - contract: address!("0xf2Cc2D274dA528AB64DA86bE3f8416E5472c5a62"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png"), -}; - -pub static BOBA_NETWORK_130_BBB41B05: TokenInfo = TokenInfo { - name: "Boba Network", - symbol: "BOBA", - decimals: 18, - contract: address!("0xBE8E46422fB7F9Ca9D639B3109492D64BbB41b05"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/20285/thumb/BOBA.png?1636811576"), -}; - -pub static BARNBRIDGE_130_61DF8972: TokenInfo = TokenInfo { - name: "BarnBridge", - symbol: "BOND", - decimals: 18, - contract: address!("0x4d5b7e9CCE3Ab81298dA7E1F52b48c9a61Df8972"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853"), -}; - -pub static BONK: TokenInfo = TokenInfo { - name: "BONK", - symbol: "BONK", - decimals: 5, - contract: address!("0xBbE97f3522101e5B6976cBf77376047097BA837F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/28600/standard/bonk.jpg?1696527587"), -}; - -pub static BRAINTRUST_130_00986B71: TokenInfo = TokenInfo { - name: "Braintrust", - symbol: "BTRST", - decimals: 18, - contract: address!("0x6A4a359C7453F5892392FCb8eAB7A9A100986B71"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/18100/thumb/braintrust.PNG?1630475394"), -}; - -pub static BINANCE_USD_130_BDA9F9C6: TokenInfo = TokenInfo { - name: "Binance USD", - symbol: "BUSD", - decimals: 18, - contract: address!("0xa4da5c92F44422dFA3E2E309b53d93bbbDa9f9c6"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), -}; - -pub static COIN98_130_F8E4F8E1: TokenInfo = TokenInfo { - name: "Coin98", - symbol: "C98", - decimals: 18, - contract: address!("0x29129fa2e0F35594ca7b362fFA8c80f5f8e4f8E1"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/17117/thumb/logo.png?1626412904"), -}; - -pub static COINBASE_WRAPPED_BTC_130_AB6A1EF1: TokenInfo = TokenInfo { - name: "Coinbase Wrapped BTC", - symbol: "cbBTC", - decimals: 8, - contract: address!("0xb6A3E8e5715fd4c99EcEDaaAe121bDe4Ab6a1Ef1"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/40143/standard/cbbtc.webp"), -}; - -pub static COINBASE_WRAPPED_STAKED_ETH_130_8211DB59: TokenInfo = TokenInfo { - name: "Coinbase Wrapped Staked ETH", - symbol: "cbETH", - decimals: 18, - contract: address!("0xEb64b50FeF2A363940369285F86Ae9a68211db59"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/27008/large/cbeth.png"), -}; - -pub static CELO_NATIVE_ASSET_WORMHOLE_130_5A8A8D9C: TokenInfo = TokenInfo { - name: "Celo native asset (Wormhole)", - symbol: "CELO", - decimals: 18, - contract: address!("0x6008F5BaD83742fDbFf5AAc55e3c51b65A8A8D9C"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png"), -}; - -pub static CELER_NETWORK_130_48035703: TokenInfo = TokenInfo { - name: "Celer Network", - symbol: "CELR", - decimals: 18, - contract: address!("0x5AD5d6B1AE6761Aab12066b51D21729248035703"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/4379/thumb/Celr.png?1554705437"), -}; - -pub static CHROMIA_130_210A4E5B: TokenInfo = TokenInfo { - name: "Chromia", - symbol: "CHR", - decimals: 6, - contract: address!("0xAC930Be88cFAc775A937E9291c4234Bf210a4e5b"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/5000/thumb/Chromia.png?1559038018"), -}; - -pub static CHILIZ_130_8B2396B0: TokenInfo = TokenInfo { - name: "Chiliz", - symbol: "CHZ", - decimals: 18, - contract: address!("0xb0C69e24450e29afa8008962052007E08b2396b0"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/8834/thumb/Chiliz.png?1561970540"), -}; - -pub static CLOVER_FINANCE_130_FA41404C: TokenInfo = TokenInfo { - name: "Clover Finance", - symbol: "CLV", - decimals: 18, - contract: address!("0xD7212097f6d6B195a9Bc350b8dCE28a7fA41404C"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/15278/thumb/clover.png?1645084454"), -}; - -pub static COMPOUND_130_F2288656: TokenInfo = TokenInfo { - name: "Compound", - symbol: "COMP", - decimals: 18, - contract: address!("0xdf78e4F0A8279942ca68046476919A90f2288656"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), -}; - -pub static COTI_130_32F499C3: TokenInfo = TokenInfo { - name: "COTI", - symbol: "COTI", - decimals: 18, - contract: address!("0xc63612B3e697AEeC61C3Ce9baEc0f9Db32F499C3"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2962/thumb/Coti.png?1559653863"), -}; - -pub static CIRCUITS_OF_VALUE_130_CC295BEC: TokenInfo = TokenInfo { - name: "Circuits of Value", - symbol: "COVAL", - decimals: 8, - contract: address!("0x2562DC34c21371613CEF236b321EE63fCC295beC"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/588/thumb/coval-logo.png?1599493950"), -}; - -pub static COW_PROTOCOL_130_B26D3996: TokenInfo = TokenInfo { - name: "CoW Protocol", - symbol: "COW", - decimals: 18, - contract: address!("0xC3a97c76AA194711E05Ff1d181534090B26D3996"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/24384/large/CoW-token_logo.png?1719524382"), -}; - -pub static CLEARPOOL_130_423DFB57: TokenInfo = TokenInfo { - name: "Clearpool", - symbol: "CPOOL", - decimals: 18, - contract: address!("0xF8E7B485CE10D3C7Ac30B8444B98a0cC423dFb57"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/19252/large/photo_2022-08-31_12.45.02.jpeg?1696518697"), -}; - -pub static COVALENT_130_621F90C1: TokenInfo = TokenInfo { - name: "Covalent", - symbol: "CQT", - decimals: 18, - contract: address!("0x6C28eeB9E018011d3841f42c5b458713621F90C1"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14168/thumb/covalent-cqt.png?1624545218"), -}; - -pub static CRONOS_130_A30DE818: TokenInfo = TokenInfo { - name: "Cronos", - symbol: "CRO", - decimals: 8, - contract: address!("0x73c63A80Ec77BFe31eEc6663828C4beaA30dE818"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/7310/thumb/oCw2s3GI_400x400.jpeg?1645172042"), -}; - -pub static CRYPTERIUM_130_18B0D066: TokenInfo = TokenInfo { - name: "Crypterium", - symbol: "CRPT", - decimals: 18, - contract: address!("0x7e7784f13029c7C4BF4746112B1A503818B0D066"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1901/thumb/crypt.png?1547036205"), -}; - -pub static CURVE_DAO_TOKEN_130_D1C2CCB3: TokenInfo = TokenInfo { - name: "Curve DAO Token", - symbol: "CRV", - decimals: 18, - contract: address!("0xAC73671a1762FE835208Fb93b7aE7490d1c2cCb3"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), -}; - -pub static CARTESI_130_BAAED2C5: TokenInfo = TokenInfo { - name: "Cartesi", - symbol: "CTSI", - decimals: 18, - contract: address!("0xa7073F530856cD32c2037150dd9763B9BAaED2C5"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), -}; - -pub static CRYPTEX_FINANCE_130_62FCB619: TokenInfo = TokenInfo { - name: "Cryptex Finance", - symbol: "CTX", - decimals: 18, - contract: address!("0x36fA435F6def83cbB7a0706d035C9eA062fCb619"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171"), -}; - -pub static SOMNIUM_SPACE_CUBES_130_92C2F8AF: TokenInfo = TokenInfo { - name: "Somnium Space CUBEs", - symbol: "CUBE", - decimals: 8, - contract: address!("0xE60e9b2E68297d5DF6B383fEe787B7fB92c2F8aF"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/10687/thumb/CUBE_icon.png?1617026861"), -}; - -pub static CIVIC_130_E85A01ED: TokenInfo = TokenInfo { - name: "Civic", - symbol: "CVC", - decimals: 8, - contract: address!("0x35C458aD1e3e68d2717C8349b985384Be85a01Ed"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556"), -}; - -pub static CONVEX_FINANCE_130_F0087EA5: TokenInfo = TokenInfo { - name: "Convex Finance", - symbol: "CVX", - decimals: 18, - contract: address!("0x1C6789F30e7E335c2Eca2c75EC193aDBF0087Ea5"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/15585/thumb/convex.png?1621256328"), -}; - -pub static COVALENT_X_TOKEN_130_F14E5A09: TokenInfo = TokenInfo { - name: "Covalent X Token", - symbol: "CXT", - decimals: 18, - contract: address!("0x8E29E12B46FeE20E034fE1e812bc12EFf14E5A09"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/39177/large/CXT_Ticker.png?1720829918"), -}; - -pub static DAI_STABLECOIN_130_19573F81: TokenInfo = TokenInfo { - name: "Dai Stablecoin", - symbol: "DAI", - decimals: 18, - contract: address!("0x20CAb320A855b39F724131C69424240519573f81"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), -}; - -pub static MINES_OF_DALARNIA_130_90288086: TokenInfo = TokenInfo { - name: "Mines of Dalarnia", - symbol: "DAR", - decimals: 6, - contract: address!("0x2ef0775A19d1bc2258653fc5529F8f8490288086"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/19837/thumb/dar.png?1636014223"), -}; - -pub static DERIVADAO_130_3A270265: TokenInfo = TokenInfo { - name: "DerivaDAO", - symbol: "DDX", - decimals: 18, - contract: address!("0x91ED4bb192e3461E45575730508525083A270265"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13453/thumb/ddx_logo.png?1608741641"), -}; - -pub static DENT_130_328E874C: TokenInfo = TokenInfo { - name: "Dent", - symbol: "DENT", - decimals: 8, - contract: address!("0x45a4f750d806498A4c7f7B5267815aaC328e874C"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1152/thumb/gLCEA2G.png?1604543239"), -}; - -pub static DEXTOOLS_130_1723CDDD: TokenInfo = TokenInfo { - name: "DexTools", - symbol: "DEXT", - decimals: 18, - contract: address!("0x17C38207334011a131b0Acf200E35Cd81723cddd"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188"), -}; - -pub static DIA_130_3F9543C2: TokenInfo = TokenInfo { - name: "DIA", - symbol: "DIA", - decimals: 18, - contract: address!("0x4bdc8553cf14EEBCD489cD1d75b7FF463f9543c2"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751"), -}; - -pub static DISTRICT0X_130_C1B9E545: TokenInfo = TokenInfo { - name: "district0x", - symbol: "DNT", - decimals: 18, - contract: address!("0x0eb07cE7a28FF84DF132fb5ee5F56Aabc1b9E545"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/849/thumb/district0x.png?1547223762"), -}; - -pub static DOGECOIN: TokenInfo = TokenInfo { - name: "Dogecoin", - symbol: "DOGE", - decimals: 18, - contract: address!("0x12E96C2BFEA6E835CF8Dd38a5834fa61Cf723736"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/5/standard/dogecoin.png?1696501409"), -}; - -pub static DEFI_PULSE_INDEX_130_CD2F84F1: TokenInfo = TokenInfo { - name: "DeFi Pulse Index", - symbol: "DPI", - decimals: 18, - contract: address!("0xE274f564c37aE15fd2570D544102eD4ACd2f84f1"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12465/thumb/defi_pulse_index_set.png?1600051053"), -}; - -pub static DREP_130_38EA9EE7: TokenInfo = TokenInfo { - name: "Drep", - symbol: "DREP", - decimals: 18, - contract: address!("0x56aF109D597eb0a0F79ebCD0786Dd88C38EA9Ee7"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14578/thumb/KotgsCgS_400x400.jpg?1617094445"), -}; - -pub static DYDX_130_5FAEB82C: TokenInfo = TokenInfo { - name: "dYdX", - symbol: "DYDX", - decimals: 18, - contract: address!("0x601b11907EAa8d3785C0b10b41C3a7315faeB82c"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/17500/thumb/hjnIm9bV.jpg?1628009360"), -}; - -pub static DEFI_YIELD_PROTOCOL_130_9D598610: TokenInfo = TokenInfo { - name: "DeFi Yield Protocol", - symbol: "DYP", - decimals: 18, - contract: address!("0xBdaD8E37a9600F0A35976fE61608a4C89D598610"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066"), -}; - -pub static EIGENLAYER_130_D016C47D: TokenInfo = TokenInfo { - name: "EigenLayer", - symbol: "EIGEN", - decimals: 18, - contract: address!("0xc89ab9B82610BB9b748F6757b8F3ac59d016C47D"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/37441/large/eigen.jpg?1728023974"), -}; - -pub static ELASTOS_130_D8E8C1AB: TokenInfo = TokenInfo { - name: "Elastos", - symbol: "ELA", - decimals: 18, - contract: address!("0x24aBc32215354Ba3eD224bfa6312E31dD8E8c1ab"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2780/thumb/Elastos.png?1597048112"), -}; - -pub static DOGELON_MARS_130_26C1DE05: TokenInfo = TokenInfo { - name: "Dogelon Mars", - symbol: "ELON", - decimals: 18, - contract: address!("0x91441fE1415B00bEA8930A4354Fe00c426C1DE05"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413"), -}; - -pub static ETHENA_130_A6CBD2DD: TokenInfo = TokenInfo { - name: "Ethena", - symbol: "ENA", - decimals: 18, - contract: address!("0x9116E70d613860D349495d9Ef8e2AE1cA6cBD2dd"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/36530/standard/ethena.png"), -}; - -pub static ENJIN_COIN_130_84A6D0A6: TokenInfo = TokenInfo { - name: "Enjin Coin", - symbol: "ENJ", - decimals: 18, - contract: address!("0x9A0D1b7594CAAF0A9e4687cAc9fF4E0B84a6d0A6"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1102/thumb/enjin-coin-logo.png?1547035078"), -}; - -pub static ETHEREUM_NAME_SERVICE_130_B5F0383A: TokenInfo = TokenInfo { - name: "Ethereum Name Service", - symbol: "ENS", - decimals: 18, - contract: address!("0x80756FAf1e7Fec5678bf505670eF176AB5F0383a"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140"), -}; - -pub static ETHERNITY_CHAIN_130_A93CDB03: TokenInfo = TokenInfo { - name: "Ethernity Chain", - symbol: "ERN", - decimals: 18, - contract: address!("0x5E5903C236E6873EB8400C3d1979271Fa93cdB03"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14238/thumb/LOGO_HIGH_QUALITY.png?1647831402"), -}; - -pub static ETHER_FI_130_58880821: TokenInfo = TokenInfo { - name: "Ether.fi", - symbol: "ETHFI", - decimals: 18, - contract: address!("0xF8740269F121327D03ff77BeD03a9A3258880821"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/35958/standard/etherfi.jpeg"), -}; - -pub static EULER_130_5B5D03FE: TokenInfo = TokenInfo { - name: "Euler", - symbol: "EUL", - decimals: 18, - contract: address!("0x6319F47719b6713b1624C1b3A8e2DBf15b5D03FE"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/26149/thumb/YCvKDfl8_400x400.jpeg?1656041509"), -}; - -pub static EURO_COIN_130_2813B0A8: TokenInfo = TokenInfo { - name: "Euro Coin", - symbol: "EURC", - decimals: 6, - contract: address!("0x72f34BC403a005A9Be390762EAa46ED42813B0a8"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420"), -}; - -pub static QUANTOZ_EURQ_130_24D7D72D: TokenInfo = TokenInfo { - name: "Quantoz EURQ", - symbol: "EURQ", - decimals: 6, - contract: address!("0xEc42461D9BbDF4eFB6481099253bBB7324D7d72d"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/51853/large/EURQ_1000px_Color.png?1732071269"), -}; - -pub static STABLR_EURO_130_9C36FB5F: TokenInfo = TokenInfo { - name: "StablR Euro", - symbol: "EURR", - decimals: 6, - contract: address!("0x7A1ef7fD6E0d708295D8FD0C30Fd437d9C36FB5f"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/53720/large/stablreuro-logo.png?1737125898"), -}; - -pub static HARVEST_FINANCE_130_31EE825F: TokenInfo = TokenInfo { - name: "Harvest Finance", - symbol: "FARM", - decimals: 18, - contract: address!("0x472E8be16Cc9823b9f6a73A34EA55c0c31ee825F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180"), -}; - -pub static FETCH_AI_130_DDD7DFE7: TokenInfo = TokenInfo { - name: "Fetch ai", - symbol: "FET", - decimals: 18, - contract: address!("0x45343279DefDAd803d81C06fBCf87936DDD7DFE7"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136"), -}; - -pub static STAFI_130_A10764A6: TokenInfo = TokenInfo { - name: "Stafi", - symbol: "FIS", - decimals: 18, - contract: address!("0xec9Be303f204864145CCC193aEb21B5fa10764A6"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991"), -}; - -pub static FLOKI_130_6C51FA81: TokenInfo = TokenInfo { - name: "FLOKI", - symbol: "FLOKI", - decimals: 9, - contract: address!("0x1b3EC249dc44a64bF5Cb8Afdd70e30c26c51fA81"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318"), -}; - -pub static FORTA_130_D87D94E5: TokenInfo = TokenInfo { - name: "Forta", - symbol: "FORT", - decimals: 18, - contract: address!("0xB20fD6fD28e1430f98a8C1e9A83C88E5D87D94e5"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/25060/thumb/Forta_lgo_%281%29.png?1655353696"), -}; - -pub static AMPLEFORTH_GOVERNANCE_TOKEN_130_2220F12E: TokenInfo = TokenInfo { - name: "Ampleforth Governance Token", - symbol: "FORTH", - decimals: 18, - contract: address!("0xFa004fa2ad8Ef993C2B0412baB776b182220F12e"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14917/thumb/photo_2021-04-22_00.00.03.jpeg?1619020835"), -}; - -pub static SHAPESHIFT_FOX_TOKEN_130_3B7A318E: TokenInfo = TokenInfo { - name: "ShapeShift FOX Token", - symbol: "FOX", - decimals: 18, - contract: address!("0xe0BB1924C17b39B71758F49a00D7c0363B7a318E"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622"), -}; - -pub static FRAX_130_D74132B9: TokenInfo = TokenInfo { - name: "Frax", - symbol: "FRAX", - decimals: 18, - contract: address!("0x8c7879bf25D678D9949F305857bD4437d74132B9"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), -}; - -pub static FANTOM_130_90DC7F0E: TokenInfo = TokenInfo { - name: "Fantom", - symbol: "FTM", - decimals: 18, - contract: address!("0xe99235A02958637a5e01575297fBBa3790dC7F0e"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016"), -}; - -pub static FUNCTION_X_130_1D7AF1AF: TokenInfo = TokenInfo { - name: "Function X", - symbol: "FX", - decimals: 18, - contract: address!("0x6F32725F82Bbb06FFdC04974db437fec1d7af1Af"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/8186/thumb/47271330_590071468072434_707260356350705664_n.jpg?1556096683"), -}; - -pub static FRAX_SHARE_130_062021D6: TokenInfo = TokenInfo { - name: "Frax Share", - symbol: "FXS", - decimals: 18, - contract: address!("0x79301DF2117C7F56859fD01b28bBAA61062021D6"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), -}; - -pub static GRAVITY_130_6FD8803C: TokenInfo = TokenInfo { - name: "Gravity", - symbol: "G", - decimals: 18, - contract: address!("0x481cB2C560fc3351833b582b92b965626fd8803C"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/39200/large/gravity.jpg?1721020647"), -}; - -pub static GALXE_130_443D8675: TokenInfo = TokenInfo { - name: "Galxe", - symbol: "GAL", - decimals: 18, - contract: address!("0x70b2b785061d4c91C76CF87692f85B5c443d8675"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533"), -}; - -pub static GALA_130_B560FAC9: TokenInfo = TokenInfo { - name: "GALA", - symbol: "GALA", - decimals: 8, - contract: address!("0x31A71801291774d267615f74b3a44FCEB560FAc9"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12493/standard/GALA-COINGECKO.png?1696512310"), -}; - -pub static GOLDFINCH_130_B157D3D0: TokenInfo = TokenInfo { - name: "Goldfinch", - symbol: "GFI", - decimals: 18, - contract: address!("0x0328A0255866706547B79072DEE54976b157d3D0"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/19081/thumb/GOLDFINCH.png?1634369662"), -}; - -pub static AAVEGOTCHI_130_840AD24B: TokenInfo = TokenInfo { - name: "Aavegotchi", - symbol: "GHST", - decimals: 18, - contract: address!("0x4aE5712A153fDfDE81C305fF7f2E4e59840aD24B"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12467/thumb/ghst_200.png?1600750321"), -}; - -pub static GOLEM_130_E2C9F2B9: TokenInfo = TokenInfo { - name: "Golem", - symbol: "GLM", - decimals: 18, - contract: address!("0x04b747f478AE09AC797d026C8402f409E2C9f2b9"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/542/thumb/Golem_Submark_Positive_RGB.png?1606392013"), -}; - -pub static GNOSIS_TOKEN_130_E125A938: TokenInfo = TokenInfo { - name: "Gnosis Token", - symbol: "GNO", - decimals: 18, - contract: address!("0xC4c6c3A3043Ad5ECe5c91290630A7735e125a938"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png"), -}; - -pub static GODS_UNCHAINED_130_D3683F48: TokenInfo = TokenInfo { - name: "Gods Unchained", - symbol: "GODS", - decimals: 18, - contract: address!("0x6E74EA6546e1f21Abf581b59114f2Bf5d3683f48"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/17139/thumb/10631.png?1635718182"), -}; - -pub static THE_GRAPH_130_B3204D71: TokenInfo = TokenInfo { - name: "The Graph", - symbol: "GRT", - decimals: 18, - contract: address!("0xBb2272Ffc0Ef8F439373aDffD45c3591B3204D71"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566"), -}; - -pub static GITCOIN_130_8FE5CF48: TokenInfo = TokenInfo { - name: "Gitcoin", - symbol: "GTC", - decimals: 18, - contract: address!("0x592620d454a10c47274dBfe3BD922b9a8fE5cf48"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929"), -}; - -pub static GEMINI_DOLLAR_130_5C0920A9: TokenInfo = TokenInfo { - name: "Gemini Dollar", - symbol: "GUSD", - decimals: 2, - contract: address!("0xEbA12eC786Cdc21b4bd5ba601B595b6A5C0920a9"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/5992/thumb/gemini-dollar-gusd.png?1536745278"), -}; - -pub static GYEN_130_A574C36F: TokenInfo = TokenInfo { - name: "GYEN", - symbol: "GYEN", - decimals: 6, - contract: address!("0xad173F5B5FE39DD1183a0d3C49C57629A574c36F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343"), -}; - -pub static HASHFLOW_130_8C34A28B: TokenInfo = TokenInfo { - name: "Hashflow", - symbol: "HFT", - decimals: 18, - contract: address!("0x656104f2028BbFD7144C8f71Fa15daaA8c34A28b"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/26136/large/hashflow-icon-cmc.png"), -}; - -pub static HIGHSTREET_130_B1374879: TokenInfo = TokenInfo { - name: "Highstreet", - symbol: "HIGH", - decimals: 18, - contract: address!("0x99F64C3Db98a4870eFf637315d5C86dcb1374879"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470"), -}; - -pub static HOPR_130_AF385B36: TokenInfo = TokenInfo { - name: "HOPR", - symbol: "HOPR", - decimals: 18, - contract: address!("0xc32C0c5a52F36D244C552E45C485cBceaf385B36"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14061/thumb/Shared_HOPR_logo_512px.png?1614073468"), -}; - -pub static HYPERLIQUID: TokenInfo = TokenInfo { - name: "Hyperliquid", - symbol: "HYPE", - decimals: 18, - contract: address!("0x15D0e0c55a3E7eE67152aD7E89acf164253Ff68d"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/50882/large/hyperliquid.jpg?1729431300"), -}; - -pub static IDEX_130_60EABE8E: TokenInfo = TokenInfo { - name: "IDEX", - symbol: "IDEX", - decimals: 18, - contract: address!("0x4eA052BcAeE7d7ef2E3D61D601e878A560eaBe8e"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2565/thumb/logomark-purple-286x286.png?1638362736"), -}; - -pub static ILLUVIUM_130_42F3E51F: TokenInfo = TokenInfo { - name: "Illuvium", - symbol: "ILV", - decimals: 18, - contract: address!("0xa76195FA77304Bba4cD8946198f5a90E42F3E51F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14468/large/ILV.JPG"), -}; - -pub static IMMUTABLE_X_130_F5AA8053: TokenInfo = TokenInfo { - name: "Immutable X", - symbol: "IMX", - decimals: 18, - contract: address!("0xc4Fc8cF76883094404DDb875d2AF15D1F5AA8053"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/17233/thumb/imx.png?1636691817"), -}; - -pub static INDEX_COOPERATIVE_130_121E39B7: TokenInfo = TokenInfo { - name: "Index Cooperative", - symbol: "INDEX", - decimals: 18, - contract: address!("0xa5Afe7646f07d2C41AA82Bb6AE09e99E121e39B7"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12729/thumb/index.png?1634894321"), -}; - -pub static INJECTIVE_130_9A89F9F8: TokenInfo = TokenInfo { - name: "Injective", - symbol: "INJ", - decimals: 18, - contract: address!("0x9361cA28625E12C7f088523B274A25059A89f9F8"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237"), -}; - -pub static INVERSE_FINANCE_130_9F7B54FB: TokenInfo = TokenInfo { - name: "Inverse Finance", - symbol: "INV", - decimals: 18, - contract: address!("0xD326ACaB8799fb44C3A5B7f7eFbAaB5f9F7b54fb"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14205/thumb/inverse_finance.jpg?1614921871"), -}; - -pub static IOTEX_130_E2B6843F: TokenInfo = TokenInfo { - name: "IoTeX", - symbol: "IOTX", - decimals: 18, - contract: address!("0xD749094Bc62615f0c8645467e241b71Ae2B6843F"), - chain: 130, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/2777.png"), -}; - -pub static GEOJAM_130_1D5C61A8: TokenInfo = TokenInfo { - name: "Geojam", - symbol: "JAM", - decimals: 18, - contract: address!("0x428c2B7Fa7a7821891fb529BAE4d80a71d5c61A8"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/24648/thumb/ey40AzBN_400x400.jpg?1648507272"), -}; - -pub static JASMYCOIN_130_22720708: TokenInfo = TokenInfo { - name: "JasmyCoin", - symbol: "JASMY", - decimals: 18, - contract: address!("0x8EF0686F380dD07f3e2121831839371922720708"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13876/thumb/JASMY200x200.jpg?1612473259"), -}; - -pub static JUPITER_130_E5CAB8B2: TokenInfo = TokenInfo { - name: "Jupiter", - symbol: "JUP", - decimals: 18, - contract: address!("0x781CC305fCBFe7cde376C9Ef5469d5a7E5CaB8b2"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/10351/thumb/logo512.png?1632480932"), -}; - -pub static JUPITER_130_2381AFAD: TokenInfo = TokenInfo { - name: "Jupiter", - symbol: "JUP", - decimals: 6, - contract: address!("0xbe51A5e8FA434F09663e8fB4CCe79d0B2381Afad"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/34188/standard/jup.png?1704266489"), -}; - -pub static KEEP_NETWORK_130_EA6AFE80: TokenInfo = TokenInfo { - name: "Keep Network", - symbol: "KEEP", - decimals: 18, - contract: address!("0x05DBd720fc26F732c8d42Ea89BD7F442EA6AFE80"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/3373/thumb/IuNzUb5b_400x400.jpg?1589526336"), -}; - -pub static SELFKEY_130_3F1BBFDC: TokenInfo = TokenInfo { - name: "SelfKey", - symbol: "KEY", - decimals: 18, - contract: address!("0x68Cea24F675e4F25584607F6c9feFb353f1bBfDc"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2034/thumb/selfkey.png?1548608934"), -}; - -pub static KYBER_NETWORK_CRYSTAL_130_B7CD2284: TokenInfo = TokenInfo { - name: "Kyber Network Crystal", - symbol: "KNC", - decimals: 18, - contract: address!("0xB0E4Ad2dFe3754e4a2443A7a828Eda5bB7Cd2284"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png"), -}; - -pub static KEEP3RV1_130_5FAD6A74: TokenInfo = TokenInfo { - name: "Keep3rV1", - symbol: "KP3R", - decimals: 18, - contract: address!("0x9C41547e404942C173E28bB2B6abE4cf5fad6A74"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12966/thumb/kp3r_logo.jpg?1607057458"), -}; - -pub static KRYLL_130_4F002943: TokenInfo = TokenInfo { - name: "KRYLL", - symbol: "KRL", - decimals: 18, - contract: address!("0x14CFFAD448AeB0876c56B7aa28999C9a4f002943"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979"), -}; - -pub static KUJIRA_130_30258681: TokenInfo = TokenInfo { - name: "Kujira", - symbol: "KUJI", - decimals: 6, - contract: address!("0x2206cdcC9B94fF7dB7A9eAbeC77b5cE430258681"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png"), -}; - -pub static LAYER3_130_1B7B482C: TokenInfo = TokenInfo { - name: "Layer3", - symbol: "L3", - decimals: 18, - contract: address!("0x1201209f55634bdDb67034efE4e8aA4D1B7B482C"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/37768/large/Square.png"), -}; - -pub static LCX_130_46687782: TokenInfo = TokenInfo { - name: "LCX", - symbol: "LCX", - decimals: 18, - contract: address!("0xb34b3DE63D22ffC90419c1a439de6C7d46687782"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/9985/thumb/zRPSu_0o_400x400.jpg?1574327008"), -}; - -pub static LIDO_DAO_130_814E8829: TokenInfo = TokenInfo { - name: "Lido DAO", - symbol: "LDO", - decimals: 18, - contract: address!("0x68A6dbc7214a0F2b0d875963663F1613814E8829"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644"), -}; - -pub static CHAINLINK_TOKEN_130_9BBEEFB7: TokenInfo = TokenInfo { - name: "ChainLink Token", - symbol: "LINK", - decimals: 18, - contract: address!("0x5a53B6D19D8EDCb7923F0D840EeBB3f09BBeEfB7"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), -}; - -pub static LITENTRY_130_91BE0FDF: TokenInfo = TokenInfo { - name: "Litentry", - symbol: "LIT", - decimals: 18, - contract: address!("0x68648F52B85407806bC1d349B745D13C91be0fDf"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13825/large/logo_200x200.png"), -}; - -pub static LEAGUE_OF_KINGDOMS_130_AAC89733: TokenInfo = TokenInfo { - name: "League of Kingdoms", - symbol: "LOKA", - decimals: 18, - contract: address!("0x1D1BFCFC6ae6FE045f151C7e589fB241AAC89733"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/22572/thumb/loka_64pix.png?1642643271"), -}; - -pub static LOOM_NETWORK_130_009F523C: TokenInfo = TokenInfo { - name: "Loom Network", - symbol: "LOOM", - decimals: 18, - contract: address!("0xc68992e0514968BfbA3Dad201fef91f6009f523c"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0/logo.png"), -}; - -pub static LIVEPEER_130_F35B73E3: TokenInfo = TokenInfo { - name: "Livepeer", - symbol: "LPT", - decimals: 18, - contract: address!("0x11c6B34caDC550B65A9666497d7FCb39f35B73E3"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/7137/thumb/logo-circle-green.png?1619593365"), -}; - -pub static LIQUITY_130_53C71A60: TokenInfo = TokenInfo { - name: "Liquity", - symbol: "LQTY", - decimals: 18, - contract: address!("0x0176B38b7767451b1B682236eCe2fae853C71a60"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180"), -}; - -pub static LOOPRINGCOIN_V2_130_A8AB158A: TokenInfo = TokenInfo { - name: "LoopringCoin V2", - symbol: "LRC", - decimals: 18, - contract: address!("0xA2af802b95D7e20167e5aeaC7Fe8fDf4a8aB158A"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png"), -}; - -pub static BLOCKLORDS_130_0C7BEE3F: TokenInfo = TokenInfo { - name: "BLOCKLORDS", - symbol: "LRDS", - decimals: 18, - contract: address!("0xD7eb7348Ba44c5A2f9f1D1d3534623230c7bee3F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/34775/standard/LRDS_PNG.png"), -}; - -pub static LIQUITY_USD_130_D72577FB: TokenInfo = TokenInfo { - name: "Liquity USD", - symbol: "LUSD", - decimals: 18, - contract: address!("0xf81B7485B4cB59645F74528D702c7f8CD72577FB"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327"), -}; - -pub static DECENTRALAND_130_00FE358B: TokenInfo = TokenInfo { - name: "Decentraland", - symbol: "MANA", - decimals: 18, - contract: address!("0x276361c863903751771e9DabA6dDfaAf00FE358b"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745"), -}; - -pub static MASK_NETWORK_130_1B9512C4: TokenInfo = TokenInfo { - name: "Mask Network", - symbol: "MASK", - decimals: 18, - contract: address!("0xC42B642F5010a2A3bD3CA2396Fe6f2e21B9512C4"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316"), -}; - -pub static MATH_130_99ED2C97: TokenInfo = TokenInfo { - name: "MATH", - symbol: "MATH", - decimals: 18, - contract: address!("0xB999b66186d7a48BF0Eb5d22f4E7053A99eD2C97"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590"), -}; - -pub static POLYGON_130_6507176B: TokenInfo = TokenInfo { - name: "Polygon", - symbol: "MATIC", - decimals: 18, - contract: address!("0xF6AC97B05B3bC92f829c7584b25839906507176b"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), -}; - -pub static MERIT_CIRCLE_130_2D657399: TokenInfo = TokenInfo { - name: "Merit Circle", - symbol: "MC", - decimals: 18, - contract: address!("0x460ec1C67e1614Bf1feAb84b98795BAE2d657399"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/19304/thumb/Db4XqML.png?1634972154"), -}; - -pub static MOSS_CARBON_CREDIT_130_7E6ACC40: TokenInfo = TokenInfo { - name: "Moss Carbon Credit", - symbol: "MCO2", - decimals: 18, - contract: address!("0x68619Bc0C709FB63555Fe988ed14e78f7E6ACc40"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14414/thumb/ENtxnThA_400x400.jpg?1615948522"), -}; - -pub static MEASURABLE_DATA_TOKEN_130_31BFEFF4: TokenInfo = TokenInfo { - name: "Measurable Data Token", - symbol: "MDT", - decimals: 18, - contract: address!("0xB29FddC20D5e4bacE9F54c1d9237953331BFeFF4"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2441/thumb/mdt_logo.png?1569813574"), -}; - -pub static MEMECOIN_130_8E3E7D06: TokenInfo = TokenInfo { - name: "Memecoin", - symbol: "MEME", - decimals: 18, - contract: address!("0x397E34AFF8bFc8Ec14aa78F378074F6d8E3E7d06"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/32528/large/memecoin_(2).png"), -}; - -pub static METIS_130_B3A8F102: TokenInfo = TokenInfo { - name: "Metis", - symbol: "METIS", - decimals: 18, - contract: address!("0xBfBa2A8745e5C85544DB7C8824C6962aB3A8f102"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312"), -}; - -pub static MAGIC_INTERNET_MONEY_130_3E3602AB: TokenInfo = TokenInfo { - name: "Magic Internet Money", - symbol: "MIM", - decimals: 18, - contract: address!("0x397C1f55FefF63C8947624b0d457a2CA3e3602ab"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612"), -}; - -pub static MIRROR_PROTOCOL_130_4A72D717: TokenInfo = TokenInfo { - name: "Mirror Protocol", - symbol: "MIR", - decimals: 18, - contract: address!("0x5FE989EaB3021d7e742099d05a7937bA4A72D717"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13295/thumb/mirror_logo_transparent.png?1611554658"), -}; - -pub static MELON_130_4DC3C117: TokenInfo = TokenInfo { - name: "Melon", - symbol: "MLN", - decimals: 18, - contract: address!("0xf7A581f6e26EEa790225d76Af8821EA34Dc3c117"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295"), -}; - -pub static MOG_COIN_130_78921EBD: TokenInfo = TokenInfo { - name: "Mog Coin", - symbol: "MOG", - decimals: 18, - contract: address!("0x58d68e179864605fEA06EAADF1185c6e78921Ebd"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/31059/large/MOG_LOGO_200x200.png"), -}; - -pub static MONAVALE_130_1C7A1087: TokenInfo = TokenInfo { - name: "Monavale", - symbol: "MONA", - decimals: 18, - contract: address!("0xAe6065FB0244A68036C82deC9a8dE5501c7A1087"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13298/thumb/monavale_logo.jpg?1607232721"), -}; - -pub static MOVEMENT_130_0FF19949: TokenInfo = TokenInfo { - name: "Movement", - symbol: "MOVE", - decimals: 8, - contract: address!("0xaa2109f14Bb155766cBA9E7fa8B8D4bF0ff19949"), - chain: 130, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/32452.png"), -}; - -pub static MAPLE_130_D752A219: TokenInfo = TokenInfo { - name: "Maple", - symbol: "MPL", - decimals: 18, - contract: address!("0x587e0E022b074015F4e81eCa489c0C41d752A219"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14097/thumb/photo_2021-05-03_14.20.41.jpeg?1620022863"), -}; - -pub static METAL_130_6CFAD9EA: TokenInfo = TokenInfo { - name: "Metal", - symbol: "MTL", - decimals: 8, - contract: address!("0x71d69d07914d087f1C3536F7A5006a256CfAd9Ea"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/763/thumb/Metal.png?1592195010"), -}; - -pub static MULTICHAIN_130_D82B4701: TokenInfo = TokenInfo { - name: "Multichain", - symbol: "MULTI", - decimals: 18, - contract: address!("0x1C3a8fB65Ab82D73e26B6403bf505B99d82b4701"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238"), -}; - -pub static MSTABLE_USD_130_B40A8DD1: TokenInfo = TokenInfo { - name: "mStable USD", - symbol: "MUSD", - decimals: 18, - contract: address!("0x10F109379E231d5c294ee6A5f9Abb2F8b40A8Dd1"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11576/thumb/mStable_USD.png?1595591803"), -}; - -pub static MUSE_DAO_130_81D5F345: TokenInfo = TokenInfo { - name: "Muse DAO", - symbol: "MUSE", - decimals: 18, - contract: address!("0xe3d92FB06a4EEbaC5879D3C1073e0eAB81D5f345"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13230/thumb/muse_logo.png?1606460453"), -}; - -pub static GENSOKISHI_METAVERSE_130_FF182974: TokenInfo = TokenInfo { - name: "GensoKishi Metaverse", - symbol: "MV", - decimals: 18, - contract: address!("0xD6ec6A24d5365A1811B05099f8D353c0Ff182974"), - chain: 130, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/17704.png"), -}; - -pub static MXC_130_02727794: TokenInfo = TokenInfo { - name: "MXC", - symbol: "MXC", - decimals: 18, - contract: address!("0xCF7c45Ccc1327ac1E9Cb9E098898c59402727794"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/4604/thumb/mxc.png?1655534336"), -}; - -pub static POLYSWARM_130_795032DF: TokenInfo = TokenInfo { - name: "PolySwarm", - symbol: "NCT", - decimals: 18, - contract: address!("0x328Ed7736871F863C8216Ca6CbB6f29B795032Df"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2843/thumb/ImcYCVfX_400x400.jpg?1628519767"), -}; - -pub static NEIRO_130_87696276: TokenInfo = TokenInfo { - name: "Neiro", - symbol: "Neiro", - decimals: 9, - contract: address!("0xc1C06527E810C4A198D8C5d35e1dDBc987696276"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/39488/large/neiro.jpg?1731449567"), -}; - -pub static NKN_130_336BAF62: TokenInfo = TokenInfo { - name: "NKN", - symbol: "NKN", - decimals: 18, - contract: address!("0x75b93cED9627Cd172912304Fb79Cd3e7336BaF62"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/3375/thumb/nkn.png?1548329212"), -}; - -pub static NUMERAIRE_130_DBDA20FC: TokenInfo = TokenInfo { - name: "Numeraire", - symbol: "NMR", - decimals: 18, - contract: address!("0x931e587542b8603EA3C6420dD8d3b22eDbdA20FC"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png"), -}; - -pub static NUCYPHER_130_AACEA6B9: TokenInfo = TokenInfo { - name: "NuCypher", - symbol: "NU", - decimals: 18, - contract: address!("0x2AEB5256de25ECed47797b82d2F5C404AACEA6b9"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/3318/thumb/photo1198982838879365035.jpg?1547037916"), -}; - -pub static OCEAN_PROTOCOL_130_3CD79208: TokenInfo = TokenInfo { - name: "Ocean Protocol", - symbol: "OCEAN", - decimals: 18, - contract: address!("0x652293F4e9b0ef61C52a78D6615D9f5f3cD79208"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686"), -}; - -pub static ORIGIN_PROTOCOL_130_EE18C880: TokenInfo = TokenInfo { - name: "Origin Protocol", - symbol: "OGN", - decimals: 18, - contract: address!("0xa60CE8f7ec6A091535b4708569B39DF5eE18c880"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878"), -}; - -pub static OMG_NETWORK_130_8EE37383: TokenInfo = TokenInfo { - name: "OMG Network", - symbol: "OMG", - decimals: 18, - contract: address!("0x5949b9200dF1e77878dB3D061e43cF878Ee37383"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/776/thumb/OMG_Network.jpg?1591167168"), -}; - -pub static OMNI_NETWORK_130_959EB0E3: TokenInfo = TokenInfo { - name: "Omni Network", - symbol: "OMNI", - decimals: 18, - contract: address!("0xf5614D20c13D5BF2F9e640f00B7B2B76959Eb0E3"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/36465/standard/Symbol-Color.png?1711511095"), -}; - -pub static ONDO_FINANCE_130_85321557: TokenInfo = TokenInfo { - name: "Ondo Finance", - symbol: "ONDO", - decimals: 18, - contract: address!("0xaD0bae21db0b471dFfC6f8F9EEacFe9A85321557"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/26580/standard/ONDO.png?1696525656"), -}; - -pub static ORCA_ALLIANCE_130_1BE3E8C0: TokenInfo = TokenInfo { - name: "ORCA Alliance", - symbol: "ORCA", - decimals: 18, - contract: address!("0xCF2050ebC80B74370C1C2B71bDB635d11be3E8c0"), - chain: 130, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/5183.png"), -}; - -pub static ORION_PROTOCOL_130_B6EAF396: TokenInfo = TokenInfo { - name: "Orion Protocol", - symbol: "ORN", - decimals: 8, - contract: address!("0x3C5319013FD75976F0f13b0bc0852537B6eaF396"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11841/thumb/orion_logo.png?1594943318"), -}; - -pub static ORCHID_130_52B98042: TokenInfo = TokenInfo { - name: "Orchid", - symbol: "OXT", - decimals: 18, - contract: address!("0x9775C2b4f245248dE5596252Ac69311152B98042"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4575f41308EC1483f3d399aa9a2826d74Da13Deb/logo.png"), -}; - -pub static PAYPEREX_130_0D292327: TokenInfo = TokenInfo { - name: "PayperEx", - symbol: "PAX", - decimals: 18, - contract: address!("0x3614c8d98Bf905AbE075BfA289231bbc0D292327"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1601/thumb/pax.png?1547035800"), -}; - -pub static PLAYDAPP_130_1E75D6AC: TokenInfo = TokenInfo { - name: "PlayDapp", - symbol: "PDA", - decimals: 18, - contract: address!("0xeC37cdfC9a692b3cCd5c85696D14aaA31E75d6aC"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14316/standard/PDA-symbol.png?1710234068"), -}; - -pub static PEPE_130_9074952B: TokenInfo = TokenInfo { - name: "Pepe", - symbol: "PEPE", - decimals: 18, - contract: address!("0xD9b5DA95B3D97c3E9872102fDb47d4c09074952B"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725"), -}; - -pub static PERPETUAL_PROTOCOL_130_CCFEC7D5: TokenInfo = TokenInfo { - name: "Perpetual Protocol", - symbol: "PERP", - decimals: 18, - contract: address!("0x5944D2728d5fea7D1F4AA4958E3aEbb3CCFEc7D5"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), -}; - -pub static PIRATE_NATION_130_18D064C6: TokenInfo = TokenInfo { - name: "Pirate Nation", - symbol: "PIRATE", - decimals: 18, - contract: address!("0xd0F77df9a8f0e855F910361f5f59958118d064c6"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/38524/standard/_Pirate_Transparent_200x200.png"), -}; - -pub static PLUTON_130_ABB6F6C7: TokenInfo = TokenInfo { - name: "Pluton", - symbol: "PLU", - decimals: 18, - contract: address!("0x5441619a9754Aee0665c939743cf7611abB6F6C7"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1241/thumb/pluton.png?1548331624"), -}; - -pub static POLYGON_ECOSYSTEM_TOKEN_130_E5682E95: TokenInfo = TokenInfo { - name: "Polygon Ecosystem Token", - symbol: "POL", - decimals: 18, - contract: address!("0xF6A49aEdbD7861DeD0DA2BE1f21C6954E5682E95"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/32440/large/polygon.png?1698233684"), -}; - -pub static POLKASTARTER_130_DC306503: TokenInfo = TokenInfo { - name: "Polkastarter", - symbol: "POLS", - decimals: 18, - contract: address!("0x82a98121eaf30b0E135b08d4208c837Cdc306503"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702"), -}; - -pub static POLYMATH_130_D538D863: TokenInfo = TokenInfo { - name: "Polymath", - symbol: "POLY", - decimals: 18, - contract: address!("0x2f5cfdC89fb96f2cf6c0FB1Ca6e3501Dd538D863"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034"), -}; - -pub static MARLIN_130_4D4782D5: TokenInfo = TokenInfo { - name: "Marlin", - symbol: "POND", - decimals: 18, - contract: address!("0xA2a36541c5a54bd2815985418105091B4D4782d5"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/8903/thumb/POND_200x200.png?1622515451"), -}; - -pub static PORTAL_130_0F2A5642: TokenInfo = TokenInfo { - name: "Portal", - symbol: "PORTAL", - decimals: 18, - contract: address!("0x562E588471cA0e710b2b1217867FFb2E0F2a5642"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/35436/standard/portal.jpeg"), -}; - -pub static POWER_LEDGER_130_DFFA6BFF: TokenInfo = TokenInfo { - name: "Power Ledger", - symbol: "POWR", - decimals: 6, - contract: address!("0xf265af514762286A63d015FeE382B90edfFa6bff"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1104/thumb/power-ledger.png?1547035082"), -}; - -pub static PRIME_130_CBF9FEE0: TokenInfo = TokenInfo { - name: "Prime", - symbol: "PRIME", - decimals: 18, - contract: address!("0xD17D5f0DA4200bBfd3D6626AC6aEA2eccbf9fEE0"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222"), -}; - -pub static PROPY_130_1F41A7C9: TokenInfo = TokenInfo { - name: "Propy", - symbol: "PRO", - decimals: 8, - contract: address!("0xC6Fbf362a12804FEca22000f37DB5EFC1F41A7c9"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/869/thumb/propy.png?1548332100"), -}; - -pub static PARSIQ_130_0ABF3DEF: TokenInfo = TokenInfo { - name: "PARSIQ", - symbol: "PRQ", - decimals: 18, - contract: address!("0xc7B7dcF3c6CAcAAc13F92c9173f9A0060ABf3def"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280"), -}; - -pub static PSTAKE_FINANCE_130_E7D7CAA2: TokenInfo = TokenInfo { - name: "pSTAKE Finance", - symbol: "PSTAKE", - decimals: 18, - contract: address!("0x13FE2c4504f3AA18708561250e2F20E4E7D7CAa2"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/23931/thumb/PSTAKE_Dark.png?1645709930"), -}; - -pub static PUFFER_FINANCE_130_38B560D2: TokenInfo = TokenInfo { - name: "Puffer Finance", - symbol: "PUFFER", - decimals: 18, - contract: address!("0xAdf70dc4AaeFbC6D1E7A6cF0B02b0F2138b560d2"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/50630/large/puffer.jpg?1728545297"), -}; - -pub static PAYPAL_USD_130_8E6207C5: TokenInfo = TokenInfo { - name: "PayPal USD", - symbol: "PYUSD", - decimals: 6, - contract: address!("0x0D2f98904D88909072eA6e61105CBBf78e6207c5"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/31212/large/PYUSD_Logo_%282%29.png?1691458314"), -}; - -pub static QUANT_130_98C360D4: TokenInfo = TokenInfo { - name: "Quant", - symbol: "QNT", - decimals: 18, - contract: address!("0x3a8723f2929F370c61EaC583d6652e5C98C360d4"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/3370/thumb/5ZOu7brX_400x400.jpg?1612437252"), -}; - -pub static QREDO_130_8C1068B8: TokenInfo = TokenInfo { - name: "Qredo", - symbol: "QRDO", - decimals: 8, - contract: address!("0x006254C4664C678e64c3265da28304cc8c1068b8"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/17541/thumb/qrdo.png?1630637735"), -}; - -pub static QUANTSTAMP_130_6BB5EABB: TokenInfo = TokenInfo { - name: "Quantstamp", - symbol: "QSP", - decimals: 18, - contract: address!("0xb019a038eaDCB2F96321D236F6633C8d6Bb5eAbB"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1219/thumb/0_E0kZjb4dG4hUnoDD_.png?1604815917"), -}; - -pub static QUICKSWAP_130_F8E6CAC2: TokenInfo = TokenInfo { - name: "Quickswap", - symbol: "QUICK", - decimals: 18, - contract: address!("0xD815958F92E6aBe63437BCe166E97027f8E6caC2"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13970/thumb/1_pOU6pBMEmiL-ZJVb0CYRjQ.png?1613386659"), -}; - -pub static RADICLE_130_F08A1A45: TokenInfo = TokenInfo { - name: "Radicle", - symbol: "RAD", - decimals: 18, - contract: address!("0x3F9A30c86DC7F0c657eA17d52Efe09Eff08a1a45"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14013/thumb/radicle.png?1614402918"), -}; - -pub static RAI_REFLEX_INDEX_130_89F34A66: TokenInfo = TokenInfo { - name: "Rai Reflex Index", - symbol: "RAI", - decimals: 18, - contract: address!("0x6164A78F7B2aC49cf9b76c49e5B6909e89f34a66"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334"), -}; - -pub static SUPERRARE_130_E025BB6F: TokenInfo = TokenInfo { - name: "SuperRare", - symbol: "RARE", - decimals: 18, - contract: address!("0xe8a0078aA52ac7e93aE43818DdD64591E025BB6F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/17753/thumb/RARE.jpg?1629220534"), -}; - -pub static RARIBLE_130_03C8561C: TokenInfo = TokenInfo { - name: "Rarible", - symbol: "RARI", - decimals: 18, - contract: address!("0x16F01392Ed7fC6F3C345CF544cf1172103C8561C"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11845/thumb/Rari.png?1594946953"), -}; - -pub static RUBIC_130_66B403E3: TokenInfo = TokenInfo { - name: "Rubic", - symbol: "RBC", - decimals: 18, - contract: address!("0x29EA5682024c8C62Cd8BDf691C4f0c5D66B403E3"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12629/thumb/200x200.png?1607952509"), -}; - -pub static RIBBON_FINANCE_130_C841CD3E: TokenInfo = TokenInfo { - name: "Ribbon Finance", - symbol: "RBN", - decimals: 18, - contract: address!("0x75B2dBb2a7C70073133E42F64366a986c841cd3e"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/15823/thumb/RBN_64x64.png?1633529723"), -}; - -pub static REPUBLIC_TOKEN_130_8261617E: TokenInfo = TokenInfo { - name: "Republic Token", - symbol: "REN", - decimals: 18, - contract: address!("0x560603E0bFC941063D1375Ec4E3f9FE38261617E"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png"), -}; - -pub static REPUTATION_AUGUR_V1_130_B2816FC4: TokenInfo = TokenInfo { - name: "Reputation Augur v1", - symbol: "REP", - decimals: 18, - contract: address!("0x097ca3FC389697080C84148C455Ca839b2816Fc4"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1985365e9f78359a9B6AD760e32412f4a445E862/logo.png"), -}; - -pub static REPUTATION_AUGUR_V2_130_1E72A8C4: TokenInfo = TokenInfo { - name: "Reputation Augur v2", - symbol: "REPv2", - decimals: 18, - contract: address!("0xE86B1E5613a5761D005a2D00D8a1B4ad1e72A8c4"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x221657776846890989a759BA2973e427DfF5C9bB/logo.png"), -}; - -pub static REQUEST_130_9D8663CD: TokenInfo = TokenInfo { - name: "Request", - symbol: "REQ", - decimals: 18, - contract: address!("0x9FcC3133779F2039c29908c915b6EFaE9d8663Cd"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1031/thumb/Request_icon_green.png?1643250951"), -}; - -pub static REVV_130_0F9CA657: TokenInfo = TokenInfo { - name: "REVV", - symbol: "REVV", - decimals: 18, - contract: address!("0xc14a68015fA6396eF97B57839da544910f9Ca657"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12373/thumb/REVV_TOKEN_Refined_2021_%281%29.png?1627652390"), -}; - -pub static RENZO_130_AAD6C9AB: TokenInfo = TokenInfo { - name: "Renzo", - symbol: "REZ", - decimals: 18, - contract: address!("0x2178f07c1d585C39272CAf69A72beF08aAD6c9AB"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/37327/standard/renzo_200x200.png?1714025012"), -}; - -pub static RARI_GOVERNANCE_TOKEN_130_946CF284: TokenInfo = TokenInfo { - name: "Rari Governance Token", - symbol: "RGT", - decimals: 18, - contract: address!("0x8c9606001CF1787CEb80E03DEF3F9BaF946CF284"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014"), -}; - -pub static IEXEC_RLC_130_B3347ACB: TokenInfo = TokenInfo { - name: "iExec RLC", - symbol: "RLC", - decimals: 9, - contract: address!("0x538fB2719135740b8877607217Dc391FB3347ACb"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1604543202"), -}; - -pub static RALLY_130_3F88C889: TokenInfo = TokenInfo { - name: "Rally", - symbol: "RLY", - decimals: 18, - contract: address!("0x7Ad899b7C793743fDE692d982F190f443F88c889"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12843/thumb/image.png?1611212077"), -}; - -pub static RENDER_TOKEN_130_8D649868: TokenInfo = TokenInfo { - name: "Render Token", - symbol: "RNDR", - decimals: 18, - contract: address!("0x965C6DeBFa700F53a38d42DbaeD922c58d649868"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11636/thumb/rndr.png?1638840934"), -}; - -pub static ROOK_130_9DE41D99: TokenInfo = TokenInfo { - name: "Rook", - symbol: "ROOK", - decimals: 18, - contract: address!("0x682B2f07e61022A80Ac2753448f7D95E9de41D99"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13005/thumb/keeper_dao_logo.jpg?1604316506"), -}; - -pub static RESERVE_RIGHTS_130_B1889066: TokenInfo = TokenInfo { - name: "Reserve Rights", - symbol: "RSR", - decimals: 18, - contract: address!("0x993A565A1E6219951323cA3c34Cee0A3b1889066"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856"), -}; - -pub static SAFE_130_10EFD888: TokenInfo = TokenInfo { - name: "Safe", - symbol: "SAFE", - decimals: 18, - contract: address!("0x47B72717E48Da346C3F1ED1311c8DCDe10EfD888"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/27032/standard/Artboard_1_copy_8circle-1.png?1696526084"), -}; - -pub static THE_SANDBOX_130_2CAF25CA: TokenInfo = TokenInfo { - name: "The Sandbox", - symbol: "SAND", - decimals: 18, - contract: address!("0x6A654A2ec95fB988Ea37746dBCca10772CAf25CA"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1597397942"), -}; - -pub static STADER_130_B32D72E5: TokenInfo = TokenInfo { - name: "Stader", - symbol: "SD", - decimals: 18, - contract: address!("0x7ccc67C7b232aa6417d9422e90D91ec4b32d72E5"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png"), -}; - -pub static SHIBA_INU_130_5664158E: TokenInfo = TokenInfo { - name: "Shiba Inu", - symbol: "SHIB", - decimals: 18, - contract: address!("0xaa571d01057cdF477D73433D36D86fCb5664158e"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11939/thumb/shiba.png?1622619446"), -}; - -pub static SHPING_130_66024F2F: TokenInfo = TokenInfo { - name: "Shping", - symbol: "SHPING", - decimals: 18, - contract: address!("0x45Bda7bA10DaC525a86DBEaB3135701A66024F2F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2588/thumb/r_yabKKi_400x400.jpg?1639470164"), -}; - -pub static SKALE_130_8AD20C01: TokenInfo = TokenInfo { - name: "SKALE", - symbol: "SKL", - decimals: 18, - contract: address!("0x486Bbb6f250343AdB4782F50Dd09766f8aD20c01"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13245/thumb/SKALE_token_300x300.png?1606789574"), -}; - -pub static SKY_GOVERNANCE_TOKEN_130_D07074E4: TokenInfo = TokenInfo { - name: "SKY Governance Token", - symbol: "SKY", - decimals: 18, - contract: address!("0x5A6058002d0d336e5E8860652e7054a6d07074E4"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/39925/large/sky.jpg?1724827980"), -}; - -pub static SMOOTH_LOVE_POTION_130_96CB03B3: TokenInfo = TokenInfo { - name: "Smooth Love Potion", - symbol: "SLP", - decimals: 0, - contract: address!("0xbD2DD310FECBFb1111fC3262F3a97bA696cb03B3"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/10366/thumb/SLP.png?1578640057"), -}; - -pub static STATUS_130_265ABF5F: TokenInfo = TokenInfo { - name: "Status", - symbol: "SNT", - decimals: 18, - contract: address!("0x914f7CE2B080B2186159C2213B1e193E265aBF5F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778"), -}; - -pub static SYNTHETIX_NETWORK_TOKEN_130_59E6BC88: TokenInfo = TokenInfo { - name: "Synthetix Network Token", - symbol: "SNX", - decimals: 18, - contract: address!("0x022D952aBCc6C8271F26e59e37A65dC359E6bc88"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), -}; - -pub static UNISOCKS_130_DC4627AB: TokenInfo = TokenInfo { - name: "Unisocks", - symbol: "SOCKS", - decimals: 18, - contract: address!("0x5e03C123D829505F4DEa87cf679F77c9dC4627ab"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/10717/thumb/qFrcoiM.png?1582525244"), -}; - -pub static SOL_WORMHOLE_130_C3D054FE: TokenInfo = TokenInfo { - name: "SOL Wormhole ", - symbol: "SOL", - decimals: 9, - contract: address!("0x4Ff3E944D5Cb54f6f4A1dd035782BE59c3d054FE"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), -}; - -pub static SOLANA: TokenInfo = TokenInfo { - name: "Solana", - symbol: "SOL", - decimals: 9, - contract: address!("0xbdE8A5331E8Ac4831cf8ea9e42e229219EafaB97"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54680/large/base.png?1749023388"), -}; - -pub static SPELL_TOKEN_130_C17FEF7F: TokenInfo = TokenInfo { - name: "Spell Token", - symbol: "SPELL", - decimals: 18, - contract: address!("0x739316C7bc4A39Eb39dcFa1b181b64abc17fEF7F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862"), -}; - -pub static SPX6900_130_036DD629: TokenInfo = TokenInfo { - name: "SPX6900", - symbol: "SPX", - decimals: 8, - contract: address!("0x51A7b9a11f10D04C16306D90dc4EC22b036DD629"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083"), -}; - -pub static STARGATE_FINANCE_130_19373135: TokenInfo = TokenInfo { - name: "Stargate Finance", - symbol: "STG", - decimals: 18, - contract: address!("0x77c8A8E1dd3b5270d3Ab589543e9A83319373135"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518"), -}; - -pub static STORJ_TOKEN_130_C9951835: TokenInfo = TokenInfo { - name: "Storj Token", - symbol: "STORJ", - decimals: 8, - contract: address!("0xf13B5B21555092882e69b22282DAf891c9951835"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png"), -}; - -pub static STARKNET_130_2332C72E: TokenInfo = TokenInfo { - name: "Starknet", - symbol: "STRK", - decimals: 18, - contract: address!("0x09f705405677970E509d606348D4635D2332c72e"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/26433/standard/starknet.png?1696525507"), -}; - -pub static STOX_130_CACCEA22: TokenInfo = TokenInfo { - name: "Stox", - symbol: "STX", - decimals: 18, - contract: address!("0xEf86E70E534E02AADEAE95b843973d4AcacCeA22"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1230/thumb/stox-token.png?1547035256"), -}; - -pub static SUKU_130_82176525: TokenInfo = TokenInfo { - name: "SUKU", - symbol: "SUKU", - decimals: 18, - contract: address!("0xc05B416738DDEBd14D5A9B790a6e1ce782176525"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11969/thumb/UmfW5S6f_400x400.jpg?1596602238"), -}; - -pub static SUPERFARM_130_2BD86D3D: TokenInfo = TokenInfo { - name: "SuperFarm", - symbol: "SUPER", - decimals: 18, - contract: address!("0x0c288302629Fc22504D59Ddf8fbf8AA92bD86D3D"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899"), -}; - -pub static SYNTH_SUSD_130_9B3A6A0F: TokenInfo = TokenInfo { - name: "Synth sUSD", - symbol: "sUSD", - decimals: 18, - contract: address!("0x7251d204c2e867b31096D5c7091298239B3A6a0F"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765"), -}; - -pub static SUSHI_130_BDFB3CE5: TokenInfo = TokenInfo { - name: "Sushi", - symbol: "SUSHI", - decimals: 18, - contract: address!("0x2982Be2D0c6ae4A7D5BC1c8fe7B630E3BDfb3ce5"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), -}; - -pub static SWELL_130_028A5870: TokenInfo = TokenInfo { - name: "Swell", - symbol: "SWELL", - decimals: 18, - contract: address!("0xa8015cbc9f7c58788BA00854c330F027028A5870"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/28777/large/swell1.png?1727899715"), -}; - -pub static SWFTCOIN_130_45AF1616: TokenInfo = TokenInfo { - name: "SWFTCOIN", - symbol: "SWFTC", - decimals: 8, - contract: address!("0x0610cDF9856b8825213672981056CD4945Af1616"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2346/thumb/SWFTCoin.jpg?1618392022"), -}; - -pub static SWIPE_130_9785C2E1: TokenInfo = TokenInfo { - name: "Swipe", - symbol: "SXP", - decimals: 18, - contract: address!("0xDcA295E850666753c6332D6B0E0445B09785c2E1"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/9368/thumb/swipe.png?1566792311"), -}; - -pub static SYLO_130_CFFCF85E: TokenInfo = TokenInfo { - name: "Sylo", - symbol: "SYLO", - decimals: 18, - contract: address!("0x1BAAc1979527A38F367c6f89bE081aBfcFFCF85E"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/6430/thumb/SYLO.svg?1589527756"), -}; - -pub static SYNAPSE_130_81888A48: TokenInfo = TokenInfo { - name: "Synapse", - symbol: "SYN", - decimals: 18, - contract: address!("0xCeb1F5671C47cee096C3B40353863b6781888A48"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049"), -}; - -pub static SYRUP_TOKEN_130_8CD6FA96: TokenInfo = TokenInfo { - name: "Syrup Token", - symbol: "SYRUP", - decimals: 18, - contract: address!("0x8f7F997ba304f426E3138999919c23f68cD6FA96"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/51232/standard/IMG_7420.png?1730831572"), -}; - -pub static THRESHOLD_NETWORK_130_48F2AD54: TokenInfo = TokenInfo { - name: "Threshold Network", - symbol: "T", - decimals: 18, - contract: address!("0x8F43Ab8648F1a3BAEea3782Ba5f562a148f2Ad54"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340"), -}; - -pub static BITTENSOR: TokenInfo = TokenInfo { - name: "Bittensor", - symbol: "TAO", - decimals: 18, - contract: address!("0xFdCa15bd55F350a36E63C47661914d80411d2C22"), - chain: 130, - logo_uri: Some("https://app.uniswap.org/assets/unichain-logo-B-lwXybJ.png"), -}; - -pub static TBTC_130_20BC7814: TokenInfo = TokenInfo { - name: "tBTC", - symbol: "tBTC", - decimals: 18, - contract: address!("0xAd497996Dc33DC8E8e552824CcEe199420BC7814"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png"), -}; - -pub static CHRONOTECH_130_1EDA749C: TokenInfo = TokenInfo { - name: "ChronoTech", - symbol: "TIME", - decimals: 8, - contract: address!("0xD9Cbd701bbEA8e9Aaee7d82aa60748451eDa749c"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/604/thumb/time-32x32.png?1627130666"), -}; - -pub static ALIEN_WORLDS_130_A9A46C68: TokenInfo = TokenInfo { - name: "Alien Worlds", - symbol: "TLM", - decimals: 4, - contract: address!("0xd649b9AD2104418B5b032a5899fBcd54a9a46c68"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14676/thumb/kY-C4o7RThfWrDQsLCAG4q4clZhBDDfJQVhWUEKxXAzyQYMj4Jmq1zmFwpRqxhAJFPOa0AsW_PTSshoPuMnXNwq3rU7Imp15QimXTjlXMx0nC088mt1rIwRs75GnLLugWjSllxgzvQ9YrP4tBgclK4_rb17hjnusGj_c0u2fx0AvVokjSNB-v2poTj0xT9BZRCbzRE3-lF1.jpg?1617700061"), -}; - -pub static TOKEMAK_130_36213E0B: TokenInfo = TokenInfo { - name: "Tokemak", - symbol: "TOKE", - decimals: 18, - contract: address!("0x5eD5DA180bB125f229AB7b825E34D2b936213e0B"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/17495/thumb/tokemak-avatar-200px-black.png?1628131614"), -}; - -pub static TE_FOOD_130_A7BD5AC6: TokenInfo = TokenInfo { - name: "TE FOOD", - symbol: "TONE", - decimals: 18, - contract: address!("0x502865ECDd2a2929Aa9418297bE7d3C4a7BD5Ac6"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/2325/thumb/tec.png?1547036538"), -}; - -pub static ORIGINTRAIL_130_DBAE6F2E: TokenInfo = TokenInfo { - name: "OriginTrail", - symbol: "TRAC", - decimals: 18, - contract: address!("0x1ac70C9e29bC19640E64D938DD8D6A46dbAe6f2e"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/1877/thumb/TRAC.jpg?1635134367"), -}; - -pub static TELLOR_130_6D8EC63B: TokenInfo = TokenInfo { - name: "Tellor", - symbol: "TRB", - decimals: 18, - contract: address!("0x8e902FDeA73e5CF9621D2Bee82cD79196d8ec63b"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686"), -}; - -pub static TRIBE_130_33DACDBD: TokenInfo = TokenInfo { - name: "Tribe", - symbol: "TRIBE", - decimals: 18, - contract: address!("0x437dD6360Bd17FB353c67376371133Cd33dacdBD"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/14575/thumb/tribe.PNG?1617487954"), -}; - -pub static TRUEFI_130_F30CFE0E: TokenInfo = TokenInfo { - name: "TrueFi", - symbol: "TRU", - decimals: 8, - contract: address!("0x55C65102C26b173696e935B1325e5AaeF30cFE0e"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13180/thumb/truefi_glyph_color.png?1617610941"), -}; - -pub static TURBO_130_F2D202A1: TokenInfo = TokenInfo { - name: "Turbo", - symbol: "TURBO", - decimals: 18, - contract: address!("0x1E4339318EcE1d6D9d2Fb129b31C06b9F2d202A1"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/30117/large/TurboMark-QL_200.png?1708079597"), -}; - -pub static THE_VIRTUA_KOLECT_130_13BD9D5D: TokenInfo = TokenInfo { - name: "The Virtua Kolect", - symbol: "TVK", - decimals: 18, - contract: address!("0x756fb781389DCaF9D3BC5468927F06A913bD9D5D"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13330/thumb/virtua_original.png?1656043619"), -}; - -pub static UMA_VOTING_TOKEN_V1_130_72435F8C: TokenInfo = TokenInfo { - name: "UMA Voting Token v1", - symbol: "UMA", - decimals: 18, - contract: address!("0x478923278640a10A60951E379aFFb60772435f8C"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), -}; - -pub static UNIFI_PROTOCOL_DAO_130_0408A30B: TokenInfo = TokenInfo { - name: "Unifi Protocol DAO", - symbol: "UNFI", - decimals: 18, - contract: address!("0xe9225a870b54f8FBA42c8188D211271f0408a30B"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/13152/thumb/logo-2.png?1605748967"), -}; - -pub static UNISWAP_130_7CE9EA21: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0x8f187aA05619a017077f5308904739877ce9eA21"), - chain: 130, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static PAWTOCOL_130_3E264D36: TokenInfo = TokenInfo { - name: "Pawtocol", - symbol: "UPI", - decimals: 18, - contract: address!("0x5EAFF8Fa6f3831Bb86FeEB701E6f98293E264D36"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12186/thumb/pawtocol.jpg?1597962008"), -}; - -pub static USDCOIN_130_0EF57AD6: TokenInfo = TokenInfo { - name: "USDCoin", - symbol: "USDC", - decimals: 6, - contract: address!("0x078D782b760474a361dDA0AF3839290b0EF57AD6"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), -}; - -pub static GLOBAL_DOLLAR_130_A9F86F1E: TokenInfo = TokenInfo { - name: "Global Dollar", - symbol: "USDG", - decimals: 6, - contract: address!("0x2A22868610610199D43fE93A16661473A9f86f1E"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/51281/large/GDN_USDG_Token_200x200.png"), -}; - -pub static PAX_DOLLAR_130_6DE0FEFF: TokenInfo = TokenInfo { - name: "Pax Dollar", - symbol: "USDP", - decimals: 18, - contract: address!("0xF7E6430137eF8087E0D472343f358e986De0FEFF"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/6013/standard/Pax_Dollar.png?1696506427"), -}; - -pub static QUANTOZ_USDQ_130_7B2F3A5F: TokenInfo = TokenInfo { - name: "Quantoz USDQ", - symbol: "USDQ", - decimals: 6, - contract: address!("0xf37748D2Cc6E6d5D05945Ce130C03c147b2F3a5F"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/51852/large/USDQ_1000px_Color.png?1732071232"), -}; - -pub static STABLR_USD_130_004C06A7: TokenInfo = TokenInfo { - name: "StablR USD", - symbol: "USDR", - decimals: 6, - contract: address!("0xaC025d055a6B633992dE1F796b97B97F004c06a7"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/53721/large/stablrusd-logo.png?1737126629"), -}; - -pub static USDS_STABLECOIN_130_3B2F7BB4: TokenInfo = TokenInfo { - name: "USDS Stablecoin", - symbol: "USDS", - decimals: 18, - contract: address!("0x116EE4d63847fb295dD919aE57B768EA3B2f7Bb4"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/39926/large/usds.webp?1726666683"), -}; - -pub static TETHER_USD_130_54C75518: TokenInfo = TokenInfo { - name: "Tether USD", - symbol: "USDT", - decimals: 6, - contract: address!("0x588CE4F028D8e7B53B687865d6A67b3A54C75518"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), -}; - -pub static USUAL_130_98BC5950: TokenInfo = TokenInfo { - name: "USUAL", - symbol: "USUAL", - decimals: 18, - contract: address!("0xc7bA59c95ba747a7c374DC7208a0513798BC5950"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/51091/large/USUAL.jpg?1730035787"), -}; - -pub static VANRY_130_01564A0B: TokenInfo = TokenInfo { - name: "VANRY", - symbol: "VANRY", - decimals: 18, - contract: address!("0x286b5Ecea3749c7c7047104aa3C5749901564A0b"), - chain: 130, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/33466/large/apple-touch-icon.png?1701942541"), -}; - -pub static VOYAGER_TOKEN_130_8FFE537F: TokenInfo = TokenInfo { - name: "Voyager Token", - symbol: "VGX", - decimals: 8, - contract: address!("0x4afd08AC2416450d9c8b84D287dbfFb68FFe537f"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/794/thumb/Voyager-vgx.png?1575693595"), -}; - -pub static WRAPPED_AMPLEFORTH_130_06364A49: TokenInfo = TokenInfo { - name: "Wrapped Ampleforth", - symbol: "WAMPL", - decimals: 18, - contract: address!("0xb86a08ec917EeF9f835aC2B26c3a506c06364A49"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/20825/thumb/photo_2021-11-25_02-05-11.jpg?1637811951"), -}; - -pub static WRAPPED_BTC_130_4EC4AFB8: TokenInfo = TokenInfo { - name: "Wrapped BTC", - symbol: "WBTC", - decimals: 8, - contract: address!("0x927B51f251480a681271180DA4de28D44EC4AfB8"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), -}; - -pub static WRAPPED_CENTRIFUGE_130_D72E82C4: TokenInfo = TokenInfo { - name: "Wrapped Centrifuge", - symbol: "WCFG", - decimals: 18, - contract: address!("0xaE87B8eb5E313AC72B306CbA7c1E3f23D72e82C4"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/17106/thumb/WCFG.jpg?1626266462"), -}; - -pub static WRAPPED_ETHER_130_00000006: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0x4200000000000000000000000000000000000006"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static DOGWIFHAT: TokenInfo = TokenInfo { - name: "dogwifhat", - symbol: "WIF", - decimals: 6, - contract: address!("0x97Fadb3D000b953360FD011e173F12cDDB5d70Fa"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/33566/standard/dogwifhat.jpg?1702499428"), -}; - -pub static WOO_NETWORK_130_EFD89E62: TokenInfo = TokenInfo { - name: "WOO Network", - symbol: "WOO", - decimals: 18, - contract: address!("0xef22b9df2dDf4246A827575C4Aa46BDaeFd89E62"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), -}; - -pub static CHAIN_130_DC06A12F: TokenInfo = TokenInfo { - name: "Chain", - symbol: "XCN", - decimals: 18, - contract: address!("0x15261eEb999eD3C3ae3c5319E0035940dc06a12f"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054"), -}; - -pub static PLASMA: TokenInfo = TokenInfo { - name: "Plasma", - symbol: "XPL", - decimals: 18, - contract: address!("0x139451953Ef1865c096F89C5e522C081DC3b5f11"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/plasma/info/logo.png"), -}; - -pub static XRP: TokenInfo = TokenInfo { - name: "XRP", - symbol: "XRP", - decimals: 18, - contract: address!("0x2615a94df961278DcbC41Fb0a54fEc5f10a693aE"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ripple/info/logo.png"), -}; - -pub static XSGD_130_021265C3: TokenInfo = TokenInfo { - name: "XSGD", - symbol: "XSGD", - decimals: 6, - contract: address!("0xb1A9385B500Fe81B58c4d0e3AaCC39d8021265c3"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623"), -}; - -pub static XYO_NETWORK_130_2AEBE4EA: TokenInfo = TokenInfo { - name: "XYO Network", - symbol: "XYO", - decimals: 18, - contract: address!("0x43D5EA0f30Bce3907aAD6783e61D56592AEbE4eA"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819"), -}; - -pub static YEARN_FINANCE_130_F84A3201: TokenInfo = TokenInfo { - name: "yearn finance", - symbol: "YFI", - decimals: 18, - contract: address!("0x52Bf54Eb4210F588320f3e4c151Bca81f84a3201"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), -}; - -pub static DFI_MONEY_130_6C18A07E: TokenInfo = TokenInfo { - name: "DFI money", - symbol: "YFII", - decimals: 18, - contract: address!("0x62ffD4229bb9a327412D1BE518A1dbAe6c18A07E"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/11902/thumb/YFII-logo.78631676.png?1598677348"), -}; - -pub static YIELD_GUILD_GAMES_130_76E36F4B: TokenInfo = TokenInfo { - name: "Yield Guild Games", - symbol: "YGG", - decimals: 18, - contract: address!("0xeA20C2Cf22acBbF3d8311D15bC73FD7076E36f4B"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/17358/thumb/le1nzlO6_400x400.jpg?1632465691"), -}; - -pub static ZCASH: TokenInfo = TokenInfo { - name: "Zcash", - symbol: "ZEC", - decimals: 18, - contract: address!("0x83f31af747189c2FA9E5DeB253200c505eff6ed2"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/zcash/info/logo.png"), -}; - -pub static ZETACHAIN_130_B3CB3CA4: TokenInfo = TokenInfo { - name: "Zetachain", - symbol: "Zeta", - decimals: 18, - contract: address!("0x757dCF360f2FE999FAEEBcc6E80f5Eceb3cb3CA4"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/26718/standard/Twitter_icon.png?1696525788"), -}; - -pub static LAYERZERO_130_7ED29CFB: TokenInfo = TokenInfo { - name: "LayerZero", - symbol: "ZRO", - decimals: 18, - contract: address!("0x00ad3704d1e101DF76f87738bEfE67737eD29cFb"), - chain: 130, - logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), -}; - -pub static TOKEN_0X_PROTOCOL_TOKEN_130_A6E7EDF5: TokenInfo = TokenInfo { - name: "0x Protocol Token", - symbol: "ZRX", - decimals: 18, - contract: address!("0x7e7e8e5f0eDd7ca2ed3D9609cea1FF37a6E7Edf5"), - chain: 130, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), -}; - -pub static AAVE_137_2B21C90B: TokenInfo = TokenInfo { - name: "Aave", - symbol: "AAVE", - decimals: 18, - contract: address!("0xD6DF932A45C0f255f85145f286eA0b292B21C90B"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), -}; - -pub static AGEUR_137_C0057DB4: TokenInfo = TokenInfo { - name: "agEur", - symbol: "agEUR", - decimals: 18, - contract: address!("0xE0B52e49357Fd4DAf2c15e02058DCE6BC0057db4"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), -}; - -pub static AMP_137_4F27054D: TokenInfo = TokenInfo { - name: "Amp", - symbol: "AMP", - decimals: 18, - contract: address!("0x0621d647cecbFb64b79E44302c1933cB4f27054d"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/12409/thumb/amp-200x200.png?1599625397"), -}; - -pub static BALANCER_137_3B0E76A3: TokenInfo = TokenInfo { - name: "Balancer", - symbol: "BAL", - decimals: 18, - contract: address!("0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png"), -}; - -pub static BAND_PROTOCOL_137_D82606AC: TokenInfo = TokenInfo { - name: "Band Protocol", - symbol: "BAND", - decimals: 18, - contract: address!("0xA8b1E0764f85f53dfe21760e8AfE5446D82606ac"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/9545/thumb/band-protocol.png?1568730326"), -}; - -pub static BANCOR_NETWORK_TOKEN_137_2A4F7842: TokenInfo = TokenInfo { - name: "Bancor Network Token", - symbol: "BNT", - decimals: 18, - contract: address!("0xc26D47d5c33aC71AC5CF9F776D63Ba292a4F7842"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png"), -}; - -pub static COMPOUND_137_837AEF5C: TokenInfo = TokenInfo { - name: "Compound", - symbol: "COMP", - decimals: 18, - contract: address!("0x8505b9d2254A7Ae468c0E9dd10Ccea3A837aef5c"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), -}; - -pub static CURVE_DAO_TOKEN_137_33A610AF: TokenInfo = TokenInfo { - name: "Curve DAO Token", - symbol: "CRV", - decimals: 18, - contract: address!("0x172370d5Cd63279eFa6d502DAB29171933a610AF"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), -}; - -pub static CIVIC_137_398B02BE: TokenInfo = TokenInfo { - name: "Civic", - symbol: "CVC", - decimals: 8, - contract: address!("0x66Dc5A08091d1968e08C16aA5b27BAC8398b02Be"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556"), -}; - -pub static DAI_STABLECOIN_137_39C6A063: TokenInfo = TokenInfo { - name: "Dai Stablecoin", - symbol: "DAI", - decimals: 18, - contract: address!("0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), -}; - -pub static ETHEREUM_NAME_SERVICE_137_90EE7C4F: TokenInfo = TokenInfo { - name: "Ethereum Name Service", - symbol: "ENS", - decimals: 18, - contract: address!("0xbD7A5Cf51d22930B8B3Df6d834F9BCEf90EE7c4f"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140"), -}; - -pub static GNOSIS_TOKEN_137_7DF024A8: TokenInfo = TokenInfo { - name: "Gnosis Token", - symbol: "GNO", - decimals: 18, - contract: address!("0x5FFD62D3C3eE2E81C00A7b9079FB248e7dF024A8"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png"), -}; - -pub static THE_GRAPH_137_499F5531: TokenInfo = TokenInfo { - name: "The Graph", - symbol: "GRT", - decimals: 18, - contract: address!("0x5fe2B58c013d7601147DcdD68C143A77499f5531"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566"), -}; - -pub static KEEP_NETWORK_137_2EB0C72C: TokenInfo = TokenInfo { - name: "Keep Network", - symbol: "KEEP", - decimals: 18, - contract: address!("0x42f37A1296b2981F7C3cAcEd84c5096b2Eb0C72C"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/3373/thumb/IuNzUb5b_400x400.jpg?1589526336"), -}; - -pub static KYBER_NETWORK_CRYSTAL_137_9CFA1DC7: TokenInfo = TokenInfo { - name: "Kyber Network Crystal", - symbol: "KNC", - decimals: 18, - contract: address!("0x324b28d6565f784d596422B0F2E5aB6e9CFA1Dc7"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png"), -}; - -pub static CHAINLINK_TOKEN_137_3FABAD39: TokenInfo = TokenInfo { - name: "ChainLink Token", - symbol: "LINK", - decimals: 18, - contract: address!("0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), -}; - -pub static LOOM_NETWORK_137_1193F6B3: TokenInfo = TokenInfo { - name: "Loom Network", - symbol: "LOOM", - decimals: 18, - contract: address!("0x66EfB7cC647e0efab02eBA4316a2d2941193F6b3"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0/logo.png"), -}; - -pub static LOOPRINGCOIN_V2_137_BB47DDC1: TokenInfo = TokenInfo { - name: "LoopringCoin V2", - symbol: "LRC", - decimals: 18, - contract: address!("0x84e1670F61347CDaeD56dcc736FB990fBB47ddC1"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png"), -}; - -pub static DECENTRALAND_137_33606FD4: TokenInfo = TokenInfo { - name: "Decentraland", - symbol: "MANA", - decimals: 18, - contract: address!("0xA1c57f48F0Deb89f569dFbE6E2B7f46D33606fD4"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745"), -}; - -pub static POLYGON_137_00001010: TokenInfo = TokenInfo { - name: "Polygon", - symbol: "MATIC", - decimals: 18, - contract: address!("0x0000000000000000000000000000000000001010"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), -}; - -pub static MAKER_137_E01FF61D: TokenInfo = TokenInfo { - name: "Maker", - symbol: "MKR", - decimals: 18, - contract: address!("0x6f7C932e7684666C9fd1d44527765433e01fF61d"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png"), -}; - -pub static NUMERAIRE_137_11F46729: TokenInfo = TokenInfo { - name: "Numeraire", - symbol: "NMR", - decimals: 18, - contract: address!("0x0Bf519071b02F22C17E7Ed5F4002ee1911f46729"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png"), -}; - -pub static ORCHID_137_D31F6060: TokenInfo = TokenInfo { - name: "Orchid", - symbol: "OXT", - decimals: 18, - contract: address!("0x9880e3dDA13c8e7D4804691A45160102d31F6060"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4575f41308EC1483f3d399aa9a2826d74Da13Deb/logo.png"), -}; - -pub static REPUBLIC_TOKEN_137_26ED89D0: TokenInfo = TokenInfo { - name: "Republic Token", - symbol: "REN", - decimals: 18, - contract: address!("0x19782D3Dc4701cEeeDcD90f0993f0A9126ed89d0"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png"), -}; - -pub static REPUTATION_AUGUR_V2_137_7363F733: TokenInfo = TokenInfo { - name: "Reputation Augur v2", - symbol: "REPv2", - decimals: 18, - contract: address!("0x6563c1244820CfBd6Ca8820FBdf0f2847363F733"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x221657776846890989a759BA2973e427DfF5C9bB/logo.png"), -}; - -pub static SYNTHETIX_NETWORK_TOKEN_137_11FEF68A: TokenInfo = TokenInfo { - name: "Synthetix Network Token", - symbol: "SNX", - decimals: 18, - contract: address!("0x50B728D8D964fd00C2d0AAD81718b71311feF68a"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), -}; - -pub static STORJ_TOKEN_137_5A3F5792: TokenInfo = TokenInfo { - name: "Storj Token", - symbol: "STORJ", - decimals: 8, - contract: address!("0xd72357dAcA2cF11A5F155b9FF7880E595A3F5792"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png"), -}; - -pub static SYNTH_SUSD_137_6E03A7A0: TokenInfo = TokenInfo { - name: "Synth sUSD", - symbol: "sUSD", - decimals: 18, - contract: address!("0xF81b4Bec6Ca8f9fe7bE01CA734F55B2b6e03A7a0"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765"), -}; - -pub static UMA_VOTING_TOKEN_V1_137_77A6B731: TokenInfo = TokenInfo { - name: "UMA Voting Token v1", - symbol: "UMA", - decimals: 18, - contract: address!("0x3066818837c5e6eD6601bd5a91B0762877A6B731"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), -}; - -pub static UNISWAP_137_7FB5180F: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0xb33EaAd8d922B1083446DC23f610c2567fB5180f"), - chain: 137, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static USDCOIN_137_3D5C3359: TokenInfo = TokenInfo { - name: "USDCoin", - symbol: "USDC", - decimals: 6, - contract: address!("0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), -}; - -pub static USDCOIN_POS: TokenInfo = TokenInfo { - name: "USDCoin (PoS)", - symbol: "USDC.e", - decimals: 6, - contract: address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), -}; - -pub static TETHER_USD_137_04B58E8F: TokenInfo = TokenInfo { - name: "Tether USD", - symbol: "USDT", - decimals: 6, - contract: address!("0xc2132D05D31c914a87C6611C10748AEb04B58e8F"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), -}; - -pub static VANAR_CHAIN: TokenInfo = TokenInfo { - name: "Vanar Chain", - symbol: "VANRY", - decimals: 18, - contract: address!("0x8DE5B80a0C1B02Fe4976851D030B36122dbb8624"), - chain: 137, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/33466/large/apple-touch-icon.png?1701942541"), -}; - -pub static VOXIES: TokenInfo = TokenInfo { - name: "Voxies", - symbol: "VOXEL", - decimals: 18, - contract: address!("0xd0258a3fD00f38aa8090dfee343f10A9D4d30D3F"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/21260/large/voxies.png"), -}; - -pub static WRAPPED_BTC_137_47D9BFD6: TokenInfo = TokenInfo { - name: "Wrapped BTC", - symbol: "WBTC", - decimals: 8, - contract: address!("0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), -}; - -pub static WRAPPED_ETHER_137_F1B9F619: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static WRAPPED_MATIC: TokenInfo = TokenInfo { - name: "Wrapped Matic", - symbol: "WMATIC", - decimals: 18, - contract: address!("0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), -}; - -pub static XSGD_137_8D201995: TokenInfo = TokenInfo { - name: "XSGD", - symbol: "XSGD", - decimals: 6, - contract: address!("0xDC3326e71D45186F113a2F448984CA0e8D201995"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623"), -}; - -pub static YEARN_FINANCE_137_465260B6: TokenInfo = TokenInfo { - name: "yearn finance", - symbol: "YFI", - decimals: 18, - contract: address!("0xDA537104D6A5edd53c6fBba9A898708E465260b6"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), -}; - -pub static LAYERZERO_137_F13271CD: TokenInfo = TokenInfo { - name: "LayerZero", - symbol: "ZRO", - decimals: 18, - contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), - chain: 137, - logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), -}; - -pub static TOKEN_0X_PROTOCOL_TOKEN_137_CA6BE3D5: TokenInfo = TokenInfo { - name: "0x Protocol Token", - symbol: "ZRX", - decimals: 18, - contract: address!("0x5559Edb74751A0edE9DeA4DC23aeE72cCA6bE3D5"), - chain: 137, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), -}; - -pub static SOL_WORMHOLE_143_245217F1: TokenInfo = TokenInfo { - name: "SOL Wormhole ", - symbol: "SOL", - decimals: 9, - contract: address!("0xea17E5a9efEBf1477dB45082d67010E2245217f1"), - chain: 143, - logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), -}; - -pub static USDCOIN_143_5AAFB603: TokenInfo = TokenInfo { - name: "USDCoin", - symbol: "USDC", - decimals: 6, - contract: address!("0x754704Bc059F8C67012fEd69BC8A327a5aafb603"), - chain: 143, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), -}; - -pub static TETHER_USD_143_750FC82D: TokenInfo = TokenInfo { - name: "Tether USD", - symbol: "USDT", - decimals: 6, - contract: address!("0xe7cd86e13AC4309349F30B3435a9d337750fC82D"), - chain: 143, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), -}; - -pub static WRAPPED_BTC_143_230D2B9C: TokenInfo = TokenInfo { - name: "Wrapped BTC", - symbol: "WBTC", - decimals: 8, - contract: address!("0x0555E30da8f98308EdB960aa94C0Db47230d2B9c"), - chain: 143, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), -}; - -pub static WRAPPED_ETHER_143_35481242: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0xEE8c0E9f1BFFb4Eb878d8f15f368A02a35481242"), - chain: 143, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static GLOBAL_DOLLAR_196_933D2DC8: TokenInfo = TokenInfo { - name: "Global Dollar", - symbol: "USDG", - decimals: 6, - contract: address!("0x4ae46a509F6b1D9056937BA4500cb143933D2dc8"), - chain: 196, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/51281/large/GDN_USDG_Token_200x200.png?1730484111"), -}; - -pub static ZKSYNC: TokenInfo = TokenInfo { - name: "ZKsync", - symbol: "ZK", - decimals: 18, - contract: address!("0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E"), - chain: 324, - logo_uri: Some("https://assets.coingecko.com/coins/images/38043/large/ZKTokenBlack.png?17186145029"), -}; - -pub static BRIDGED_USDC: TokenInfo = TokenInfo { - name: "Bridged USDC", - symbol: "USDC.e", - decimals: 6, - contract: address!("0x79A02482A880bCE3F13e09Da970dC34db4CD24d1"), - chain: 480, - logo_uri: Some("https://assets.coingecko.com/coins/images/35218/large/USDC_Icon.png?1707908537"), -}; - -pub static WRAPPED_BTC_480_2D70CFA3: TokenInfo = TokenInfo { - name: "Wrapped BTC", - symbol: "WBTC", - decimals: 8, - contract: address!("0x03C7054BCB39f7b2e5B2c7AcB37583e32D70Cfa3"), - chain: 480, - logo_uri: Some("https://assets.coingecko.com/coins/images/7598/large/wrapped_bitcoin_wbtc.png?1696507857"), -}; - -pub static WRAPPED_ETHER_480_00000006: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0x4200000000000000000000000000000000000006"), - chain: 480, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static USDCOIN_1868_4AACC369: TokenInfo = TokenInfo { - name: "USDCoin", - symbol: "USDC", - decimals: 6, - contract: address!("0xbA9986D2381edf1DA03B0B9c1f8b00dc4AacC369"), - chain: 1868, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), -}; - -pub static TETHER_USD_1868_97B5AE35: TokenInfo = TokenInfo { - name: "Tether USD", - symbol: "USDT", - decimals: 6, - contract: address!("0x3A337a6adA9d885b6Ad95ec48F9b75f197b5AE35"), - chain: 1868, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), -}; - -pub static WRAPPED_ETHER_1868_00000006: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0x4200000000000000000000000000000000000006"), - chain: 1868, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static TOKEN_1INCH_8453_1E111CBE: TokenInfo = TokenInfo { - name: "1inch", - symbol: "1INCH", - decimals: 18, - contract: address!("0xc5fecC3a29Fb57B5024eEc8a2239d4621e111CBE"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), -}; - -pub static AAVE_8453_D17F814B: TokenInfo = TokenInfo { - name: "Aave", - symbol: "AAVE", - decimals: 18, - contract: address!("0x63706e401c06ac8513145b7687A14804d17f814b"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), -}; - -pub static ARCBLOCK_8453_7C1FA556: TokenInfo = TokenInfo { - name: "Arcblock", - symbol: "ABT", - decimals: 18, - contract: address!("0xe2A8cCB00E328a0EC2204CB0c736309D7c1fa556"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/2341/thumb/arcblock.png?1547036543"), -}; - -pub static AMBIRE_ADEX_8453_A3E0EFD9: TokenInfo = TokenInfo { - name: "Ambire AdEx", - symbol: "ADX", - decimals: 18, - contract: address!("0x3c87e7AF3cDBAe5bB56b4936325Ea95CA3E0EfD9"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540"), -}; - -pub static AERODROME_FINANCE: TokenInfo = TokenInfo { - name: "Aerodrome Finance", - symbol: "AERO", - decimals: 18, - contract: address!("0x940181a94A35A4569E4529A3CDfB74e38FD98631"), - chain: 8453, - logo_uri: Some("https://basescan.org/token/images/aerodrome_32.png"), -}; - -pub static AIXBT_BY_VIRTUALS: TokenInfo = TokenInfo { - name: "aixbt by Virtuals", - symbol: "AIXBT", - decimals: 18, - contract: address!("0x4F9Fd6Be4a90f2620860d680c0d4d5Fb53d1A825"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/51784/large/3.png?1731981138"), -}; - -pub static ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_8453_D59F3DCC: TokenInfo = TokenInfo { - name: "Alethea Artificial Liquid Intelligence", - symbol: "ALI", - decimals: 18, - contract: address!("0x97c806e7665d3AFd84A8Fe1837921403D59F3Dcc"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848"), -}; - -pub static AUSTRALIAN_DIGITAL_DOLLAR: TokenInfo = TokenInfo { - name: "Australian Digital Dollar", - symbol: "AUDD", - decimals: 6, - contract: address!("0x449B3317a6d1efb1Bc3ba0700C9EaA4FFFf4Ae65"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/33263/large/AUDD-Logo-Blue_512.png?1701319895"), -}; - -pub static AVANTIS: TokenInfo = TokenInfo { - name: "Avantis", - symbol: "AVNT", - decimals: 18, - contract: address!("0x696F9436B67233384889472Cd7cD58A6fB5DF4f1"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/68972/large/avnt-token.png?1757134448"), -}; - -pub static AWE_NETWORK: TokenInfo = TokenInfo { - name: "AWE Network", - symbol: "AWE", - decimals: 18, - contract: address!("0x1B4617734C43F6159F3a70b7E06d883647512778"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/8713/large/awe-network.jpg?1747816016"), -}; - -pub static B3: TokenInfo = TokenInfo { - name: "B3", - symbol: "B3", - decimals: 18, - contract: address!("0xB3B32F9f8827D4634fE7d973Fa1034Ec9fdDB3B3"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54287/large/B3.png?1739001374"), -}; - -pub static HARRYPOTTEROBAMASONIC10INU_8453_D39A1A29: TokenInfo = TokenInfo { - name: "HarryPotterObamaSonic10Inu", - symbol: "BITCOIN", - decimals: 8, - contract: address!("0x2a06A17CBC6d0032Cac2c6696DA90f29D39a1a29"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224"), -}; - -pub static BANKRCOIN: TokenInfo = TokenInfo { - name: "BankrCoin", - symbol: "BNKR", - decimals: 18, - contract: address!("0x22aF33FE49fD1Fa80c7149773dDe5890D3c76F3b"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/52626/large/bankr-static.png?1736405365"), -}; - -pub static COINBASE_WRAPPED_ADA: TokenInfo = TokenInfo { - name: "Coinbase Wrapped ADA", - symbol: "cbADA", - decimals: 6, - contract: address!("0xcbADA732173e39521CDBE8bf59a6Dc85A9fc7b8c"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/66647/large/Coinbase_Wrapped_Ada_%28cbADA%29.png?1750129533"), -}; - -pub static COINBASE_WRAPPED_BTC_8453_0EED33BF: TokenInfo = TokenInfo { - name: "Coinbase Wrapped BTC", - symbol: "cbBTC", - decimals: 8, - contract: address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/40143/standard/cbbtc.webp"), -}; - -pub static COINBASE_WRAPPED_DOGE: TokenInfo = TokenInfo { - name: "Coinbase Wrapped DOGE", - symbol: "CBDOGE", - decimals: 8, - contract: address!("0xcbD06E5A2B0C65597161de254AA074E489dEb510"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/66268/large/Coinbase_Wrapped_Doge_%28cbDOGE%29.png?1749023465"), -}; - -pub static COINBASE_WRAPPED_STAKED_ETH_8453_CF0DEC22: TokenInfo = TokenInfo { - name: "Coinbase Wrapped Staked ETH", - symbol: "cbETH", - decimals: 18, - contract: address!("0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22"), - chain: 8453, - logo_uri: Some("https://ethereum-optimism.github.io/data/cbETH/logo.svg"), -}; - -pub static COINBASE_WRAPPED_LTC: TokenInfo = TokenInfo { - name: "Coinbase Wrapped LTC", - symbol: "cbLTC", - decimals: 8, - contract: address!("0xcb17C9Db87B595717C857a08468793f5bAb6445F"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/66646/large/Coinbase_Wrapped_Litecoin_%28cbLTC%29.png?1750129508"), -}; - -pub static COINBASE_WRAPPED_XRP: TokenInfo = TokenInfo { - name: "Coinbase Wrapped XRP", - symbol: "cbXRP", - decimals: 6, - contract: address!("0xcb585250f852C6c6bf90434AB21A00f02833a4af"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/66267/large/Coinbase_Wrapped_XPR_%28cbXRP%29.png?1749023398"), -}; - -pub static TOKENBOT: TokenInfo = TokenInfo { - name: "tokenbot", - symbol: "CLANKER", - decimals: 18, - contract: address!("0x1bc0c42215582d5A085795f4baDbaC3ff36d1Bcb"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/51440/large/CLANKER.png?1731232869"), -}; - -pub static COMPOUND_8453_976840E0: TokenInfo = TokenInfo { - name: "Compound", - symbol: "COMP", - decimals: 18, - contract: address!("0x9e1028F5F1D5eDE59748FFceE5532509976840E0"), - chain: 8453, - logo_uri: Some("https://ethereum-optimism.github.io/data/COMP/logo.svg"), -}; - -pub static COOKIE: TokenInfo = TokenInfo { - name: "Cookie", - symbol: "COOKIE", - decimals: 18, - contract: address!("0xC0041EF357B183448B235a8Ea73Ce4E4eC8c265F"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/38450/large/cookie_token_logo_200x200.png?1733194528"), -}; - -pub static CURVE_DAO_TOKEN_8453_67DD0415: TokenInfo = TokenInfo { - name: "Curve DAO Token", - symbol: "CRV", - decimals: 18, - contract: address!("0x8Ee73c484A26e0A5df2Ee2a4960B789967dd0415"), - chain: 8453, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), -}; - -pub static CARTESI_8453_76138D45: TokenInfo = TokenInfo { - name: "Cartesi", - symbol: "CTSI", - decimals: 18, - contract: address!("0x259Fac10c5CbFEFE3E710e1D9467f70a76138d45"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), -}; - -pub static CRYPTEX_FINANCE_8453_D4666E14: TokenInfo = TokenInfo { - name: "Cryptex Finance", - symbol: "CTX", - decimals: 18, - contract: address!("0xBB22Ff867F8Ca3D5F2251B4084F6Ec86D4666E14"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171"), -}; - -pub static COVALENT_X_TOKEN_8453_8EB628FF: TokenInfo = TokenInfo { - name: "Covalent X Token", - symbol: "CXT", - decimals: 18, - contract: address!("0xB1E1f3Cc2B6fE4420C1Ac82022b457018Eb628ff"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/39177/large/CXT_Ticker.png?1720829918"), -}; - -pub static DAI_STABLECOIN_8453_917DB0CB: TokenInfo = TokenInfo { - name: "Dai Stablecoin", - symbol: "DAI", - decimals: 18, - contract: address!("0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb"), - chain: 8453, - logo_uri: Some("https://ethereum-optimism.github.io/data/DAI/logo.svg"), -}; - -pub static DEGEN: TokenInfo = TokenInfo { - name: "Degen", - symbol: "DEGEN", - decimals: 18, - contract: address!("0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/34515/large/android-chrome-512x512.png?1706198225"), -}; - -pub static DOGINME: TokenInfo = TokenInfo { - name: "doginme", - symbol: "doginme", - decimals: 18, - contract: address!("0x6921B130D297cc43754afba22e5EAc0FBf8Db75b"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/35123/large/doginme-logo1-transparent200.png?1710856784"), -}; - -pub static DOVU_8453_B953F865: TokenInfo = TokenInfo { - name: "DOVU", - symbol: "DOVU", - decimals: 8, - contract: address!("0xB38266e0e9D9681b77aEB0A280E98131b953F865"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/31930/large/Dovu_Icon_Black_%281%29.png?1696530738"), -}; - -pub static DERIVE_8453_B645D083: TokenInfo = TokenInfo { - name: "Derive", - symbol: "DRV", - decimals: 18, - contract: address!("0x9d0E8f5b25384C7310CB8C6aE32C8fbeb645d083"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695"), -}; - -pub static DEFINITIVE: TokenInfo = TokenInfo { - name: "Definitive", - symbol: "EDGE", - decimals: 18, - contract: address!("0xED6E000dEF95780fb89734c07EE2ce9F6dcAf110"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/55072/large/EDGE-120x120.png?1743598652"), -}; - -pub static ELSA: TokenInfo = TokenInfo { - name: "Elsa", - symbol: "ELSA", - decimals: 18, - contract: address!("0x29cC30f9D113B356Ce408667aa6433589CeCBDcA"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/71623/large/Red_circle_white_logo_512x512_%281%29.png?1768570174"), -}; - -pub static EURC: TokenInfo = TokenInfo { - name: "EURC", - symbol: "EURC", - decimals: 6, - contract: address!("0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/26045/standard/euro.png"), -}; - -pub static FAI: TokenInfo = TokenInfo { - name: "FAI", - symbol: "FAI", - decimals: 18, - contract: address!("0xb33Ff54b9F7242EF1593d2C9Bcd8f9df46c77935"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/52315/large/FAI.png?1733076295"), -}; - -pub static FLOCK: TokenInfo = TokenInfo { - name: "Flock", - symbol: "FLOCK", - decimals: 18, - contract: address!("0x5aB3D4c385B400F3aBB49e80DE2fAF6a88A7B691"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/53178/large/FLock_Token_Logo.png?1735561398"), -}; - -pub static FLUID: TokenInfo = TokenInfo { - name: "Fluid", - symbol: "FLUID", - decimals: 18, - contract: address!("0x61E030A56D33e8260FdD81f03B162A79Fe3449Cd"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/14688/large/Logo_1_(brighter).png?1734430693"), -}; - -pub static SPORT_FUN: TokenInfo = TokenInfo { - name: "Sport.fun", - symbol: "FUN1", - decimals: 18, - contract: address!("0x16EE7ecAc70d1028E7712751E2Ee6BA808a7dd92"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/71076/large/sport-fun-logo.png?1766298060"), -}; - -pub static HOME: TokenInfo = TokenInfo { - name: "HOME", - symbol: "HOME", - decimals: 18, - contract: address!("0x4BfAa776991E85e5f8b1255461cbbd216cFc714f"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54873/large/defi-app.png?1742235743"), -}; - -pub static HYPERLANE: TokenInfo = TokenInfo { - name: "Hyperlane", - symbol: "HYPER", - decimals: 18, - contract: address!("0xC9d23ED2ADB0f551369946BD377f8644cE1ca5c4"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/55298/large/Hyperlane.png?1745248900"), -}; - -pub static IOTEX_8453_27AE38C1: TokenInfo = TokenInfo { - name: "IoTeX", - symbol: "IOTX", - decimals: 18, - contract: address!("0xBCBAf311ceC8a4EAC0430193A528d9FF27ae38C1"), - chain: 8453, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/2777.png"), -}; - -pub static GEOJAM_8453_3AA2A057: TokenInfo = TokenInfo { - name: "Geojam", - symbol: "JAM", - decimals: 18, - contract: address!("0xFf9957816c813C5Ad0b9881A8990Df1E3AA2a057"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/24648/thumb/ey40AzBN_400x400.jpg?1648507272"), -}; - -pub static KAITO: TokenInfo = TokenInfo { - name: "KAITO", - symbol: "KAITO", - decimals: 18, - contract: address!("0x98d0baa52b2D063E780DE12F615f963Fe8537553"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54411/large/Qm4DW488_400x400.jpg?1739552780"), -}; - -pub static KEYBOARD_CAT: TokenInfo = TokenInfo { - name: "Keyboard Cat", - symbol: "KEYCAT", - decimals: 18, - contract: address!("0x9a26F5433671751C3276a065f57e5a02D2817973"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/36608/large/keyboard_cat.jpeg?1711965348"), -}; - -pub static KRYLL_8453_611F9F7A: TokenInfo = TokenInfo { - name: "KRYLL", - symbol: "KRL", - decimals: 18, - contract: address!("0xDAE49C25fAd3a62a8e8bFB6dA12c46bE611f9f7a"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979"), -}; - -pub static KEETA: TokenInfo = TokenInfo { - name: "Keeta", - symbol: "KTA", - decimals: 18, - contract: address!("0xc0634090F2Fe6c6d75e61Be2b949464aBB498973"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54723/large/2025-03-05_22.53.06.jpg?1741234207"), -}; - -pub static LCX_8453_71D3C171: TokenInfo = TokenInfo { - name: "LCX", - symbol: "LCX", - decimals: 18, - contract: address!("0xd7468c14ae76C3Fc308aEAdC223D5D1F71d3c171"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/9985/thumb/zRPSu_0o_400x400.jpg?1574327008"), -}; - -pub static LIQUITY_8453_BDDC125C: TokenInfo = TokenInfo { - name: "Liquity", - symbol: "LQTY", - decimals: 18, - contract: address!("0x5259384690aCF240e9b0A8811bD0FFbFBDdc125C"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180"), -}; - -pub static MAMO: TokenInfo = TokenInfo { - name: "Mamo", - symbol: "MAMO", - decimals: 18, - contract: address!("0x7300B37DfdfAb110d83290A29DfB31B1740219fE"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/55958/large/Mamo_Circle_200x200_TransBG.png?1748974093"), -}; - -pub static NOICE: TokenInfo = TokenInfo { - name: "Noice", - symbol: "NOICE", - decimals: 18, - contract: address!("0x9Cb41FD9dC6891BAe8187029461bfAADF6CC0C69"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/55981/large/tCtKSYL3_400x400.jpg?1747925133"), -}; - -pub static ODOS_TOKEN: TokenInfo = TokenInfo { - name: "Odos Token", - symbol: "ODOS", - decimals: 18, - contract: address!("0xca73ed1815e5915489570014e024b7EbE65dE679"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/52914/large/odos.jpg?1734678948"), -}; - -pub static PENDLE_8453_029EEB3E: TokenInfo = TokenInfo { - name: "Pendle", - symbol: "PENDLE", - decimals: 18, - contract: address!("0xA99F6e6785Da0F5d6fB42495Fe424BCE029Eeb3E"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728"), -}; - -pub static PEPE_8453_8B982BE3: TokenInfo = TokenInfo { - name: "Pepe", - symbol: "PEPE", - decimals: 18, - contract: address!("0xB4fDe59a779991bfB6a52253B51947828b982be3"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725"), -}; - -pub static PERPETUAL_PROTOCOL_8453_DAAD58DE: TokenInfo = TokenInfo { - name: "Perpetual Protocol", - symbol: "PERP", - decimals: 18, - contract: address!("0xCD6dDDa305955AcD6b94b934f057E8b0daaD58dE"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), -}; - -pub static PRIME_8453_A5ADD21B: TokenInfo = TokenInfo { - name: "Prime", - symbol: "PRIME", - decimals: 18, - contract: address!("0xfA980cEd6895AC314E7dE34Ef1bFAE90a5AdD21b"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222"), -}; - -pub static PROPY_8453_9230438B: TokenInfo = TokenInfo { - name: "Propy", - symbol: "PRO", - decimals: 8, - contract: address!("0x18dD5B087bCA9920562aFf7A0199b96B9230438b"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/869/thumb/propy.png?1548332100"), -}; - -pub static PROMPT: TokenInfo = TokenInfo { - name: "Prompt", - symbol: "PROMPT", - decimals: 18, - contract: address!("0x30c7235866872213F68cb1F08c37Cb9eCCB93452"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/55169/large/wayfinder.jpg?1744336900"), -}; - -pub static RAVEDAO: TokenInfo = TokenInfo { - name: "RaveDAO", - symbol: "RAVE", - decimals: 18, - contract: address!("0x1aA8fD5BCce2231C6100d55Bf8B377cff33Acfc3"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/70544/large/coin.jpeg?1762452940"), -}; - -pub static RECALL_NETWORK: TokenInfo = TokenInfo { - name: "Recall Network", - symbol: "RECALL", - decimals: 18, - contract: address!("0x1f16e03C1a5908818F47f6EE7bB16690b40D0671"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/69994/large/recall-logo.jpeg?1760337415"), -}; - -pub static RAINBOW: TokenInfo = TokenInfo { - name: "Rainbow", - symbol: "RNBW", - decimals: 18, - contract: address!("0xa53887F7e7c1bf5010b8627F1C1ba94fE7a5d6E0"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/69445/large/RNBW-200px.png?1770053251"), -}; - -pub static RESEARCHCOIN: TokenInfo = TokenInfo { - name: "ResearchCoin", - symbol: "RSC", - decimals: 18, - contract: address!("0xFbB75A59193A3525a8825BeBe7D4b56899E2f7e1"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/28146/large/RH_BOTTLE_CLEAN_Aug_2024_1.png?1732742001"), -}; - -pub static RESERVE_RIGHTS_8453_6072F64A: TokenInfo = TokenInfo { - name: "Reserve Rights", - symbol: "RSR", - decimals: 18, - contract: address!("0xaB36452DbAC151bE02b16Ca17d8919826072f64a"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856"), -}; - -pub static SAPIEN: TokenInfo = TokenInfo { - name: "Sapien", - symbol: "SAPIEN", - decimals: 18, - contract: address!("0xC729777d0470F30612B1564Fd96E8Dd26f5814E3"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/68423/large/logo.png?1755710030"), -}; - -pub static SEAMLESSS: TokenInfo = TokenInfo { - name: "Seamlesss", - symbol: "SEAM", - decimals: 18, - contract: address!("0x1C7a460413dD4e964f96D8dFC56E7223cE88CD85"), - chain: 8453, - logo_uri: Some("https://basescan.org/token/images/seamless_32.png"), -}; - -pub static STATUS_8453_2E8AC09E: TokenInfo = TokenInfo { - name: "Status", - symbol: "SNT", - decimals: 18, - contract: address!("0x662015EC830DF08C0FC45896FaB726542e8AC09E"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778"), -}; - -pub static SYNTHETIX_NETWORK_TOKEN_8453_327FDA66: TokenInfo = TokenInfo { - name: "Synthetix Network Token", - symbol: "SNX", - decimals: 18, - contract: address!("0x22e6966B799c4D5B13BE962E1D117b56327FDa66"), - chain: 8453, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), -}; - -pub static SPX6900_8453_6819BB2C: TokenInfo = TokenInfo { - name: "SPX6900", - symbol: "SPX", - decimals: 8, - contract: address!("0x50dA645f148798F68EF2d7dB7C1CB22A6819bb2C"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083"), -}; - -pub static SUPERFLUID_TOKEN: TokenInfo = TokenInfo { - name: "Superfluid Token", - symbol: "SUP", - decimals: 18, - contract: address!("0xa69f80524381275A7fFdb3AE01c54150644c8792"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/68697/large/sup.png?1756287343"), -}; - -pub static SUSHI_8453_98B2AFBA: TokenInfo = TokenInfo { - name: "Sushi", - symbol: "SUSHI", - decimals: 18, - contract: address!("0x7D49a065D17d6d4a55dc13649901fdBB98B2AFBA"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), -}; - -pub static SYNDICATE: TokenInfo = TokenInfo { - name: "Syndicate", - symbol: "SYND", - decimals: 18, - contract: address!("0x11dC28D01984079b7efE7763b533e6ed9E3722B9"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/69122/large/synd.png?1757576144"), -}; - -pub static TBTC_8453_22AB794B: TokenInfo = TokenInfo { - name: "tBTC", - symbol: "tBTC", - decimals: 18, - contract: address!("0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b"), - chain: 8453, - logo_uri: Some("https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png"), -}; - -pub static TOSHI: TokenInfo = TokenInfo { - name: "Toshi", - symbol: "TOSHI", - decimals: 18, - contract: address!("0xAC1Bd2486aAf3B5C0fc3Fd868558b082a531B2B4"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/31126/large/Toshi_Logo_-_Circular.png?1721677476"), -}; - -pub static TOWNS: TokenInfo = TokenInfo { - name: "Towns", - symbol: "TOWNS", - decimals: 18, - contract: address!("0x00000000A22C618fd6b4D7E9A335C4B96B189a38"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/55230/large/yImUvwK__400x400.png?1744857671"), -}; - -pub static INTUITION: TokenInfo = TokenInfo { - name: "Intuition", - symbol: "TRUST", - decimals: 18, - contract: address!("0x6cd905dF2Ed214b22e0d48FF17CD4200C1C6d8A3"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/55976/large/intuition_trust.jpg?1747904133"), -}; - -pub static UNISWAP_8453_114A3C83: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0xc3De830EA07524a0761646a6a4e4be0e114a3C83"), - chain: 8453, - logo_uri: Some("https://ethereum-optimism.github.io/data/UNI/logo.png"), -}; - -pub static SUPERFORM: TokenInfo = TokenInfo { - name: "Superform", - symbol: "UP", - decimals: 18, - contract: address!("0x5b2193fDc451C1f847bE09CA9d13A4Bf60f8c86B"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/70945/large/superform.png?1764747920"), -}; - -pub static USD_BASE_COIN: TokenInfo = TokenInfo { - name: "USD Base Coin", - symbol: "USDbC", - decimals: 6, - contract: address!("0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA"), - chain: 8453, - logo_uri: Some("https://ethereum-optimism.github.io/data/USDC/logo.png"), -}; - -pub static USD_COIN: TokenInfo = TokenInfo { - name: "USD Coin", - symbol: "USDC", - decimals: 6, - contract: address!("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"), - chain: 8453, - logo_uri: Some("https://ethereum-optimism.github.io/data/USDC/logo.png"), -}; - -pub static VENICE_TOKEN: TokenInfo = TokenInfo { - name: "Venice Token", - symbol: "VVV", - decimals: 18, - contract: address!("0xacfE6019Ed1A7Dc6f7B508C02d1b04ec88cC21bf"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/54023/standard/Venice_Token_(1).png?1738017546"), -}; - -pub static WALLETCONNECT_TOKEN_8453_DD927945: TokenInfo = TokenInfo { - name: "WalletConnect Token", - symbol: "WCT", - decimals: 18, - contract: address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/50390/large/wc-token1.png?1727569464"), -}; - -pub static MOONWELL: TokenInfo = TokenInfo { - name: "Moonwell", - symbol: "WELL", - decimals: 18, - contract: address!("0xA88594D404727625A9437C3f886C7643872296AE"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/26133/large/WELL.png?1696525221"), -}; - -pub static WRAPPED_ETHER_8453_00000006: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0x4200000000000000000000000000000000000006"), - chain: 8453, - logo_uri: Some("https://ethereum-optimism.github.io/data/WETH/logo.png"), -}; - -pub static WORLD_MOBILE_TOKEN: TokenInfo = TokenInfo { - name: "World Mobile Token", - symbol: "WMTX", - decimals: 18, - contract: address!("0x3e31966d4f81C72D2a55310A6365A56A4393E98D"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/17333/large/Token_icon_round_1024.png?1741247846"), -}; - -pub static XYO_NETWORK_8453_223ADC94: TokenInfo = TokenInfo { - name: "XYO Network", - symbol: "XYO", - decimals: 18, - contract: address!("0xD7B99ffB8B2afc6fe013a17207cbe50f223aDc94"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819"), -}; - -pub static YEARN_FINANCE_8453_AD3CB239: TokenInfo = TokenInfo { - name: "yearn finance", - symbol: "YFI", - decimals: 18, - contract: address!("0x9EaF8C1E34F05a589EDa6BAfdF391Cf6Ad3CB239"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), -}; - -pub static YIELD_GUILD_GAMES_8453_F5EF1799: TokenInfo = TokenInfo { - name: "Yield Guild Games", - symbol: "YGG", - decimals: 18, - contract: address!("0xaAC78d1219c08AecC8e37e03858FE885f5EF1799"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/17358/thumb/le1nzlO6_400x400.jpg?1632465691"), -}; - -pub static HORIZEN: TokenInfo = TokenInfo { - name: "Horizen", - symbol: "ZEN", - decimals: 18, - contract: address!("0xf43eB8De897Fbc7F2502483B2Bef7Bb9EA179229"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/691/large/Horizen2.0-logo_icon-on-yellow_%281%29.png?1751696763"), -}; - -pub static BOUNDLESS_8453_FBBCE7CF: TokenInfo = TokenInfo { - name: "Boundless", - symbol: "ZKC", - decimals: 18, - contract: address!("0xAA61bB7777bD01B684347961918f1E07fBbCe7CF"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/68462/large/boundless.png?1755826792"), -}; - -pub static ZORA: TokenInfo = TokenInfo { - name: "Zora", - symbol: "ZORA", - decimals: 18, - contract: address!("0x1111111111166b7FE7bd91427724B487980aFc69"), - chain: 8453, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54693/large/zora.jpg?1741094751"), -}; - -pub static LAYERZERO_8453_F13271CD: TokenInfo = TokenInfo { - name: "LayerZero", - symbol: "ZRO", - decimals: 18, - contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), - chain: 8453, - logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), -}; - -pub static TOKEN_0X_PROTOCOL_TOKEN_8453_BC9779D0: TokenInfo = TokenInfo { - name: "0x Protocol Token", - symbol: "ZRX", - decimals: 18, - contract: address!("0x3bB4445D30AC020a84c1b5A8A2C6248ebC9779D0"), - chain: 8453, - logo_uri: Some("https://ethereum-optimism.github.io/data/ZRX/logo.png"), -}; - -pub static TOKEN_1INCH_42161_3F4BB9AF: TokenInfo = TokenInfo { - name: "1inch", - symbol: "1INCH", - decimals: 18, - contract: address!("0x6314C31A7a1652cE482cffe247E9CB7c3f4BB9aF"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), -}; - -pub static AAVE_42161_CE967196: TokenInfo = TokenInfo { - name: "Aave", - symbol: "AAVE", - decimals: 18, - contract: address!("0xba5DdD1f9d7F570dc94a51479a000E3BCE967196"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), -}; - -pub static ACROSS_PROTOCOL_TOKEN_42161_03D9C99D: TokenInfo = TokenInfo { - name: "Across Protocol Token", - symbol: "ACX", - decimals: 18, - contract: address!("0x53691596d1BCe8CEa565b84d4915e69e03d9C99d"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165"), -}; - -pub static AEVO_42161_2B9783CD: TokenInfo = TokenInfo { - name: "Aevo", - symbol: "AEVO", - decimals: 18, - contract: address!("0x377c1Fc73D4D0f5600cd943776CED07c2B9783cd"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/35893/standard/aevo.png"), -}; - -pub static AGEUR_42161_723528E7: TokenInfo = TokenInfo { - name: "agEur", - symbol: "agEUR", - decimals: 18, - contract: address!("0xFA5Ed56A203466CbBC2430a43c66b9D8723528E7"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), -}; - -pub static ADVENTURE_GOLD_42161_012A3B9C: TokenInfo = TokenInfo { - name: "Adventure Gold", - symbol: "AGLD", - decimals: 18, - contract: address!("0xb7910E8b16e63EFD51d5D1a093d56280012A3B9C"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/18125/thumb/lpgblc4h_400x400.jpg?1630570955"), -}; - -pub static AIOZ_NETWORK_42161_E1569923: TokenInfo = TokenInfo { - name: "AIOZ Network", - symbol: "AIOZ", - decimals: 18, - contract: address!("0xeC76E8fe6e2242e6c2117caA244B9e2DE1569923"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126"), -}; - -pub static ALEPH_IM_42161_8E245A6C: TokenInfo = TokenInfo { - name: "Aleph im", - symbol: "ALEPH", - decimals: 18, - contract: address!("0xe7dcD50836d0A28c959c72D72122fEDB8E245A6C"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725"), -}; - -pub static ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_42161_FC0A71D1: TokenInfo = TokenInfo { - name: "Alethea Artificial Liquid Intelligence", - symbol: "ALI", - decimals: 18, - contract: address!("0xeF6124368c0B56556667e0de77eA008DfC0a71d1"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848"), -}; - -pub static ALPHA_VENTURE_DAO_42161_0A6B2646: TokenInfo = TokenInfo { - name: "Alpha Venture DAO", - symbol: "ALPHA", - decimals: 18, - contract: address!("0xC9CBf102c73fb77Ec14f8B4C8bd88e050a6b2646"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876"), -}; - -pub static ANKR_42161_C1E95447: TokenInfo = TokenInfo { - name: "Ankr", - symbol: "ANKR", - decimals: 18, - contract: address!("0x1bfc5d35bf0f7B9e15dc24c78b8C02dbC1e95447"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978"), -}; - -pub static APECOIN_42161_DBAD2210: TokenInfo = TokenInfo { - name: "ApeCoin", - symbol: "APE", - decimals: 18, - contract: address!("0x74885b4D524d497261259B38900f54e6dbAd2210"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/24383/small/apecoin.jpg?1647476455"), -}; - -pub static API3_42161_92CA7811: TokenInfo = TokenInfo { - name: "API3", - symbol: "API3", - decimals: 18, - contract: address!("0xF01dB12F50D0CDF5Fe360ae005b9c52F92CA7811"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13256/thumb/api3.jpg?1606751424"), -}; - -pub static ARBITRUM_42161_E49E6548: TokenInfo = TokenInfo { - name: "Arbitrum", - symbol: "ARB", - decimals: 18, - contract: address!("0x912CE59144191C1204E64559FE8253a0e49E6548"), - chain: 42161, - logo_uri: Some("https://arbitrum.foundation/logo.png"), -}; - -pub static ARKHAM_42161_DA4E656E: TokenInfo = TokenInfo { - name: "Arkham", - symbol: "ARKM", - decimals: 18, - contract: address!("0xDac5094B7D59647626444a4F905060FCda4E656E"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/30929/standard/Arkham_Logo_CG.png?1696529771"), -}; - -pub static AUTOMATA_42161_75714D03: TokenInfo = TokenInfo { - name: "Automata", - symbol: "ATA", - decimals: 18, - contract: address!("0xAC9Ac2C17cdFED4AbC80A53c5553388575714d03"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745"), -}; - -pub static AETHIR_TOKEN_42161_49092FB4: TokenInfo = TokenInfo { - name: "Aethir Token", - symbol: "ATH", - decimals: 18, - contract: address!("0xc7dEf82Ba77BAF30BbBc9b6162DC075b49092fb4"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/36179/large/logogram_circle_dark_green_vb_green_(1).png?1718232706"), -}; - -pub static AXELAR_42161_E2C6810F: TokenInfo = TokenInfo { - name: "Axelar", - symbol: "AXL", - decimals: 6, - contract: address!("0x23ee2343B892b1BB63503a4FAbc840E0e2C6810f"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg"), -}; - -pub static AXIE_INFINITY_42161_3E5D0089: TokenInfo = TokenInfo { - name: "Axie Infinity", - symbol: "AXS", - decimals: 18, - contract: address!("0xe88998Fb579266628aF6a03e3821d5983e5D0089"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082"), -}; - -pub static BADGER_DAO_42161_0D76472E: TokenInfo = TokenInfo { - name: "Badger DAO", - symbol: "BADGER", - decimals: 18, - contract: address!("0xBfa641051Ba0a0Ad1b0AcF549a89536A0D76472E"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13287/thumb/badger_dao_logo.jpg?1607054976"), -}; - -pub static BALANCER_42161_F56A56B8: TokenInfo = TokenInfo { - name: "Balancer", - symbol: "BAL", - decimals: 18, - contract: address!("0x040d1EdC9569d4Bab2D15287Dc5A4F10F56a56B8"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png"), -}; - -pub static BASIC_ATTENTION_TOKEN_42161_616AEE75: TokenInfo = TokenInfo { - name: "Basic Attention Token", - symbol: "BAT", - decimals: 18, - contract: address!("0x3450687EF141dCd6110b77c2DC44B008616AeE75"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427"), -}; - -pub static BICONOMY_42161_60A8E74D: TokenInfo = TokenInfo { - name: "Biconomy", - symbol: "BICO", - decimals: 18, - contract: address!("0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749"), -}; - -pub static BITDAO_42161_EB921C2A: TokenInfo = TokenInfo { - name: "BitDAO", - symbol: "BIT", - decimals: 18, - contract: address!("0x406C8dB506653D882295875F633bEC0bEb921C2A"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/17627/thumb/rI_YptK8.png?1653983088"), -}; - -pub static HARRYPOTTEROBAMASONIC10INU_42161_13BD565D: TokenInfo = TokenInfo { - name: "HarryPotterObamaSonic10Inu", - symbol: "BITCOIN", - decimals: 8, - contract: address!("0xf7e17BA61973bcDB61f471eFb989E47d13bD565D"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224"), -}; - -pub static BLUR_42161_FE606EB2: TokenInfo = TokenInfo { - name: "Blur", - symbol: "BLUR", - decimals: 18, - contract: address!("0xEf171a5BA71348eff16616fd692855c2Fe606EB2"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/28453/large/blur.png?1670745921"), -}; - -pub static BANCOR_NETWORK_TOKEN_42161_BA06D073: TokenInfo = TokenInfo { - name: "Bancor Network Token", - symbol: "BNT", - decimals: 18, - contract: address!("0x7A24159672b83ED1b89467c9d6A99556bA06D073"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png"), -}; - -pub static BARNBRIDGE_42161_EE64A4E1: TokenInfo = TokenInfo { - name: "BarnBridge", - symbol: "BOND", - decimals: 18, - contract: address!("0x0D81E50bC677fa67341c44D7eaA9228DEE64A4e1"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853"), -}; - -pub static BINANCE_USD_42161_462629A2: TokenInfo = TokenInfo { - name: "Binance USD", - symbol: "BUSD", - decimals: 18, - contract: address!("0x31190254504622cEFdFA55a7d3d272e6462629a2"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), -}; - -pub static PANCAKESWAP_42161_7CF58860: TokenInfo = TokenInfo { - name: "PancakeSwap", - symbol: "CAKE", - decimals: 18, - contract: address!("0xCdc343ebf71e38F003eD6c80171F5B8D7cF58860"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/12632/large/pancakeswap-cake-logo_%281%29.png?1696512440"), -}; - -pub static COINBASE_WRAPPED_BTC_42161_0EED33BF: TokenInfo = TokenInfo { - name: "Coinbase Wrapped BTC", - symbol: "cbBTC", - decimals: 8, - contract: address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/40143/large/cbbtc.webp"), -}; - -pub static COINBASE_WRAPPED_STAKED_ETH_42161_EAE7732F: TokenInfo = TokenInfo { - name: "Coinbase Wrapped Staked ETH", - symbol: "cbETH", - decimals: 18, - contract: address!("0x1DEBd73E752bEaF79865Fd6446b0c970EaE7732f"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/27008/large/cbeth.png"), -}; - -pub static CELO_NATIVE_ASSET_WORMHOLE_42161_1EF4F336: TokenInfo = TokenInfo { - name: "Celo native asset (Wormhole)", - symbol: "CELO", - decimals: 18, - contract: address!("0x4E51aC49bC5e2d87e0EF713E9e5AB2D71EF4F336"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png"), -}; - -pub static CELER_NETWORK_42161_40F345AB: TokenInfo = TokenInfo { - name: "Celer Network", - symbol: "CELR", - decimals: 18, - contract: address!("0x3a8B787f78D775AECFEEa15706D4221B40F345AB"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/4379/thumb/Celr.png?1554705437"), -}; - -pub static COMPOUND_42161_5C6C91DE: TokenInfo = TokenInfo { - name: "Compound", - symbol: "COMP", - decimals: 18, - contract: address!("0x354A6dA3fcde098F8389cad84b0182725c6C91dE"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), -}; - -pub static COTI_42161_D81EA101: TokenInfo = TokenInfo { - name: "COTI", - symbol: "COTI", - decimals: 18, - contract: address!("0x6FE14d3CC2f7bDdffBa5CdB3BBE7467dd81ea101"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/2962/thumb/Coti.png?1559653863"), -}; - -pub static COW_PROTOCOL_42161_F5C87A04: TokenInfo = TokenInfo { - name: "CoW Protocol", - symbol: "COW", - decimals: 18, - contract: address!("0xcb8b5CD20BdCaea9a010aC1F8d835824F5C87A04"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/24384/large/CoW-token_logo.png?1719524382"), -}; - -pub static COVALENT_42161_657273BF: TokenInfo = TokenInfo { - name: "Covalent", - symbol: "CQT", - decimals: 18, - contract: address!("0x69b937dB799a9BECC9E8A6F0a5d36eA3657273bf"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14168/thumb/covalent-cqt.png?1624545218"), -}; - -pub static CRONOS_42161_676F354C: TokenInfo = TokenInfo { - name: "Cronos", - symbol: "CRO", - decimals: 8, - contract: address!("0x8ea3156f834A0dfC78F1A5304fAC2CdA676F354C"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/7310/thumb/oCw2s3GI_400x400.jpeg?1645172042"), -}; - -pub static CURVE_DAO_TOKEN_42161_FA034978: TokenInfo = TokenInfo { - name: "Curve DAO Token", - symbol: "CRV", - decimals: 18, - contract: address!("0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), -}; - -pub static CARTESI_42161_1B476999: TokenInfo = TokenInfo { - name: "Cartesi", - symbol: "CTSI", - decimals: 18, - contract: address!("0x319f865b287fCC10b30d8cE6144e8b6D1b476999"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), -}; - -pub static CRYPTEX_FINANCE_42161_0425E12B: TokenInfo = TokenInfo { - name: "Cryptex Finance", - symbol: "CTX", - decimals: 18, - contract: address!("0x84F5c2cFba754E76DD5aE4fB369CfC920425E12b"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171"), -}; - -pub static CIVIC_42161_1DDBF144: TokenInfo = TokenInfo { - name: "Civic", - symbol: "CVC", - decimals: 8, - contract: address!("0x9DfFB23CAd3322440bCcFF7aB1C58E781dDBF144"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556"), -}; - -pub static CONVEX_FINANCE_42161_520829C5: TokenInfo = TokenInfo { - name: "Convex Finance", - symbol: "CVX", - decimals: 18, - contract: address!("0xaAFcFD42c9954C6689ef1901e03db742520829c5"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/15585/thumb/convex.png?1621256328"), -}; - -pub static DAI_STABLECOIN_42161_C9000DA1: TokenInfo = TokenInfo { - name: "Dai Stablecoin", - symbol: "DAI", - decimals: 18, - contract: address!("0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), -}; - -pub static DEXTOOLS_42161_9B64E227: TokenInfo = TokenInfo { - name: "DexTools", - symbol: "DEXT", - decimals: 18, - contract: address!("0x3Be7cB2e9413Ef8F42b4A202a0114EB59b64e227"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188"), -}; - -pub static DIA_42161_E17AC05E: TokenInfo = TokenInfo { - name: "DIA", - symbol: "DIA", - decimals: 18, - contract: address!("0xca642467C6Ebe58c13cB4A7091317f34E17ac05e"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751"), -}; - -pub static DISTRICT0X_42161_A49AD47A: TokenInfo = TokenInfo { - name: "district0x", - symbol: "DNT", - decimals: 18, - contract: address!("0xE3696a02b2C9557639E29d829E9C45EFa49aD47A"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/849/thumb/district0x.png?1547223762"), -}; - -pub static DEFI_PULSE_INDEX_42161_B68DD74C: TokenInfo = TokenInfo { - name: "DeFi Pulse Index", - symbol: "DPI", - decimals: 18, - contract: address!("0x4667cf53C4eDF659E402B733BEA42B18B68dd74c"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12465/thumb/defi_pulse_index_set.png?1600051053"), -}; - -pub static DERIVE_42161_90ABB135: TokenInfo = TokenInfo { - name: "Derive", - symbol: "DRV", - decimals: 18, - contract: address!("0x77b7787a09818502305C95d68A2571F090abb135"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695"), -}; - -pub static DYDX_42161_8CC90C5A: TokenInfo = TokenInfo { - name: "dYdX", - symbol: "DYDX", - decimals: 18, - contract: address!("0x51863cB90Ce5d6dA9663106F292fA27c8CC90c5a"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/17500/thumb/hjnIm9bV.jpg?1628009360"), -}; - -pub static EIGENLAYER_42161_6F96C248: TokenInfo = TokenInfo { - name: "EigenLayer", - symbol: "EIGEN", - decimals: 18, - contract: address!("0x606C3e5075e5555e79Aa15F1E9FACB776F96C248"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/37441/large/eigen.jpg?1728023974"), -}; - -pub static DOGELON_MARS_42161_17077FD4: TokenInfo = TokenInfo { - name: "Dogelon Mars", - symbol: "ELON", - decimals: 18, - contract: address!("0x3e4Cff6E50F37F731284A92d44AE943e17077fD4"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413"), -}; - -pub static ETHENA_42161_8EA977D8: TokenInfo = TokenInfo { - name: "Ethena", - symbol: "ENA", - decimals: 18, - contract: address!("0xdf8F0c63D9335A0AbD89F9F752d293A98EA977d8"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/36530/standard/ethena.png"), -}; - -pub static ENJIN_COIN_42161_63806758: TokenInfo = TokenInfo { - name: "Enjin Coin", - symbol: "ENJ", - decimals: 18, - contract: address!("0x7fa9549791EFc9030e1Ed3F25D18014163806758"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/1102/thumb/enjin-coin-logo.png?1547035078"), -}; - -pub static ETHEREUM_NAME_SERVICE_42161_E70D7C28: TokenInfo = TokenInfo { - name: "Ethereum Name Service", - symbol: "ENS", - decimals: 18, - contract: address!("0xfeA31d704DEb0975dA8e77Bf13E04239e70d7c28"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140"), -}; - -pub static ETHERNITY_CHAIN_42161_4D667F96: TokenInfo = TokenInfo { - name: "Ethernity Chain", - symbol: "ERN", - decimals: 18, - contract: address!("0x2354c8e9Ea898c751F1A15Addeb048714D667f96"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14238/thumb/LOGO_HIGH_QUALITY.png?1647831402"), -}; - -pub static ESPRESSO_42161_065C94F1: TokenInfo = TokenInfo { - name: "Espresso", - symbol: "ESP", - decimals: 18, - contract: address!("0x3b8db18e69d6686Ad9371A423aFe3Dd1065C94f1"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/67626/large/espresso.jpg?1753324525"), -}; - -pub static ETHER_FI_42161_4DFD5736: TokenInfo = TokenInfo { - name: "Ether.fi", - symbol: "ETHFI", - decimals: 18, - contract: address!("0x07D65C18CECbA423298c0aEB5d2BeDED4DFd5736"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/35958/standard/etherfi.jpeg"), -}; - -pub static EURO_COIN_42161_1FC52A48: TokenInfo = TokenInfo { - name: "Euro Coin", - symbol: "EURC", - decimals: 6, - contract: address!("0x863708032B5c328e11aBcbC0DF9D79C71Fc52a48"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420"), -}; - -pub static HARVEST_FINANCE_42161_24C83C70: TokenInfo = TokenInfo { - name: "Harvest Finance", - symbol: "FARM", - decimals: 18, - contract: address!("0x8553d254Cb6934b16F87D2e486b64BbD24C83C70"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180"), -}; - -pub static FETCH_AI_42161_7DCC4CC9: TokenInfo = TokenInfo { - name: "Fetch ai", - symbol: "FET", - decimals: 18, - contract: address!("0x4BE87C766A7CE11D5Cc864b6C3Abb7457dCC4cC9"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136"), -}; - -pub static STAFI_42161_767C7282: TokenInfo = TokenInfo { - name: "Stafi", - symbol: "FIS", - decimals: 18, - contract: address!("0x849B40AB2469309117Ed1038c5A99894767C7282"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991"), -}; - -pub static FLOKI_42161_B4905FAE: TokenInfo = TokenInfo { - name: "FLOKI", - symbol: "FLOKI", - decimals: 9, - contract: address!("0xA8C25FdC09763A176353CC6a76882e05b4905FAe"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318"), -}; - -pub static FLUX_42161_D685710A: TokenInfo = TokenInfo { - name: "Flux", - symbol: "FLUX", - decimals: 18, - contract: address!("0x63806C056Fa458c548Fb416B15E358A9D685710A"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x720CD16b011b987Da3518fbf38c3071d4F0D1495/logo.png"), -}; - -pub static FORTA_42161_CC3D2923: TokenInfo = TokenInfo { - name: "Forta", - symbol: "FORT", - decimals: 18, - contract: address!("0x3A1429d50E0cBBc45c997aF600541Fe1cc3D2923"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/25060/thumb/Forta_lgo_%281%29.png?1655353696"), -}; - -pub static SHAPESHIFT_FOX_TOKEN_42161_9E513C73: TokenInfo = TokenInfo { - name: "ShapeShift FOX Token", - symbol: "FOX", - decimals: 18, - contract: address!("0xf929de51D91C77E42f5090069E0AD7A09e513c73"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622"), -}; - -pub static FRAX_42161_0BC51305: TokenInfo = TokenInfo { - name: "Frax", - symbol: "FRAX", - decimals: 18, - contract: address!("0x7468a5d8E02245B00E8C0217fCE021C70Bc51305"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), -}; - -pub static FANTOM_42161_D4C2DF37: TokenInfo = TokenInfo { - name: "Fantom", - symbol: "FTM", - decimals: 18, - contract: address!("0xd42785D323e608B9E99fa542bd8b1000D4c2Df37"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016"), -}; - -pub static FRAX_SHARE_42161_AFFFDEA4: TokenInfo = TokenInfo { - name: "Frax Share", - symbol: "FXS", - decimals: 18, - contract: address!("0xd9f9d2Ee2d3EFE420699079f16D9e924affFdEA4"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), -}; - -pub static GALXE_42161_9BFD1182: TokenInfo = TokenInfo { - name: "Galxe", - symbol: "GAL", - decimals: 18, - contract: address!("0xc27E7325a6BEA1FcC06de7941473f5279bfd1182"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533"), -}; - -pub static GALA_42161_2827FF8C: TokenInfo = TokenInfo { - name: "GALA", - symbol: "GALA", - decimals: 8, - contract: address!("0x2A676eeAd159c4C8e8593471c6d666F02827FF8C"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12493/standard/GALA-COINGECKO.png?1696512310"), -}; - -pub static GMX: TokenInfo = TokenInfo { - name: "GMX", - symbol: "GMX", - decimals: 18, - contract: address!("0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/18323/large/arbit.png?1631532468"), -}; - -pub static GNOSIS_TOKEN_42161_4DEB6CF1: TokenInfo = TokenInfo { - name: "Gnosis Token", - symbol: "GNO", - decimals: 18, - contract: address!("0xa0b862F60edEf4452F25B4160F177db44DeB6Cf1"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png"), -}; - -pub static THE_GRAPH_42161_EA7E88C7: TokenInfo = TokenInfo { - name: "The Graph", - symbol: "GRT", - decimals: 18, - contract: address!("0x9623063377AD1B27544C965cCd7342f7EA7e88C7"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566"), -}; - -pub static GITCOIN_42161_C437DEE0: TokenInfo = TokenInfo { - name: "Gitcoin", - symbol: "GTC", - decimals: 18, - contract: address!("0x7f9a7DB853Ca816B9A138AEe3380Ef34c437dEe0"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929"), -}; - -pub static GYEN_42161_D9B6D5F7: TokenInfo = TokenInfo { - name: "GYEN", - symbol: "GYEN", - decimals: 6, - contract: address!("0x589d35656641d6aB57A545F08cf473eCD9B6D5F7"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343"), -}; - -pub static HIGHSTREET_42161_615BCEEA: TokenInfo = TokenInfo { - name: "Highstreet", - symbol: "HIGH", - decimals: 18, - contract: address!("0xd12Eeb0142D4Efe7Af82e4f29E5Af382615bcEeA"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470"), -}; - -pub static HOPR_42161_70294EF7: TokenInfo = TokenInfo { - name: "HOPR", - symbol: "HOPR", - decimals: 18, - contract: address!("0x177F394A3eD18FAa85c1462Ae626438a70294EF7"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14061/thumb/Shared_HOPR_logo_512px.png?1614073468"), -}; - -pub static IDOS_TOKEN: TokenInfo = TokenInfo { - name: "idOS Token", - symbol: "IDOS", - decimals: 18, - contract: address!("0x68731d6F14B827bBCfFbEBb62b19Daa18de1d79c"), - chain: 42161, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/39596.png"), -}; - -pub static ILLUVIUM_42161_05488673: TokenInfo = TokenInfo { - name: "Illuvium", - symbol: "ILV", - decimals: 18, - contract: address!("0x61cA9D186f6b9a793BC08F6C79fd35f205488673"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14468/large/ILV.JPG"), -}; - -pub static IMMUTABLE_X_42161_FCA7783E: TokenInfo = TokenInfo { - name: "Immutable X", - symbol: "IMX", - decimals: 18, - contract: address!("0x3cFD99593a7F035F717142095a3898e3Fca7783e"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/17233/thumb/imx.png?1636691817"), -}; - -pub static INJECTIVE_42161_DF608F80: TokenInfo = TokenInfo { - name: "Injective", - symbol: "INJ", - decimals: 18, - contract: address!("0x2A2053cb633CAD465B4A8975eD3d7f09DF608F80"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237"), -}; - -pub static JASMYCOIN_42161_73E27083: TokenInfo = TokenInfo { - name: "JasmyCoin", - symbol: "JASMY", - decimals: 18, - contract: address!("0x25f05699548D3A0820b99f93c10c8BB573E27083"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13876/thumb/JASMY200x200.jpg?1612473259"), -}; - -pub static KINTO: TokenInfo = TokenInfo { - name: "Kinto", - symbol: "K", - decimals: 18, - contract: address!("0x010700AB046Dd8e92b0e3587842080Df36364ed3"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/54964/standard/k200.png?1742894885"), -}; - -pub static KRYLL_42161_B7307B69: TokenInfo = TokenInfo { - name: "KRYLL", - symbol: "KRL", - decimals: 18, - contract: address!("0xf75eE6D319741057a82a88Eeff1DbAFAB7307b69"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979"), -}; - -pub static KUJIRA_42161_5671E7CA: TokenInfo = TokenInfo { - name: "Kujira", - symbol: "KUJI", - decimals: 6, - contract: address!("0x3A18dcC9745eDcD1Ef33ecB93b0b6eBA5671e7Ca"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png"), -}; - -pub static LIDO_DAO_42161_D85EFA60: TokenInfo = TokenInfo { - name: "Lido DAO", - symbol: "LDO", - decimals: 18, - contract: address!("0x13Ad51ed4F1B7e9Dc168d8a00cB3f4dDD85EfA60"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644"), -}; - -pub static CHAINLINK_TOKEN_42161_58539FB4: TokenInfo = TokenInfo { - name: "ChainLink Token", - symbol: "LINK", - decimals: 18, - contract: address!("0xf97f4df75117a78c1A5a0DBb814Af92458539FB4"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), -}; - -pub static LITENTRY_42161_30A40B25: TokenInfo = TokenInfo { - name: "Litentry", - symbol: "LIT", - decimals: 18, - contract: address!("0x349fc93da004a63F3B1343361465981330A40B25"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13825/large/logo_200x200.png"), -}; - -pub static LIVEPEER_42161_1CB8A839: TokenInfo = TokenInfo { - name: "Livepeer", - symbol: "LPT", - decimals: 18, - contract: address!("0x289ba1701C2F088cf0faf8B3705246331cB8A839"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/7137/thumb/logo-circle-green.png?1619593365"), -}; - -pub static LIQUITY_42161_CE3E1449: TokenInfo = TokenInfo { - name: "Liquity", - symbol: "LQTY", - decimals: 18, - contract: address!("0xfb9E5D956D889D91a82737B9bFCDaC1DCE3e1449"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180"), -}; - -pub static LOOPRINGCOIN_V2_42161_1BAE7FBE: TokenInfo = TokenInfo { - name: "LoopringCoin V2", - symbol: "LRC", - decimals: 18, - contract: address!("0x46d0cE7de6247b0A95f67b43B589b4041BaE7fbE"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png"), -}; - -pub static LIQUITY_USD_42161_2541425B: TokenInfo = TokenInfo { - name: "Liquity USD", - symbol: "LUSD", - decimals: 18, - contract: address!("0x93b346b6BC2548dA6A1E7d98E9a421B42541425b"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327"), -}; - -pub static MAGIC: TokenInfo = TokenInfo { - name: "MAGIC", - symbol: "MAGIC", - decimals: 18, - contract: address!("0x539bdE0d7Dbd336b79148AA742883198BBF60342"), - chain: 42161, - logo_uri: Some("https://dynamic-assets.coinbase.com/30320a63f6038b944c9c0202fcb2392e6a1bd333814f74b4674774dd87f2d06d64fdd74c2f1ab4639917c75b749c323450408bec7a2737af8ae0c17871aa90de/asset_icons/98d278cda11639ed7449a0a3086cd2c83937ce71baf4ee43bb5b777423c00a75.png"), -}; - -pub static DECENTRALAND_42161_A165E231: TokenInfo = TokenInfo { - name: "Decentraland", - symbol: "MANA", - decimals: 18, - contract: address!("0x442d24578A564EF628A65e6a7E3e7be2a165E231"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745"), -}; - -pub static MASK_NETWORK_42161_5C313739: TokenInfo = TokenInfo { - name: "Mask Network", - symbol: "MASK", - decimals: 18, - contract: address!("0x533A7B414CD1236815a5e09F1E97FC7d5c313739"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316"), -}; - -pub static MATH_42161_B17AC332: TokenInfo = TokenInfo { - name: "MATH", - symbol: "MATH", - decimals: 18, - contract: address!("0x99F40b01BA9C469193B360f72740E416B17Ac332"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590"), -}; - -pub static POLYGON_42161_18BE0766: TokenInfo = TokenInfo { - name: "Polygon", - symbol: "MATIC", - decimals: 18, - contract: address!("0x561877b6b3DD7651313794e5F2894B2F18bE0766"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), -}; - -pub static METIS_42161_D2E33769: TokenInfo = TokenInfo { - name: "Metis", - symbol: "METIS", - decimals: 18, - contract: address!("0x7F728F3595db17B0B359f4FC47aE80FAd2e33769"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312"), -}; - -pub static MAGIC_INTERNET_MONEY_42161_0C04DAF2: TokenInfo = TokenInfo { - name: "Magic Internet Money", - symbol: "MIM", - decimals: 18, - contract: address!("0xB20A02dfFb172C474BC4bDa3fD6f4eE70C04daf2"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612"), -}; - -pub static MAKER_42161_6F8F2879: TokenInfo = TokenInfo { - name: "Maker", - symbol: "MKR", - decimals: 18, - contract: address!("0x2e9a6Df78E42a30712c10a9Dc4b1C8656f8F2879"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png"), -}; - -pub static MELON_42161_7AE4B514: TokenInfo = TokenInfo { - name: "Melon", - symbol: "MLN", - decimals: 18, - contract: address!("0x8f5c1A99b1df736Ad685006Cb6ADCA7B7Ae4b514"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295"), -}; - -pub static MANTLE_42161_EDF6C53A: TokenInfo = TokenInfo { - name: "Mantle", - symbol: "MNT", - decimals: 18, - contract: address!("0x9c1a1C7bA9c2602123FD7EF3eb41a769edf6C53A"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/30980/large/Mantle-Logo-mark.png?1739213200"), -}; - -pub static MOG_COIN_42161_206AABAC: TokenInfo = TokenInfo { - name: "Mog Coin", - symbol: "MOG", - decimals: 18, - contract: address!("0x96c42662820F6Ea32f0A61A06a38a72B206aABaC"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/31059/large/MOG_LOGO_200x200.png"), -}; - -pub static MORPHO_TOKEN_42161_02F620AC: TokenInfo = TokenInfo { - name: "Morpho Token", - symbol: "MORPHO", - decimals: 18, - contract: address!("0xE390C0B46bd723995BE02640E6F1e1c802F620AC"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/29837/large/Morpho-token-icon.png?1726771230"), -}; - -pub static MAPLE_42161_097F0CA0: TokenInfo = TokenInfo { - name: "Maple", - symbol: "MPL", - decimals: 18, - contract: address!("0x29024832eC3baBF5074D4F46102aA988097f0Ca0"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14097/thumb/photo_2021-05-03_14.20.41.jpeg?1620022863"), -}; - -pub static MULTICHAIN_42161_ECD9A39A: TokenInfo = TokenInfo { - name: "Multichain", - symbol: "MULTI", - decimals: 18, - contract: address!("0x7b9b94aebe5E2039531af8E31045f377EcD9A39A"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238"), -}; - -pub static GENSOKISHI_METAVERSE_42161_3E15992F: TokenInfo = TokenInfo { - name: "GensoKishi Metaverse", - symbol: "MV", - decimals: 18, - contract: address!("0x5445972E76c5e4CEdD12B6e2BceF69133E15992F"), - chain: 42161, - logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/17704.png"), -}; - -pub static MXC_42161_B6862ED6: TokenInfo = TokenInfo { - name: "MXC", - symbol: "MXC", - decimals: 18, - contract: address!("0x91b468Fe3dce581D7a6cFE34189F1314b6862eD6"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/4604/thumb/mxc.png?1655534336"), -}; - -pub static POLYSWARM_42161_FB920D5B: TokenInfo = TokenInfo { - name: "PolySwarm", - symbol: "NCT", - decimals: 18, - contract: address!("0x53236015A675fcB937485F1AE58040e4Fb920d5b"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/2843/thumb/ImcYCVfX_400x400.jpg?1628519767"), -}; - -pub static NKN_42161_0406177B: TokenInfo = TokenInfo { - name: "NKN", - symbol: "NKN", - decimals: 18, - contract: address!("0xBE06ca305A5Cb49ABf6B1840da7c42690406177b"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/3375/thumb/nkn.png?1548329212"), -}; - -pub static NUMERAIRE_42161_6B569711: TokenInfo = TokenInfo { - name: "Numeraire", - symbol: "NMR", - decimals: 18, - contract: address!("0x597701b32553b9fa473e21362D480b3a6B569711"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png"), -}; - -pub static OCEAN_PROTOCOL_42161_AD8234DF: TokenInfo = TokenInfo { - name: "Ocean Protocol", - symbol: "OCEAN", - decimals: 18, - contract: address!("0x933d31561e470478079FEB9A6Dd2691fAD8234DF"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686"), -}; - -pub static ORIGIN_PROTOCOL_42161_58AE423E: TokenInfo = TokenInfo { - name: "Origin Protocol", - symbol: "OGN", - decimals: 18, - contract: address!("0x6FEb262FEb0f775B5312D2e009923f7f58AE423E"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878"), -}; - -pub static OMG_NETWORK_42161_61421E8E: TokenInfo = TokenInfo { - name: "OMG Network", - symbol: "OMG", - decimals: 18, - contract: address!("0xd962C1895c46AC0378C502c207748b7061421e8e"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/776/thumb/OMG_Network.jpg?1591167168"), -}; - -pub static ONDO_FINANCE_42161_8B37A5E7: TokenInfo = TokenInfo { - name: "Ondo Finance", - symbol: "ONDO", - decimals: 18, - contract: address!("0xA2d52A05B8Bead5d824DF54Dd1AA63188B37A5E7"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/26580/standard/ONDO.png?1696525656"), -}; - -pub static ORION_PROTOCOL_42161_551E6218: TokenInfo = TokenInfo { - name: "Orion Protocol", - symbol: "ORN", - decimals: 8, - contract: address!("0x1BDCC2075d5370293E248Cab0173eC3E551e6218"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11841/thumb/orion_logo.png?1594943318"), -}; - -pub static PENDLE_42161_B9A8C9E8: TokenInfo = TokenInfo { - name: "Pendle", - symbol: "PENDLE", - decimals: 18, - contract: address!("0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728"), -}; - -pub static PEPE_42161_33959CBB: TokenInfo = TokenInfo { - name: "Pepe", - symbol: "PEPE", - decimals: 18, - contract: address!("0x35E6A59F786d9266c7961eA28c7b768B33959cbB"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725"), -}; - -pub static PERPETUAL_PROTOCOL_42161_F61D3DAC: TokenInfo = TokenInfo { - name: "Perpetual Protocol", - symbol: "PERP", - decimals: 18, - contract: address!("0x753D224bCf9AAFaCD81558c32341416df61D3DAC"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), -}; - -pub static PIRATE_NATION_42161_43D77CBF: TokenInfo = TokenInfo { - name: "Pirate Nation", - symbol: "PIRATE", - decimals: 18, - contract: address!("0xac7CE9F2794e01c0D27b096C52f592e343D77cbf"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/38524/standard/_Pirate_Transparent_200x200.png"), -}; - -pub static PLUME_42161_CB15BA13: TokenInfo = TokenInfo { - name: "Plume", - symbol: "PLUME", - decimals: 18, - contract: address!("0x73efDC761596328461B68E5FC58c3284CB15ba13"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/53623/large/plume-token.png?1736896935"), -}; - -pub static POLYGON_ECOSYSTEM_TOKEN_42161_68FE08CC: TokenInfo = TokenInfo { - name: "Polygon Ecosystem Token", - symbol: "POL", - decimals: 18, - contract: address!("0x044d8e7F3A17751D521efEa8CCf9282268fE08CC"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/32440/large/polygon.png?1698233684"), -}; - -pub static POLKASTARTER_42161_8B016B64: TokenInfo = TokenInfo { - name: "Polkastarter", - symbol: "POLS", - decimals: 18, - contract: address!("0xeeeB5EaC2dB7A7Fc28134aA3248580d48b016b64"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702"), -}; - -pub static POLYMATH_42161_B33809E9: TokenInfo = TokenInfo { - name: "Polymath", - symbol: "POLY", - decimals: 18, - contract: address!("0xE12F29704F635F4A6E7Ae154838d21F9B33809e9"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034"), -}; - -pub static MARLIN_42161_C8BD9DDD: TokenInfo = TokenInfo { - name: "Marlin", - symbol: "POND", - decimals: 18, - contract: address!("0xdA0a57B710768ae17941a9Fa33f8B720c8bD9ddD"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/8903/thumb/POND_200x200.png?1622515451"), -}; - -pub static PORTAL_42161_9DB991DE: TokenInfo = TokenInfo { - name: "Portal", - symbol: "PORTAL", - decimals: 18, - contract: address!("0x6380F3d0C1412a80EB00F49064DA30749DB991DE"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/35436/standard/portal.jpeg"), -}; - -pub static POWER_LEDGER_42161_D423E4A6: TokenInfo = TokenInfo { - name: "Power Ledger", - symbol: "POWR", - decimals: 6, - contract: address!("0x4e91F2AF1ee0F84B529478f19794F5AFD423e4A6"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/1104/thumb/power-ledger.png?1547035082"), -}; - -pub static PRIME_42161_E7AC5067: TokenInfo = TokenInfo { - name: "Prime", - symbol: "PRIME", - decimals: 18, - contract: address!("0x8d8e1b6ffc6832E8D2eF0DE8a3d957cAE7ac5067"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222"), -}; - -pub static PARSIQ_42161_CAF60CD2: TokenInfo = TokenInfo { - name: "PARSIQ", - symbol: "PRQ", - decimals: 18, - contract: address!("0x82164a8B646401a8776F9dC5c8Cba35DcAf60Cd2"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280"), -}; - -pub static PAYPAL_USD_42161_0967342E: TokenInfo = TokenInfo { - name: "PayPal USD", - symbol: "PYUSD", - decimals: 6, - contract: address!("0x327006c8712FE0AbdbbD55B7999DB39b0967342E"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/31212/large/PYUSD_Logo_%282%29.png?1691458314"), -}; - -pub static QUANT_42161_3C7EFF85: TokenInfo = TokenInfo { - name: "Quant", - symbol: "QNT", - decimals: 18, - contract: address!("0xC7557C73e0eCa2E1BF7348bB6874Aee63C7eFF85"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/3370/thumb/5ZOu7brX_400x400.jpg?1612437252"), -}; - -pub static RADICLE_42161_12155E49: TokenInfo = TokenInfo { - name: "Radicle", - symbol: "RAD", - decimals: 18, - contract: address!("0x3c45038f4807c5bb72F6BC72c2A2B9c012155e49"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14013/thumb/radicle.png?1614402918"), -}; - -pub static RAI_REFLEX_INDEX_42161_78D419F2: TokenInfo = TokenInfo { - name: "Rai Reflex Index", - symbol: "RAI", - decimals: 18, - contract: address!("0xaeF5bbcbFa438519a5ea80B4c7181B4E78d419f2"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334"), -}; - -pub static RARIBLE_42161_63C1B8E0: TokenInfo = TokenInfo { - name: "Rarible", - symbol: "RARI", - decimals: 18, - contract: address!("0xCf78572A8fE97b2B9a4B9709f6a7D9a863c1b8E0"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11845/thumb/Rari.png?1594946953"), -}; - -pub static RUBIC_42161_5CBC335F: TokenInfo = TokenInfo { - name: "Rubic", - symbol: "RBC", - decimals: 18, - contract: address!("0x2E9AE8f178d5Ea81970C7799A377B3985cbC335F"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12629/thumb/200x200.png?1607952509"), -}; - -pub static REPUBLIC_TOKEN_42161_1C79A204: TokenInfo = TokenInfo { - name: "Republic Token", - symbol: "REN", - decimals: 18, - contract: address!("0x9fA891e1dB0a6D1eEAC4B929b5AAE1011C79a204"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png"), -}; - -pub static REQUEST_42161_8BB92171: TokenInfo = TokenInfo { - name: "Request", - symbol: "REQ", - decimals: 18, - contract: address!("0x1Cb5bBc64e148C5b889E3c667B49edF78BB92171"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/1031/thumb/Request_icon_green.png?1643250951"), -}; - -pub static RARI_GOVERNANCE_TOKEN_42161_CD794794: TokenInfo = TokenInfo { - name: "Rari Governance Token", - symbol: "RGT", - decimals: 18, - contract: address!("0xef888bcA6AB6B1d26dbeC977C455388ecd794794"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014"), -}; - -pub static IEXEC_RLC_42161_5D794E66: TokenInfo = TokenInfo { - name: "iExec RLC", - symbol: "RLC", - decimals: 9, - contract: address!("0xE575586566b02A16338c199c23cA6d295D794e66"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1604543202"), -}; - -pub static RENDER_TOKEN_42161_6F21E279: TokenInfo = TokenInfo { - name: "Render Token", - symbol: "RNDR", - decimals: 18, - contract: address!("0xC8a4EeA31E9B6b61c406DF013DD4FEc76f21E279"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11636/thumb/rndr.png?1638840934"), -}; - -pub static ROCKET_POOL_PROTOCOL_42161_1D0CC507: TokenInfo = TokenInfo { - name: "Rocket Pool Protocol", - symbol: "RPL", - decimals: 18, - contract: address!("0xB766039cc6DB368759C1E56B79AFfE831d0Cc507"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/2090/large/rocket_pool_%28RPL%29.png?1696503058"), -}; - -pub static RESERVE_RIGHTS_42161_DBD2E594: TokenInfo = TokenInfo { - name: "Reserve Rights", - symbol: "RSR", - decimals: 18, - contract: address!("0xCa5Ca9083702c56b481D1eec86F1776FDbd2e594"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856"), -}; - -pub static THE_SANDBOX_42161_D64E3DAC: TokenInfo = TokenInfo { - name: "The Sandbox", - symbol: "SAND", - decimals: 18, - contract: address!("0xd1318eb19DBF2647743c720ed35174efd64e3DAC"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1597397942"), -}; - -pub static STADER_42161_92F34B63: TokenInfo = TokenInfo { - name: "Stader", - symbol: "SD", - decimals: 18, - contract: address!("0x1629c4112952a7a377cB9B8d7d8c903092f34B63"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png"), -}; - -pub static SHIBA_INU_42161_E3872FD1: TokenInfo = TokenInfo { - name: "Shiba Inu", - symbol: "SHIB", - decimals: 18, - contract: address!("0x5033833c9fe8B9d3E09EEd2f73d2aaF7E3872fd1"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11939/thumb/shiba.png?1622619446"), -}; - -pub static SKALE_42161_37267878: TokenInfo = TokenInfo { - name: "SKALE", - symbol: "SKL", - decimals: 18, - contract: address!("0x4F9b7DEDD8865871dF65c5D26B1c2dD537267878"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/13245/thumb/SKALE_token_300x300.png?1606789574"), -}; - -pub static STATUS_42161_A6415160: TokenInfo = TokenInfo { - name: "Status", - symbol: "SNT", - decimals: 18, - contract: address!("0x707F635951193dDaFBB40971a0fCAAb8A6415160"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778"), -}; - -pub static SYNTHETIX_NETWORK_TOKEN_42161_BCA37D60: TokenInfo = TokenInfo { - name: "Synthetix Network Token", - symbol: "SNX", - decimals: 18, - contract: address!("0xcBA56Cd8216FCBBF3fA6DF6137F3147cBcA37D60"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), -}; - -pub static UNISOCKS_42161_A3B264E7: TokenInfo = TokenInfo { - name: "Unisocks", - symbol: "SOCKS", - decimals: 18, - contract: address!("0xb2BE52744a804Cc732d606817C2572C5A3B264e7"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/10717/thumb/qFrcoiM.png?1582525244"), -}; - -pub static SOL_WORMHOLE_42161_EC617124: TokenInfo = TokenInfo { - name: "SOL Wormhole ", - symbol: "SOL", - decimals: 9, - contract: address!("0xb74Da9FE2F96B9E0a5f4A3cf0b92dd2bEC617124"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), -}; - -pub static SPELL_TOKEN_42161_FE15D2AF: TokenInfo = TokenInfo { - name: "Spell Token", - symbol: "SPELL", - decimals: 18, - contract: address!("0x3E6648C5a70A150A88bCE65F4aD4d506Fe15d2AF"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862"), -}; - -pub static SPX6900_42161_5D2BA901: TokenInfo = TokenInfo { - name: "SPX6900", - symbol: "SPX", - decimals: 8, - contract: address!("0x53e70cc1d527b524A1C46Eaa892e4CB35d2ba901"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083"), -}; - -pub static SQD: TokenInfo = TokenInfo { - name: "SQD", - symbol: "SQD", - decimals: 18, - contract: address!("0x1337420dED5ADb9980CFc35f8f2B054ea86f8aB1"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/37869/standard/New_Logo_SQD_Icon.png?1720048443"), -}; - -pub static STARGATE_FINANCE_42161_A16313EC: TokenInfo = TokenInfo { - name: "Stargate Finance", - symbol: "STG", - decimals: 18, - contract: address!("0xe018C7a3d175Fb0fE15D70Da2c874d3CA16313EC"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518"), -}; - -pub static STORJ_TOKEN_42161_7AA2FCC2: TokenInfo = TokenInfo { - name: "Storj Token", - symbol: "STORJ", - decimals: 8, - contract: address!("0xE6320ebF209971b4F4696F7f0954b8457Aa2FCC2"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png"), -}; - -pub static SUPERFARM_42161_26498956: TokenInfo = TokenInfo { - name: "SuperFarm", - symbol: "SUPER", - decimals: 18, - contract: address!("0x7f9cf5a2630a0d58567122217dF7609c26498956"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899"), -}; - -pub static SYNTH_SUSD_42161_9D112F95: TokenInfo = TokenInfo { - name: "Synth sUSD", - symbol: "sUSD", - decimals: 18, - contract: address!("0xA970AF1a584579B618be4d69aD6F73459D112F95"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765"), -}; - -pub static SUSHI_42161_0D85C61A: TokenInfo = TokenInfo { - name: "Sushi", - symbol: "SUSHI", - decimals: 18, - contract: address!("0xd4d42F0b6DEF4CE0383636770eF773390d85c61A"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), -}; - -pub static SWELL_42161_A58F2571: TokenInfo = TokenInfo { - name: "Swell", - symbol: "SWELL", - decimals: 18, - contract: address!("0x2C96bE2612bec20fe2975C3ACFcbBe61a58f2571"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/28777/large/swell1.png?1727899715"), -}; - -pub static SYNAPSE_42161_375EAD84: TokenInfo = TokenInfo { - name: "Synapse", - symbol: "SYN", - decimals: 18, - contract: address!("0x1bCfc0B4eE1471674cd6A9F6B363A034375eAD84"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049"), -}; - -pub static THRESHOLD_NETWORK_42161_DEC21F55: TokenInfo = TokenInfo { - name: "Threshold Network", - symbol: "T", - decimals: 18, - contract: address!("0x0945Cae3ae47cb384b2d47BC448Dc6A9dEC21F55"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340"), -}; - -pub static TBTC_42161_0A572594: TokenInfo = TokenInfo { - name: "tBTC", - symbol: "tBTC", - decimals: 18, - contract: address!("0x7E2a1eDeE171C5B19E6c54D73752396C0A572594"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png"), -}; - -pub static TELLOR_42161_10D88242: TokenInfo = TokenInfo { - name: "Tellor", - symbol: "TRB", - decimals: 18, - contract: address!("0xd58D345Fd9c82262E087d2D0607624B410D88242"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686"), -}; - -pub static TRIBE_42161_03914A5A: TokenInfo = TokenInfo { - name: "Tribe", - symbol: "TRIBE", - decimals: 18, - contract: address!("0xBfAE6fecD8124ba33cbB2180aAb0Fe4c03914A5A"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/14575/thumb/tribe.PNG?1617487954"), -}; - -pub static TURBO_42161_EDE4576A: TokenInfo = TokenInfo { - name: "Turbo", - symbol: "TURBO", - decimals: 18, - contract: address!("0x5C816d4582c857dcadb1bB1F62Ad6c9DEde4576a"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/30117/large/TurboMark-QL_200.png?1708079597"), -}; - -pub static UMA_VOTING_TOKEN_V1_42161_9B0C3B22: TokenInfo = TokenInfo { - name: "UMA Voting Token v1", - symbol: "UMA", - decimals: 18, - contract: address!("0xd693Ec944A85eeca4247eC1c3b130DCa9B0C3b22"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), -}; - -pub static UNISWAP_42161_72F1F7F0: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0"), - chain: 42161, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static WORLD_LIBERTY_FINANCIAL_USD_42161_DD217A33: TokenInfo = TokenInfo { - name: "World Liberty Financial USD", - symbol: "USD1", - decimals: 18, - contract: address!("0x7550dE0A4b9Fb8CAbA8c32E72Ee356AFdd217A33"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/54977/large/USD1_1000x1000_transparent.png?1749297002"), -}; - -pub static USDCOIN_42161_268E5831: TokenInfo = TokenInfo { - name: "USDCoin", - symbol: "USDC", - decimals: 6, - contract: address!("0xaf88d065e77c8cC2239327C5EDb3A432268e5831"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), -}; - -pub static BRIDGED_USDC_42161_BDDB5CC8: TokenInfo = TokenInfo { - name: "Bridged USDC", - symbol: "USDC.e", - decimals: 6, - contract: address!("0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), -}; - -pub static PAX_DOLLAR_42161_B699DF8F: TokenInfo = TokenInfo { - name: "Pax Dollar", - symbol: "USDP", - decimals: 18, - contract: address!("0x78df3a6044Ce3cB1905500345B967788b699dF8f"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/6013/standard/Pax_Dollar.png?1696506427"), -}; - -pub static USDS_STABLECOIN_42161_749B876B: TokenInfo = TokenInfo { - name: "USDS Stablecoin", - symbol: "USDS", - decimals: 18, - contract: address!("0x6491c05A82219b8D1479057361ff1654749b876b"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/39926/large/usds.webp?1726666683"), -}; - -pub static USUAL_42161_2140ABBB: TokenInfo = TokenInfo { - name: "USUAL", - symbol: "USUAL", - decimals: 18, - contract: address!("0x7639AB8599f1b417CbE4ceD492fB30162140AbbB"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/51091/large/USUAL.jpg?1730035787"), -}; - -pub static WRAPPED_AMPLEFORTH_42161_8AE650BB: TokenInfo = TokenInfo { - name: "Wrapped Ampleforth", - symbol: "WAMPL", - decimals: 18, - contract: address!("0x1c8Ec4DE3c2BFD3050695D89853EC6d78AE650bb"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/20825/thumb/photo_2021-11-25_02-05-11.jpg?1637811951"), -}; - -pub static WRAPPED_BTC_42161_AEFC5B0F: TokenInfo = TokenInfo { - name: "Wrapped BTC", - symbol: "WBTC", - decimals: 8, - contract: address!("0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), -}; - -pub static WRAPPED_ETHER_42161_523FBAB1: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static WORLD_LIBERTY_FINANCIAL_42161_0E1980BF: TokenInfo = TokenInfo { - name: "World Liberty Financial", - symbol: "WLFI", - decimals: 18, - contract: address!("0x4D1d7134B87490AE5eEbdB22A5820d7d0E1980bf"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/50767/large/wlfi.png?1756438915"), -}; - -pub static WOO_NETWORK_42161_3AEFD07B: TokenInfo = TokenInfo { - name: "WOO Network", - symbol: "WOO", - decimals: 18, - contract: address!("0xcAFcD85D8ca7Ad1e1C6F82F651fA15E33AEfD07b"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), -}; - -pub static TETHER_GOLD_42161_CFC6C9D3: TokenInfo = TokenInfo { - name: "Tether Gold", - symbol: "XAUT", - decimals: 6, - contract: address!("0x9B86f3c7d145979ec6b2F42eD7f92D06cfC6C9d3"), - chain: 42161, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/10481/large/Tether_Gold.png?1696510471"), -}; - -pub static CHAIN_42161_4DEEAFED: TokenInfo = TokenInfo { - name: "Chain", - symbol: "XCN", - decimals: 18, - contract: address!("0x58BbC087e36Db40a84b22c1B93a042294deEAFEd"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054"), -}; - -pub static XSGD_42161_4C1C4302: TokenInfo = TokenInfo { - name: "XSGD", - symbol: "XSGD", - decimals: 6, - contract: address!("0xa05245Ade25cC1063EE50Cf7c083B4524c1C4302"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623"), -}; - -pub static YEARN_FINANCE_42161_085B1582: TokenInfo = TokenInfo { - name: "yearn finance", - symbol: "YFI", - decimals: 18, - contract: address!("0x82e3A8F066a6989666b031d916c43672085b1582"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), -}; - -pub static ZETACHAIN_42161_47B88954: TokenInfo = TokenInfo { - name: "Zetachain", - symbol: "Zeta", - decimals: 18, - contract: address!("0x6DdBbcE7858D276678FC2B36123fD60547b88954"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/26718/standard/Twitter_icon.png?1696525788"), -}; - -pub static LAYERZERO_42161_F13271CD: TokenInfo = TokenInfo { - name: "LayerZero", - symbol: "ZRO", - decimals: 18, - contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), - chain: 42161, - logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), -}; - -pub static TOKEN_0X_PROTOCOL_TOKEN_42161_19235AE2: TokenInfo = TokenInfo { - name: "0x Protocol Token", - symbol: "ZRX", - decimals: 18, - contract: address!("0xBD591Bd4DdB64b77B5f76Eab8f03d02519235Ae2"), - chain: 42161, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), -}; - -pub static WRAPPED_BITCOIN: TokenInfo = TokenInfo { - name: "Wrapped Bitcoin", - symbol: "BTC", - decimals: 18, - contract: address!("0xD629eb00dEced2a080B7EC630eF6aC117e614f1b"), - chain: 42220, - logo_uri: Some("https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_WBTC.png"), -}; - -pub static CELO: TokenInfo = TokenInfo { - name: "Celo", - symbol: "CELO", - decimals: 18, - contract: address!("0x471EcE3750Da237f93B8E339c536989b8978a438"), - chain: 42220, - logo_uri: Some("https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_CELO.png"), -}; - -pub static USDCOIN_42220_8B32118C: TokenInfo = TokenInfo { - name: "USDCoin", - symbol: "USDC", - decimals: 6, - contract: address!("0xcebA9300f2b948710d2653dD7B07f33A8B32118C"), - chain: 42220, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), -}; - -pub static TETHER_USD_42220_87483D5E: TokenInfo = TokenInfo { - name: "Tether USD", - symbol: "USDT", - decimals: 6, - contract: address!("0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e"), - chain: 42220, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), -}; - -pub static WRAPPED_ETHER_42220_622F4361: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0x2DEf4285787d58a2f811AF24755A8150622f4361"), - chain: 42220, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static TOKEN_1INCH_43114_8B28F267: TokenInfo = TokenInfo { - name: "1inch", - symbol: "1INCH", - decimals: 18, - contract: address!("0xd501281565bf7789224523144Fe5D98e8B28f267"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), -}; - -pub static AAVE_43114_E5D386D9: TokenInfo = TokenInfo { - name: "Aave", - symbol: "AAVE", - decimals: 18, - contract: address!("0x63a72806098Bd3D9520cC43356dD78afe5D386D9"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), -}; - -pub static AGEUR_43114_F1F96C57: TokenInfo = TokenInfo { - name: "agEur", - symbol: "agEUR", - decimals: 18, - contract: address!("0xAEC8318a9a59bAEb39861d10ff6C7f7bf1F96C57"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), -}; - -pub static ALPHA_VENTURE_DAO_43114_7A8E208F: TokenInfo = TokenInfo { - name: "Alpha Venture DAO", - symbol: "ALPHA", - decimals: 18, - contract: address!("0x2147EFFF675e4A4eE1C2f918d181cDBd7a8E208f"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876"), -}; - -pub static ANKR_43114_2C84B4DE: TokenInfo = TokenInfo { - name: "Ankr", - symbol: "ANKR", - decimals: 18, - contract: address!("0x20CF1b6E9d856321ed4686877CF4538F2C84B4dE"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978"), -}; - -pub static AXELAR_43114_CE194C5D: TokenInfo = TokenInfo { - name: "Axelar", - symbol: "AXL", - decimals: 6, - contract: address!("0x44c784266cf024a60e8acF2427b9857Ace194C5d"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg"), -}; - -pub static BASIC_ATTENTION_TOKEN_43114_A4690588: TokenInfo = TokenInfo { - name: "Basic Attention Token", - symbol: "BAT", - decimals: 18, - contract: address!("0x98443B96EA4b0858FDF3219Cd13e98C7A4690588"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427"), -}; - -pub static BINANCE_USD_43114_39D2DB39: TokenInfo = TokenInfo { - name: "Binance USD", - symbol: "BUSD", - decimals: 18, - contract: address!("0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), -}; - -pub static COMPOUND_43114_906E2437: TokenInfo = TokenInfo { - name: "Compound", - symbol: "COMP", - decimals: 18, - contract: address!("0xc3048E19E76CB9a3Aa9d77D8C03c29Fc906e2437"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), -}; - -pub static CARTESI_43114_0FABF552: TokenInfo = TokenInfo { - name: "Cartesi", - symbol: "CTSI", - decimals: 18, - contract: address!("0x6b289CCeAA8639e3831095D75A3e43520faBf552"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), -}; - -pub static DAI_E_TOKEN: TokenInfo = TokenInfo { - name: "DAI.e Token", - symbol: "DAI.e", - decimals: 18, - contract: address!("0xd586E7F844cEa2F87f50152665BCbc2C279D8d70"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/avalanchec/assets/0xd586E7F844cEa2F87f50152665BCbc2C279D8d70/logo.png"), -}; - -pub static DEFI_YIELD_PROTOCOL_43114_91BCEF17: TokenInfo = TokenInfo { - name: "DeFi Yield Protocol", - symbol: "DYP", - decimals: 18, - contract: address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066"), -}; - -pub static EURO_COIN_43114_505C2ACD: TokenInfo = TokenInfo { - name: "Euro Coin", - symbol: "EURC", - decimals: 6, - contract: address!("0xC891EB4cbdEFf6e073e859e987815Ed1505c2ACD"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/26045/standard/euro.png?1696525125"), -}; - -pub static FLUX_43114_C20DAF55: TokenInfo = TokenInfo { - name: "Flux", - symbol: "FLUX", - decimals: 8, - contract: address!("0xc4B06F17ECcB2215a5DBf042C672101Fc20daF55"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x720CD16b011b987Da3518fbf38c3071d4F0D1495/logo.png"), -}; - -pub static FRAX_43114_21A1DA64: TokenInfo = TokenInfo { - name: "Frax", - symbol: "FRAX", - decimals: 18, - contract: address!("0xD24C2Ad096400B6FBcd2ad8B24E7acBc21A1da64"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), -}; - -pub static FRAX_SHARE_43114_3FC8E387: TokenInfo = TokenInfo { - name: "Frax Share", - symbol: "FXS", - decimals: 18, - contract: address!("0x214DB107654fF987AD859F34125307783fC8e387"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), -}; - -pub static GMX_43114_5011C661: TokenInfo = TokenInfo { - name: "GMX", - symbol: "GMX", - decimals: 18, - contract: address!("0x62edc0692BD897D2295872a9FFCac5425011c661"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/18323/large/arbit.png?1631532468"), -}; - -pub static THE_GRAPH_43114_69E85CB9: TokenInfo = TokenInfo { - name: "The Graph", - symbol: "GRT", - decimals: 18, - contract: address!("0x8a0cAc13c7da965a312f08ea4229c37869e85cB9"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566"), -}; - -pub static GUNZ: TokenInfo = TokenInfo { - name: "GUNZ", - symbol: "GUN", - decimals: 18, - contract: address!("0x26deBD39D5eD069770406FCa10A0E4f8d2c743eB"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/55027/standard/gunz.jpg?1743262298"), -}; - -pub static CHAINLINK_TOKEN_43114_413227A3: TokenInfo = TokenInfo { - name: "ChainLink Token", - symbol: "LINK", - decimals: 18, - contract: address!("0x5947BB275c521040051D82396192181b413227A3"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), -}; - -pub static MAGIC_INTERNET_MONEY_43114_8CB8C18D: TokenInfo = TokenInfo { - name: "Magic Internet Money", - symbol: "MIM", - decimals: 18, - contract: address!("0x130966628846BFd36ff31a822705796e8cb8C18D"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612"), -}; - -pub static MAKER_43114_AAB72D42: TokenInfo = TokenInfo { - name: "Maker", - symbol: "MKR", - decimals: 18, - contract: address!("0x88128fd4b259552A9A1D457f435a6527AAb72d42"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png"), -}; - -pub static MULTICHAIN_43114_3C8764E3: TokenInfo = TokenInfo { - name: "Multichain", - symbol: "MULTI", - decimals: 18, - contract: address!("0x9Fb9a33956351cf4fa040f65A13b835A3C8764E3"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238"), -}; - -pub static PENDLE_43114_62EA213B: TokenInfo = TokenInfo { - name: "Pendle", - symbol: "PENDLE", - decimals: 18, - contract: address!("0xfB98B335551a418cD0737375a2ea0ded62Ea213b"), - chain: 43114, - logo_uri: Some("https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728"), -}; - -pub static RAI_REFLEX_INDEX_43114_031BFF7D: TokenInfo = TokenInfo { - name: "Rai Reflex Index", - symbol: "RAI", - decimals: 18, - contract: address!("0x97Cd1CFE2ed5712660bb6c14053C0EcB031Bff7d"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334"), -}; - -pub static SYNTHETIX_NETWORK_TOKEN_43114_BA4B209B: TokenInfo = TokenInfo { - name: "Synthetix Network Token", - symbol: "SNX", - decimals: 18, - contract: address!("0xBeC243C995409E6520D7C41E404da5dEba4b209B"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), -}; - -pub static SOL_WORMHOLE_43114_06D2478F: TokenInfo = TokenInfo { - name: "SOL Wormhole ", - symbol: "SOL", - decimals: 9, - contract: address!("0xFE6B19286885a4F7F55AdAD09C3Cd1f906D2478F"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), -}; - -pub static SPELL_TOKEN_43114_1A2F7814: TokenInfo = TokenInfo { - name: "Spell Token", - symbol: "SPELL", - decimals: 18, - contract: address!("0xCE1bFFBD5374Dac86a2893119683F4911a2F7814"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862"), -}; - -pub static STARGATE_FINANCE_43114_F56E7590: TokenInfo = TokenInfo { - name: "Stargate Finance", - symbol: "STG", - decimals: 18, - contract: address!("0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518"), -}; - -pub static SUSHI_43114_722E4F76: TokenInfo = TokenInfo { - name: "Sushi", - symbol: "SUSHI", - decimals: 18, - contract: address!("0x37B608519F91f70F2EeB0e5Ed9AF4061722e4F76"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), -}; - -pub static SYNAPSE_43114_E09CA251: TokenInfo = TokenInfo { - name: "Synapse", - symbol: "SYN", - decimals: 18, - contract: address!("0x1f1E7c893855525b303f99bDF5c3c05Be09ca251"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049"), -}; - -pub static UMA_VOTING_TOKEN_V1_43114_0A5B2339: TokenInfo = TokenInfo { - name: "UMA Voting Token v1", - symbol: "UMA", - decimals: 18, - contract: address!("0x3Bd2B1c7ED8D396dbb98DED3aEbb41350a5b2339"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), -}; - -pub static UNI_E_TOKEN: TokenInfo = TokenInfo { - name: "UNI.e Token", - symbol: "UNI.e", - decimals: 18, - contract: address!("0x8eBAf22B6F053dFFeaf46f4Dd9eFA95D89ba8580"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/avalanchec/assets/0x8eBAf22B6F053dFFeaf46f4Dd9eFA95D89ba8580/logo.png"), -}; - -pub static USDC_TOKEN: TokenInfo = TokenInfo { - name: "USDC Token", - symbol: "USDC", - decimals: 6, - contract: address!("0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/avalanchec/assets/0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E/logo.png"), -}; - -pub static TETHER_USD_43114_4DF4A8C7: TokenInfo = TokenInfo { - name: "Tether USD", - symbol: "USDT", - decimals: 6, - contract: address!("0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), -}; - -pub static WRAPPED_AVAX: TokenInfo = TokenInfo { - name: "Wrapped AVAX", - symbol: "WAVAX", - decimals: 18, - contract: address!("0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/avalanchec/assets/0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7/logo.png"), -}; - -pub static WRAPPED_BTC_43114_5187B218: TokenInfo = TokenInfo { - name: "Wrapped BTC", - symbol: "WBTC", - decimals: 8, - contract: address!("0x50b7545627a5162F82A992c33b87aDc75187B218"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), -}; - -pub static WRAPPED_ETHER_43114_6BC10BAB: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static WOO_NETWORK_43114_5F58D083: TokenInfo = TokenInfo { - name: "WOO Network", - symbol: "WOO", - decimals: 18, - contract: address!("0xaBC9547B534519fF73921b1FBA6E672b5f58D083"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), -}; - -pub static YEARN_FINANCE_43114_922F52DC: TokenInfo = TokenInfo { - name: "yearn finance", - symbol: "YFI", - decimals: 18, - contract: address!("0x9eAaC1B23d935365bD7b542Fe22cEEe2922f52dc"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), -}; - -pub static LAYERZERO_43114_F13271CD: TokenInfo = TokenInfo { - name: "LayerZero", - symbol: "ZRO", - decimals: 18, - contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), - chain: 43114, - logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), -}; - -pub static TOKEN_0X_PROTOCOL_TOKEN_43114_75CDE0D2: TokenInfo = TokenInfo { - name: "0x Protocol Token", - symbol: "ZRX", - decimals: 18, - contract: address!("0x596fA47043f99A4e0F122243B841E55375cdE0d2"), - chain: 43114, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), -}; - -pub static WRAPPED_ETHER_80001_C5D1C0AA: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa"), - chain: 80001, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static WRAPPED_MATIC_80001_FB032889: TokenInfo = TokenInfo { - name: "Wrapped Matic", - symbol: "WMATIC", - decimals: 18, - contract: address!("0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889"), - chain: 80001, - logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), -}; - -pub static BLAST: TokenInfo = TokenInfo { - name: "Blast", - symbol: "BLAST", - decimals: 18, - contract: address!("0xb1a5700fA2358173Fe465e6eA4Ff52E36e88E2ad"), - chain: 81457, - logo_uri: Some("https://assets.coingecko.com/coins/images/35494/standard/Blast.jpg?1719385662"), -}; - -pub static USD_COIN_BRIDGED_FROM_ETHEREUM: TokenInfo = TokenInfo { - name: "USD Coin (Bridged from Ethereum)", - symbol: "USDzC", - decimals: 6, - contract: address!("0xCccCCccc7021b32EBb4e8C08314bD62F7c653EC4"), - chain: 7777777, - logo_uri: Some("https://assets.coingecko.com/coins/images/35218/large/USDC_Icon.png?1707908537"), -}; - -pub static UNISWAP_11155111_4201F984: TokenInfo = TokenInfo { - name: "Uniswap", - symbol: "UNI", - decimals: 18, - contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), - chain: 11155111, - logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), -}; - -pub static WRAPPED_ETHER_11155111_324D6B14: TokenInfo = TokenInfo { - name: "Wrapped Ether", - symbol: "WETH", - decimals: 18, - contract: address!("0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"), - chain: 11155111, - logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), -}; - -pub static TOKENS: &[&TokenInfo] = &[ - &TOKEN_1INCH, - &ANCIENT8, - &AAVE, - &ARCBLOCK, - &ALCHEMY_PAY, - &ACROSS_PROTOCOL_TOKEN, - &AMBIRE_ADEX, - &AERGO, - &AEVO, - &AGEUR, - &ADVENTURE_GOLD, - &AIOZ_NETWORK, - &ALCHEMIX, - &ALEPH_IM, - &ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE, - &MY_NEIGHBOR_ALICE, - &ALLORA, - &ALPHA_VENTURE_DAO, - &ALTLAYER, - &, - &ANKR, - &ARAGON, - &APECOIN, - &API3, - &APRIORI, - &APU_APUSTAJA, - &ARBITRUM, - &ARKHAM, - &ARPA_CHAIN, - &ASH, - &ASSEMBLE_PROTOCOL, - &AIRSWAP, - &AUTOMATA, - &AETHIR_TOKEN, - &BOUNCE, - &AUDD, - &AUDIUS, - &ARTVERSE_TOKEN, - &AXELAR, - &AXIE_INFINITY, - &AZTEC, - &BADGER_DAO, - &BALANCER, - &BAND_PROTOCOL, - &LOMBARD, - &BASIC_ATTENTION_TOKEN, - &BEAM, - &BICONOMY, - &BIG_TIME, - &BIO, - &BITDAO, - &HARRYPOTTEROBAMASONIC10INU, - &BLUR, - &BLUZELLE, - &BANCOR_NETWORK_TOKEN, - &BOBA_NETWORK, - &BOB, - &BARNBRIDGE, - &BREVIS, - &BRAINTRUST, - &BINANCE_USD, - &COIN98, - &PANCAKESWAP, - &COINBASE_WRAPPED_BTC, - &COINBASE_WRAPPED_STAKED_ETH, - &CELO_NATIVE_ASSET_WORMHOLE, - &CELER_NETWORK, - &CENTRIFUGE, - &CHROMIA, - &CHILIZ, - &CLOVER_FINANCE, - &COMPOUND, - &CORN, - &COTI, - &CIRCUITS_OF_VALUE, - &COW_PROTOCOL, - &CLEARPOOL, - &COVALENT, - &CRONOS, - &CRYPTERIUM, - &CURVE_DAO_TOKEN, - &CARTESI, - &CRYPTEX_FINANCE, - &SOMNIUM_SPACE_CUBES, - &CIVIC, - &CONVEX_FINANCE, - &COVALENT_X_TOKEN, - &DAI_STABLECOIN, - &MINES_OF_DALARNIA, - &DERIVADAO, - &DENT, - &DEXTOOLS, - &DIA, - &DISTRICT0X, - &DOLOMITE, - &DOVU, - &DEFI_PULSE_INDEX, - &DREP, - &DERIVE, - &DYDX, - &DEFI_YIELD_PROTOCOL, - &EIGENLAYER, - &ELASTOS, - &DOGELON_MARS, - ÐENA, - &ENJIN_COIN, - ÐEREUM_NAME_SERVICE, - &CALDERA, - ÐERNITY_CHAIN, - &ESPRESSO, - ÐER_FI, - &EULER, - &EURO_COIN, - &SCHUMAN_EUR_P, - &QUANTOZ_EURQ, - &STABLR_EURO, - &HARVEST_FINANCE, - &FETCH_AI, - &FIDELITY_DIGITAL_DOLLAR, - &STAFI, - &FLOKI, - &FLUX, - &FORTA, - &LEFORTH_GOVERNANCE_TOKEN, - &SHAPESHIFT_FOX_TOKEN, - &FRAX, - &FANTOM, - &FUNCTION_X, - &FRAX_SHARE, - &GRAVITY, - &GALXE, - &GALA, - &GOLDFINCH, - &AAVEGOTCHI, - &GOLEM, - &GNOSIS_TOKEN, - &GODS_UNCHAINED, - &THE_GRAPH, - &GITCOIN, - &GEMINI_DOLLAR, - ÐGAS, - &GYEN, - &HASHFLOW, - &HIGHSTREET, - &HOPR, - &IDEX, - &ILLUVIUM, - &IMMUNEFI, - &IMMUTABLE_X, - &INDEX_COOPERATIVE, - &INJECTIVE, - &INVERSE_FINANCE, - &INFINEX, - &IOTEX, - &IRYS, - &GEOJAM, - &JASMYCOIN, - &JUPITER, - &KEEP_NETWORK, - &KERNELDAO, - &SELFKEY, - &KITE, - &KYBER_NETWORK_CRYSTAL, - &KEEP3RV1, - &KRYLL, - &KUJIRA, - &LAYER3, - &LAGRANGE, - &LCX, - &LIDO_DAO, - &LINEA, - &CHAINLINK_TOKEN, - &LITENTRY, - &LIGHTER, - &LEAGUE_OF_KINGDOMS, - &LOOM_NETWORK, - &LIVEPEER, - &LIQUITY, - &LOOPRINGCOIN_V2, - &BLOCKLORDS, - &LIQUID_STAKED_ETH, - &LISK, - &LIQUITY_USD, - &DECENTRALAND, - &MASK_NETWORK, - &MATH, - &POLYGON, - &MERIT_CIRCLE, - &MOSS_CARBON_CREDIT, - &MEASURABLE_DATA_TOKEN, - &MEMECOIN, - &METIS, - &MAGIC_INTERNET_MONEY, - &MIRROR_PROTOCOL, - &MAKER, - &MELON, - &MANTLE, - &MOG_COIN, - &MONAVALE, - &MORPHO_TOKEN, - &MOVEMENT, - &MAPLE, - &METAL, - &MULTICHAIN, - &MSTABLE_USD, - &MUSE_DAO, - &GENSOKISHI_METAVERSE, - &MXC, - &POLYSWARM, - &NEIRO, - &NEWTON, - &NKN, - &NUMERAIRE, - &NOMINA, - &NUCYPHER, - &OCEAN_PROTOCOL, - &ORIGIN_PROTOCOL, - &OMG_NETWORK, - &OMNI_NETWORK, - &ONDO_FINANCE, - &ORCA_ALLIANCE, - &ORION_PROTOCOL, - &ORCHID, - &PAYPEREX, - &PAX_GOLD, - &PLAYDAPP, - &PENDLE, - &PEPE, - &PERPETUAL_PROTOCOL, - &PIRATE_NATION, - &PLUTON, - &PLUME, - &POLYGON_ECOSYSTEM_TOKEN, - &POLKASTARTER, - &POLYMATH, - &MARLIN, - &PORTAL, - &POWER_LEDGER, - &PRIME, - &PROPY, - &SUCCINCT, - &PARSIQ, - &PSTAKE_FINANCE, - &PUFFER_FINANCE, - &PAYPAL_USD, - &QUANT, - &QREDO, - &QUANTSTAMP, - &QUICKSWAP, - &RADICLE, - &RAI_REFLEX_INDEX, - &SUPERRARE, - &RARIBLE, - &RUBIC, - &RIBBON_FINANCE, - &REDSTONE, - &REPUBLIC_TOKEN, - &REPUTATION_AUGUR_V1, - &REPUTATION_AUGUR_V2, - &REQUEST, - &REVV, - &RENZO, - &RARI_GOVERNANCE_TOKEN, - &IEXEC_RLC, - &RAYLS, - &RLUSD, - &RALLY, - &RENDER_TOKEN, - &ROBO_TOKEN, - &ROOK, - &ROCKET_POOL_PROTOCOL, - &RESERVE_RIGHTS, - &SAFE, - &THE_SANDBOX, - &STADER, - &SENTIENT, - &SHIBA_INU, - &SHPING, - &SKALE, - &SKY_GOVERNANCE_TOKEN, - &SMOOTH_LOVE_POTION, - &STATUS, - &SYNTHETIX_NETWORK_TOKEN, - &UNISOCKS, - &SOL_WORMHOLE, - &SPELL_TOKEN, - &SPARK, - &SPX6900, - &STARGATE_FINANCE, - &STORJ_TOKEN, - &STARKNET, - &STOX, - &SUKU, - &SUPERFARM, - &SYNTH_SUSD, - &SUSHI, - &SWELL, - &SWFTCOIN, - &SWIPE, - &SPACE_AND_TIME, - &SYLO, - &SYNAPSE, - &SYRUP_TOKEN, - &THRESHOLD_NETWORK, - &TBTC, - &TERM_FINANCE, - &THEORIQ, - &CHRONOTECH, - &ALIEN_WORLDS, - &TOKEMAK, - &TOKENFI, - &TE_FOOD, - &ORIGINTRAIL, - &TELLOR, - &TREEHOUSE_TOKEN, - &TRIA, - &TRIBE, - &TRUEFI, - &TURBO, - &THE_VIRTUA_KOLECT, - &UMA_VOTING_TOKEN_V1, - &UNIFI_PROTOCOL_DAO, - &UNISWAP, - &PAWTOCOL, - &WORLD_LIBERTY_FINANCIAL_USD, - &USDCOIN, - &GLOBAL_DOLLAR, - &PAX_DOLLAR, - &QUANTOZ_USDQ, - &STABLR_USD, - &USDS_STABLECOIN, - &TETHER_USD, - &USUAL, - &VANRY, - &VOYAGER_TOKEN, - &WRAPPED_AMPLEFORTH, - &WRAPPED_ANALOG_ONE_TOKEN, - &WRAPPED_BTC, - &WRAPPED_CENTRIFUGE, - &WALLETCONNECT_TOKEN, - &WRAPPED_ETHER, - &WORLD_LIBERTY_FINANCIAL, - &WOO_NETWORK, - &ANOMA, - &TETHER_GOLD, - &CHAIN, - &XSGD, - &XYO_NETWORK, - &YIELD_BASIS, - &YEARN_FINANCE, - &DFI_MONEY, - &YIELD_GUILD_GAMES, - &ZAMA, - &ZETACHAIN, - &BOUNDLESS, - &ZKPASS, - &LAYERZERO, - &TOKEN_0X_PROTOCOL_TOKEN, - &DAI_STABLECOIN_3_CE07538D, - &UNISWAP_3_4201F984, - &WRAPPED_ETHER_3_AA0CD5AB, - &DAI_STABLECOIN_4_A8FC4735, - &MAKER_4_359AAD85, - &UNISWAP_4_4201F984, - &WRAPPED_ETHER_4_AA0CD5AB, - &UNISWAP_5_4201F984, - &WRAPPED_ETHER_5_2B2208D6, - &TOKEN_1INCH_10_94736426, - &AAVE_10_950C9278, - &ACROSS_PROTOCOL_TOKEN_10_FDD1B76B, - &ARPA_CHAIN_10_C9BFA31E, - &BALANCER_10_E9379921, - &BICONOMY_10_C0FB1C9D, - &BOBA_NETWORK_10_CB88854D, - &BARNBRIDGE_10_3F276747, - &BRAINTRUST_10_E141254E, - &BINANCE_USD_10_39D2DB39, - &COINBASE_WRAPPED_STAKED_ETH_10_78DCF3B2, - &CELO_NATIVE_ASSET_WORMHOLE_10_B9B5C349, - &CURVE_DAO_TOKEN_10_0605FB53, - &CARTESI_10_071295BF, - &CYBER, - &DAI_STABLECOIN_10_C9000DA1, - &DERIVE_10_72BBA100, - ÐEREUM_NAME_SERVICE_10_5E890A00, - &STAFI_10_911BAD41, - &SHAPESHIFT_FOX_TOKEN_10_37CED174, - &FRAX_10_9A53F475, - &FRAX_SHARE_10_1C2205BE, - &GITCOIN_10_46445B08, - &GYEN_10_D9B6D5F7, - &KRYLL_10_C9022021, - &KUJIRA_10_5671E7CA, - &LIDO_DAO_10_2596735F, - &CHAINLINK_TOKEN_10_38FFA7F6, - &LOOPRINGCOIN_V2_10_1464907E, - &LIQUITY_USD_10_9B7B2819, - &MASK_NETWORK_10_BDF63798, - &MAKER_10_27F2FCB5, - &OCEAN_PROTOCOL_10_B8B49F9E, - &OPTIMISM, - &PENDLE_10_796E66E1, - &PEPE_10_9DDB16F5, - &PERPETUAL_PROTOCOL_10_976840E0, - &RAI_REFLEX_INDEX_10_7705448B, - &RARI_GOVERNANCE_TOKEN_10_DCEC711A, - &ROCKET_POOL_PROTOCOL_10_C14D1401, - &STATUS_10_64CFB6B2, - &SYNTHETIX_NETWORK_TOKEN_10_3D7599B4, - &SOL_WORMHOLE_10_7FA664F1, - &SUKU_10_0B9E50A4, - &SYNTH_SUSD_10_751EC8D9, - &SUSHI_10_0F60112B, - &THRESHOLD_NETWORK_10_8C734EA7, - &TELLOR_10_E3CEB888, - &UMA_VOTING_TOKEN_V1_10_855A77EA, - &UNISWAP_10_0E816691, - &USDCOIN_10_D097FF85, - &USDCOIN_BRIDGED_FROM_ETHEREUM, - &TETHER_USD_10_8CE58E58, - &VELODROME_FINANCE, - &WRAPPED_BTC_10_BF0A2095, - &WALLETCONNECT_TOKEN_10_DD927945, - &WRAPPED_ETHER_10_00000006, - &WORLDCOIN, - &WOO_NETWORK_10_51A5E527, - &XYO_NETWORK_10_DBD81FC8, - &YEARN_FINANCE_10_FEE9107B, - &LAYERZERO_10_F13271CD, - &TOKEN_0X_PROTOCOL_TOKEN_10_FA3C2F33, - &DAI_STABLECOIN_42_B64CA6AA, - &MAKER_42_71A4FFCD, - &UNISWAP_42_4201F984, - &WRAPPED_ETHER_42_C2CF029C, - &TOKEN_1INCH_56_4120C302, - &AAVE_56_7E58F802, - &ALCHEMY_PAY_56_7003056D, - &AMBIRE_ADEX_56_A7077819, - &AGEUR_56_D5FE5F89, - &AIOZ_NETWORK_56_9FC3741D, - &ALEPH_IM_56_DE9038C4, - &MY_NEIGHBOR_ALICE_56_745D63E8, - &ALPHA_VENTURE_DAO_56_13B40975, - &ANKR_56_531B08E3, - &ARPA_CHAIN_56_FA2D6F7E, - &ASTER, - &AUTOMATA_56_2F141225, - &AXELAR_56_C96F1F65, - &AXIE_INFINITY_56_D4D2F8A0, - &BLUZELLE_56_DA0ACDA2, - &BINANCE_USD_56_DD087D56, - &COIN98_56_90F1C3A6, - &CHROMIA_56_32B224FE, - &CLOVER_FINANCE_56_367A4E4D, - &COMPOUND_56_8CAD67E8, - &CIRCUITS_OF_VALUE_56_2B141464, - &CARTESI_56_2D033EF2, - &DAI_STABLECOIN_56_58B1DBC3, - &MINES_OF_DALARNIA_56_D45CD978, - &DEXTOOLS_56_C29896E3, - &DIA_56_7E0901DD, - &DREP_56_01A705FF, - &DEFI_YIELD_PROTOCOL_56_91BCEF17, - &DOGELON_MARS_56_D9BE2540, - &HARVEST_FINANCE_56_A5D33743, - &FETCH_AI_56_8691FA7F, - &FLOKI_56_5363D37E, - &FRAX_56_53E89F40, - &FANTOM_56_AF29DCFE, - &FRAX_SHARE_56_5EADB9EE, - &GALXE_56_40497AA5, - ÐGAS_56_B72F7D49, - &HASHFLOW_56_35883E47, - &HIGHSTREET_56_1FFEED63, - &INJECTIVE_56_EBE4D495, - &JUPITER_56_8E140CE7, - &KUJIRA_56_7C9FB5CC, - &CHAINLINK_TOKEN_56_111A51BD, - &MASK_NETWORK_56_F4D568A3, - &MATH_56_98A36983, - &POLYGON_56_5ED682BD, - &MERIT_CIRCLE_56_4EF9E5D6, - &METIS_56_B0820639, - &MAGIC_INTERNET_MONEY_56_19F433BA, - &MIRROR_PROTOCOL_56_10D8C2C9, - &MULTICHAIN_56_3C8764E3, - &PERPETUAL_PROTOCOL_56_84C7C6F5, - &POLKASTARTER_56_0887F570, - &PARSIQ_56_93D2A577, - &PSTAKE_FINANCE_56_F58A7C0C, - &REVV_56_8D702A93, - &STADER_56_0B5481E8, - &SOL_WORMHOLE_56_D3AEA76E, - &STARGATE_FINANCE_56_9631D62B, - &SUPERFARM_56_CC4F0D4D, - &SUSHI_56_FC9124C4, - &SWFTCOIN_56_55DFBAD3, - &SWIPE_56_FABA485A, - &SYNAPSE_56_1F9E9484, - &CHRONOTECH_56_DE5D7F68, - &ALIEN_WORLDS_56_EBD57C95, - &UNIFI_PROTOCOL_DAO_56_6B814D8B, - &UNISWAP_56_A02CE9B1, - &PAWTOCOL_56_94334EE4, - &USDCOIN_56_32CD580D, - &TETHER_USD_56_B3197955, - &WRAPPED_BNB, - &WRAPPED_ETHER_56_59F933F8, - &WOO_NETWORK_56_9E945D4B, - &CHAIN_56_DF88A05B, - &LAYERZERO_56_F13271CD, - &TOKEN_1INCH_130_A9ACD06E, - &ANCIENT8_130_FEF7759A, - &AAVE_130_BEEAAE1E, - &ARCBLOCK_130_FE5675BC, - &ALCHEMY_PAY_130_E66ECF77, - &ACROSS_PROTOCOL_TOKEN_130_62BBB32C, - &AMBIRE_ADEX_130_A299A500, - &AERGO_130_F15873B5, - &AEVO_130_60D60F8B, - &AGEUR_130_C681A118, - &ADVENTURE_GOLD_130_412721CF, - &AIOZ_NETWORK_130_6CF99B1A, - &ALCHEMIX_130_5AEBDCD6, - &ALEPH_IM_130_4C15BB5C, - &ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_130_EEC73780, - &MY_NEIGHBOR_ALICE_130_8860960A, - &ALPHA_VENTURE_DAO_130_CEBD78D3, - &ALTLAYER_130_B3589153, - &_130_2BBC967F, - &ANKR_130_EFF97622, - &ARAGON_130_D4A31308, - &APECOIN_130_314046CF, - &API3_130_F678961B, - &APU_APUSTAJA_130_63B9E379, - &ARBITRUM_130_18A4B40D, - &ARKHAM_130_442EF089, - &ARPA_CHAIN_130_88E30B45, - &ASH_130_5A30D7FB, - &ASSEMBLE_PROTOCOL_130_5BA0ADA7, - &AIRSWAP_130_8C09AE56, - &AUTOMATA_130_D890C4B2, - &AETHIR_TOKEN_130_FEE183AB, - &BOUNCE_130_91BEF68E, - &AUDIUS_130_3C81684B, - &ARTVERSE_TOKEN_130_00939999, - &AXELAR_130_A4CBF2C9, - &AXIE_INFINITY_130_D188F927, - &BADGER_DAO_130_17388406, - &BALANCER_130_34A8ADDF, - &BAND_PROTOCOL_130_6A8857D5, - &BASIC_ATTENTION_TOKEN_130_508EA589, - &BEAM_130_F9500824, - &BICONOMY_130_1D0588E7, - &BIG_TIME_130_D2FA7CDC, - &BITDAO_130_FB523A5C, - &HARRYPOTTEROBAMASONIC10INU_130_9B3D706F, - &BLUR_130_2B9255EA, - &BLUZELLE_130_8EF471EE, - &BANCOR_NETWORK_TOKEN_130_472C5A62, - &BOBA_NETWORK_130_BBB41B05, - &BARNBRIDGE_130_61DF8972, - &BONK, - &BRAINTRUST_130_00986B71, - &BINANCE_USD_130_BDA9F9C6, - &COIN98_130_F8E4F8E1, - &COINBASE_WRAPPED_BTC_130_AB6A1EF1, - &COINBASE_WRAPPED_STAKED_ETH_130_8211DB59, - &CELO_NATIVE_ASSET_WORMHOLE_130_5A8A8D9C, - &CELER_NETWORK_130_48035703, - &CHROMIA_130_210A4E5B, - &CHILIZ_130_8B2396B0, - &CLOVER_FINANCE_130_FA41404C, - &COMPOUND_130_F2288656, - &COTI_130_32F499C3, - &CIRCUITS_OF_VALUE_130_CC295BEC, - &COW_PROTOCOL_130_B26D3996, - &CLEARPOOL_130_423DFB57, - &COVALENT_130_621F90C1, - &CRONOS_130_A30DE818, - &CRYPTERIUM_130_18B0D066, - &CURVE_DAO_TOKEN_130_D1C2CCB3, - &CARTESI_130_BAAED2C5, - &CRYPTEX_FINANCE_130_62FCB619, - &SOMNIUM_SPACE_CUBES_130_92C2F8AF, - &CIVIC_130_E85A01ED, - &CONVEX_FINANCE_130_F0087EA5, - &COVALENT_X_TOKEN_130_F14E5A09, - &DAI_STABLECOIN_130_19573F81, - &MINES_OF_DALARNIA_130_90288086, - &DERIVADAO_130_3A270265, - &DENT_130_328E874C, - &DEXTOOLS_130_1723CDDD, - &DIA_130_3F9543C2, - &DISTRICT0X_130_C1B9E545, - &DOGECOIN, - &DEFI_PULSE_INDEX_130_CD2F84F1, - &DREP_130_38EA9EE7, - &DYDX_130_5FAEB82C, - &DEFI_YIELD_PROTOCOL_130_9D598610, - &EIGENLAYER_130_D016C47D, - &ELASTOS_130_D8E8C1AB, - &DOGELON_MARS_130_26C1DE05, - ÐENA_130_A6CBD2DD, - &ENJIN_COIN_130_84A6D0A6, - ÐEREUM_NAME_SERVICE_130_B5F0383A, - ÐERNITY_CHAIN_130_A93CDB03, - ÐER_FI_130_58880821, - &EULER_130_5B5D03FE, - &EURO_COIN_130_2813B0A8, - &QUANTOZ_EURQ_130_24D7D72D, - &STABLR_EURO_130_9C36FB5F, - &HARVEST_FINANCE_130_31EE825F, - &FETCH_AI_130_DDD7DFE7, - &STAFI_130_A10764A6, - &FLOKI_130_6C51FA81, - &FORTA_130_D87D94E5, - &LEFORTH_GOVERNANCE_TOKEN_130_2220F12E, - &SHAPESHIFT_FOX_TOKEN_130_3B7A318E, - &FRAX_130_D74132B9, - &FANTOM_130_90DC7F0E, - &FUNCTION_X_130_1D7AF1AF, - &FRAX_SHARE_130_062021D6, - &GRAVITY_130_6FD8803C, - &GALXE_130_443D8675, - &GALA_130_B560FAC9, - &GOLDFINCH_130_B157D3D0, - &AAVEGOTCHI_130_840AD24B, - &GOLEM_130_E2C9F2B9, - &GNOSIS_TOKEN_130_E125A938, - &GODS_UNCHAINED_130_D3683F48, - &THE_GRAPH_130_B3204D71, - &GITCOIN_130_8FE5CF48, - &GEMINI_DOLLAR_130_5C0920A9, - &GYEN_130_A574C36F, - &HASHFLOW_130_8C34A28B, - &HIGHSTREET_130_B1374879, - &HOPR_130_AF385B36, - &HYPERLIQUID, - &IDEX_130_60EABE8E, - &ILLUVIUM_130_42F3E51F, - &IMMUTABLE_X_130_F5AA8053, - &INDEX_COOPERATIVE_130_121E39B7, - &INJECTIVE_130_9A89F9F8, - &INVERSE_FINANCE_130_9F7B54FB, - &IOTEX_130_E2B6843F, - &GEOJAM_130_1D5C61A8, - &JASMYCOIN_130_22720708, - &JUPITER_130_E5CAB8B2, - &JUPITER_130_2381AFAD, - &KEEP_NETWORK_130_EA6AFE80, - &SELFKEY_130_3F1BBFDC, - &KYBER_NETWORK_CRYSTAL_130_B7CD2284, - &KEEP3RV1_130_5FAD6A74, - &KRYLL_130_4F002943, - &KUJIRA_130_30258681, - &LAYER3_130_1B7B482C, - &LCX_130_46687782, - &LIDO_DAO_130_814E8829, - &CHAINLINK_TOKEN_130_9BBEEFB7, - &LITENTRY_130_91BE0FDF, - &LEAGUE_OF_KINGDOMS_130_AAC89733, - &LOOM_NETWORK_130_009F523C, - &LIVEPEER_130_F35B73E3, - &LIQUITY_130_53C71A60, - &LOOPRINGCOIN_V2_130_A8AB158A, - &BLOCKLORDS_130_0C7BEE3F, - &LIQUITY_USD_130_D72577FB, - &DECENTRALAND_130_00FE358B, - &MASK_NETWORK_130_1B9512C4, - &MATH_130_99ED2C97, - &POLYGON_130_6507176B, - &MERIT_CIRCLE_130_2D657399, - &MOSS_CARBON_CREDIT_130_7E6ACC40, - &MEASURABLE_DATA_TOKEN_130_31BFEFF4, - &MEMECOIN_130_8E3E7D06, - &METIS_130_B3A8F102, - &MAGIC_INTERNET_MONEY_130_3E3602AB, - &MIRROR_PROTOCOL_130_4A72D717, - &MELON_130_4DC3C117, - &MOG_COIN_130_78921EBD, - &MONAVALE_130_1C7A1087, - &MOVEMENT_130_0FF19949, - &MAPLE_130_D752A219, - &METAL_130_6CFAD9EA, - &MULTICHAIN_130_D82B4701, - &MSTABLE_USD_130_B40A8DD1, - &MUSE_DAO_130_81D5F345, - &GENSOKISHI_METAVERSE_130_FF182974, - &MXC_130_02727794, - &POLYSWARM_130_795032DF, - &NEIRO_130_87696276, - &NKN_130_336BAF62, - &NUMERAIRE_130_DBDA20FC, - &NUCYPHER_130_AACEA6B9, - &OCEAN_PROTOCOL_130_3CD79208, - &ORIGIN_PROTOCOL_130_EE18C880, - &OMG_NETWORK_130_8EE37383, - &OMNI_NETWORK_130_959EB0E3, - &ONDO_FINANCE_130_85321557, - &ORCA_ALLIANCE_130_1BE3E8C0, - &ORION_PROTOCOL_130_B6EAF396, - &ORCHID_130_52B98042, - &PAYPEREX_130_0D292327, - &PLAYDAPP_130_1E75D6AC, - &PEPE_130_9074952B, - &PERPETUAL_PROTOCOL_130_CCFEC7D5, - &PIRATE_NATION_130_18D064C6, - &PLUTON_130_ABB6F6C7, - &POLYGON_ECOSYSTEM_TOKEN_130_E5682E95, - &POLKASTARTER_130_DC306503, - &POLYMATH_130_D538D863, - &MARLIN_130_4D4782D5, - &PORTAL_130_0F2A5642, - &POWER_LEDGER_130_DFFA6BFF, - &PRIME_130_CBF9FEE0, - &PROPY_130_1F41A7C9, - &PARSIQ_130_0ABF3DEF, - &PSTAKE_FINANCE_130_E7D7CAA2, - &PUFFER_FINANCE_130_38B560D2, - &PAYPAL_USD_130_8E6207C5, - &QUANT_130_98C360D4, - &QREDO_130_8C1068B8, - &QUANTSTAMP_130_6BB5EABB, - &QUICKSWAP_130_F8E6CAC2, - &RADICLE_130_F08A1A45, - &RAI_REFLEX_INDEX_130_89F34A66, - &SUPERRARE_130_E025BB6F, - &RARIBLE_130_03C8561C, - &RUBIC_130_66B403E3, - &RIBBON_FINANCE_130_C841CD3E, - &REPUBLIC_TOKEN_130_8261617E, - &REPUTATION_AUGUR_V1_130_B2816FC4, - &REPUTATION_AUGUR_V2_130_1E72A8C4, - &REQUEST_130_9D8663CD, - &REVV_130_0F9CA657, - &RENZO_130_AAD6C9AB, - &RARI_GOVERNANCE_TOKEN_130_946CF284, - &IEXEC_RLC_130_B3347ACB, - &RALLY_130_3F88C889, - &RENDER_TOKEN_130_8D649868, - &ROOK_130_9DE41D99, - &RESERVE_RIGHTS_130_B1889066, - &SAFE_130_10EFD888, - &THE_SANDBOX_130_2CAF25CA, - &STADER_130_B32D72E5, - &SHIBA_INU_130_5664158E, - &SHPING_130_66024F2F, - &SKALE_130_8AD20C01, - &SKY_GOVERNANCE_TOKEN_130_D07074E4, - &SMOOTH_LOVE_POTION_130_96CB03B3, - &STATUS_130_265ABF5F, - &SYNTHETIX_NETWORK_TOKEN_130_59E6BC88, - &UNISOCKS_130_DC4627AB, - &SOL_WORMHOLE_130_C3D054FE, - &SOLANA, - &SPELL_TOKEN_130_C17FEF7F, - &SPX6900_130_036DD629, - &STARGATE_FINANCE_130_19373135, - &STORJ_TOKEN_130_C9951835, - &STARKNET_130_2332C72E, - &STOX_130_CACCEA22, - &SUKU_130_82176525, - &SUPERFARM_130_2BD86D3D, - &SYNTH_SUSD_130_9B3A6A0F, - &SUSHI_130_BDFB3CE5, - &SWELL_130_028A5870, - &SWFTCOIN_130_45AF1616, - &SWIPE_130_9785C2E1, - &SYLO_130_CFFCF85E, - &SYNAPSE_130_81888A48, - &SYRUP_TOKEN_130_8CD6FA96, - &THRESHOLD_NETWORK_130_48F2AD54, - &BITTENSOR, - &TBTC_130_20BC7814, - &CHRONOTECH_130_1EDA749C, - &ALIEN_WORLDS_130_A9A46C68, - &TOKEMAK_130_36213E0B, - &TE_FOOD_130_A7BD5AC6, - &ORIGINTRAIL_130_DBAE6F2E, - &TELLOR_130_6D8EC63B, - &TRIBE_130_33DACDBD, - &TRUEFI_130_F30CFE0E, - &TURBO_130_F2D202A1, - &THE_VIRTUA_KOLECT_130_13BD9D5D, - &UMA_VOTING_TOKEN_V1_130_72435F8C, - &UNIFI_PROTOCOL_DAO_130_0408A30B, - &UNISWAP_130_7CE9EA21, - &PAWTOCOL_130_3E264D36, - &USDCOIN_130_0EF57AD6, - &GLOBAL_DOLLAR_130_A9F86F1E, - &PAX_DOLLAR_130_6DE0FEFF, - &QUANTOZ_USDQ_130_7B2F3A5F, - &STABLR_USD_130_004C06A7, - &USDS_STABLECOIN_130_3B2F7BB4, - &TETHER_USD_130_54C75518, - &USUAL_130_98BC5950, - &VANRY_130_01564A0B, - &VOYAGER_TOKEN_130_8FFE537F, - &WRAPPED_AMPLEFORTH_130_06364A49, - &WRAPPED_BTC_130_4EC4AFB8, - &WRAPPED_CENTRIFUGE_130_D72E82C4, - &WRAPPED_ETHER_130_00000006, - &DOGWIFHAT, - &WOO_NETWORK_130_EFD89E62, - &CHAIN_130_DC06A12F, - &PLASMA, - &XRP, - &XSGD_130_021265C3, - &XYO_NETWORK_130_2AEBE4EA, - &YEARN_FINANCE_130_F84A3201, - &DFI_MONEY_130_6C18A07E, - &YIELD_GUILD_GAMES_130_76E36F4B, - &ZCASH, - &ZETACHAIN_130_B3CB3CA4, - &LAYERZERO_130_7ED29CFB, - &TOKEN_0X_PROTOCOL_TOKEN_130_A6E7EDF5, - &AAVE_137_2B21C90B, - &AGEUR_137_C0057DB4, - &_137_4F27054D, - &BALANCER_137_3B0E76A3, - &BAND_PROTOCOL_137_D82606AC, - &BANCOR_NETWORK_TOKEN_137_2A4F7842, - &COMPOUND_137_837AEF5C, - &CURVE_DAO_TOKEN_137_33A610AF, - &CIVIC_137_398B02BE, - &DAI_STABLECOIN_137_39C6A063, - ÐEREUM_NAME_SERVICE_137_90EE7C4F, - &GNOSIS_TOKEN_137_7DF024A8, - &THE_GRAPH_137_499F5531, - &KEEP_NETWORK_137_2EB0C72C, - &KYBER_NETWORK_CRYSTAL_137_9CFA1DC7, - &CHAINLINK_TOKEN_137_3FABAD39, - &LOOM_NETWORK_137_1193F6B3, - &LOOPRINGCOIN_V2_137_BB47DDC1, - &DECENTRALAND_137_33606FD4, - &POLYGON_137_00001010, - &MAKER_137_E01FF61D, - &NUMERAIRE_137_11F46729, - &ORCHID_137_D31F6060, - &REPUBLIC_TOKEN_137_26ED89D0, - &REPUTATION_AUGUR_V2_137_7363F733, - &SYNTHETIX_NETWORK_TOKEN_137_11FEF68A, - &STORJ_TOKEN_137_5A3F5792, - &SYNTH_SUSD_137_6E03A7A0, - &UMA_VOTING_TOKEN_V1_137_77A6B731, - &UNISWAP_137_7FB5180F, - &USDCOIN_137_3D5C3359, - &USDCOIN_POS, - &TETHER_USD_137_04B58E8F, - &VANAR_CHAIN, - &VOXIES, - &WRAPPED_BTC_137_47D9BFD6, - &WRAPPED_ETHER_137_F1B9F619, - &WRAPPED_MATIC, - &XSGD_137_8D201995, - &YEARN_FINANCE_137_465260B6, - &LAYERZERO_137_F13271CD, - &TOKEN_0X_PROTOCOL_TOKEN_137_CA6BE3D5, - &SOL_WORMHOLE_143_245217F1, - &USDCOIN_143_5AAFB603, - &TETHER_USD_143_750FC82D, - &WRAPPED_BTC_143_230D2B9C, - &WRAPPED_ETHER_143_35481242, - &GLOBAL_DOLLAR_196_933D2DC8, - &ZKSYNC, - &BRIDGED_USDC, - &WRAPPED_BTC_480_2D70CFA3, - &WRAPPED_ETHER_480_00000006, - &USDCOIN_1868_4AACC369, - &TETHER_USD_1868_97B5AE35, - &WRAPPED_ETHER_1868_00000006, - &TOKEN_1INCH_8453_1E111CBE, - &AAVE_8453_D17F814B, - &ARCBLOCK_8453_7C1FA556, - &AMBIRE_ADEX_8453_A3E0EFD9, - &AERODROME_FINANCE, - &AIXBT_BY_VIRTUALS, - &ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_8453_D59F3DCC, - &AUSTRALIAN_DIGITAL_DOLLAR, - &AVANTIS, - &AWE_NETWORK, - &B3, - &HARRYPOTTEROBAMASONIC10INU_8453_D39A1A29, - &BANKRCOIN, - &COINBASE_WRAPPED_ADA, - &COINBASE_WRAPPED_BTC_8453_0EED33BF, - &COINBASE_WRAPPED_DOGE, - &COINBASE_WRAPPED_STAKED_ETH_8453_CF0DEC22, - &COINBASE_WRAPPED_LTC, - &COINBASE_WRAPPED_XRP, - &TOKENBOT, - &COMPOUND_8453_976840E0, - &COOKIE, - &CURVE_DAO_TOKEN_8453_67DD0415, - &CARTESI_8453_76138D45, - &CRYPTEX_FINANCE_8453_D4666E14, - &COVALENT_X_TOKEN_8453_8EB628FF, - &DAI_STABLECOIN_8453_917DB0CB, - &DEGEN, - &DOGINME, - &DOVU_8453_B953F865, - &DERIVE_8453_B645D083, - &DEFINITIVE, - &ELSA, - &EURC, - &FAI, - &FLOCK, - &FLUID, - &SPORT_FUN, - &HOME, - &HYPERLANE, - &IOTEX_8453_27AE38C1, - &GEOJAM_8453_3AA2A057, - &KAITO, - &KEYBOARD_CAT, - &KRYLL_8453_611F9F7A, - &KEETA, - &LCX_8453_71D3C171, - &LIQUITY_8453_BDDC125C, - &MAMO, - &NOICE, - &ODOS_TOKEN, - &PENDLE_8453_029EEB3E, - &PEPE_8453_8B982BE3, - &PERPETUAL_PROTOCOL_8453_DAAD58DE, - &PRIME_8453_A5ADD21B, - &PROPY_8453_9230438B, - &PROMPT, - &RAVEDAO, - &RECALL_NETWORK, - &RAINBOW, - &RESEARCHCOIN, - &RESERVE_RIGHTS_8453_6072F64A, - &SAPIEN, - &SEAMLESSS, - &STATUS_8453_2E8AC09E, - &SYNTHETIX_NETWORK_TOKEN_8453_327FDA66, - &SPX6900_8453_6819BB2C, - &SUPERFLUID_TOKEN, - &SUSHI_8453_98B2AFBA, - &SYNDICATE, - &TBTC_8453_22AB794B, - &TOSHI, - &TOWNS, - &INTUITION, - &UNISWAP_8453_114A3C83, - &SUPERFORM, - &USD_BASE_COIN, - &USD_COIN, - &VENICE_TOKEN, - &WALLETCONNECT_TOKEN_8453_DD927945, - &MOONWELL, - &WRAPPED_ETHER_8453_00000006, - &WORLD_MOBILE_TOKEN, - &XYO_NETWORK_8453_223ADC94, - &YEARN_FINANCE_8453_AD3CB239, - &YIELD_GUILD_GAMES_8453_F5EF1799, - &HORIZEN, - &BOUNDLESS_8453_FBBCE7CF, - &ZORA, - &LAYERZERO_8453_F13271CD, - &TOKEN_0X_PROTOCOL_TOKEN_8453_BC9779D0, - &TOKEN_1INCH_42161_3F4BB9AF, - &AAVE_42161_CE967196, - &ACROSS_PROTOCOL_TOKEN_42161_03D9C99D, - &AEVO_42161_2B9783CD, - &AGEUR_42161_723528E7, - &ADVENTURE_GOLD_42161_012A3B9C, - &AIOZ_NETWORK_42161_E1569923, - &ALEPH_IM_42161_8E245A6C, - &ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_42161_FC0A71D1, - &ALPHA_VENTURE_DAO_42161_0A6B2646, - &ANKR_42161_C1E95447, - &APECOIN_42161_DBAD2210, - &API3_42161_92CA7811, - &ARBITRUM_42161_E49E6548, - &ARKHAM_42161_DA4E656E, - &AUTOMATA_42161_75714D03, - &AETHIR_TOKEN_42161_49092FB4, - &AXELAR_42161_E2C6810F, - &AXIE_INFINITY_42161_3E5D0089, - &BADGER_DAO_42161_0D76472E, - &BALANCER_42161_F56A56B8, - &BASIC_ATTENTION_TOKEN_42161_616AEE75, - &BICONOMY_42161_60A8E74D, - &BITDAO_42161_EB921C2A, - &HARRYPOTTEROBAMASONIC10INU_42161_13BD565D, - &BLUR_42161_FE606EB2, - &BANCOR_NETWORK_TOKEN_42161_BA06D073, - &BARNBRIDGE_42161_EE64A4E1, - &BINANCE_USD_42161_462629A2, - &PANCAKESWAP_42161_7CF58860, - &COINBASE_WRAPPED_BTC_42161_0EED33BF, - &COINBASE_WRAPPED_STAKED_ETH_42161_EAE7732F, - &CELO_NATIVE_ASSET_WORMHOLE_42161_1EF4F336, - &CELER_NETWORK_42161_40F345AB, - &COMPOUND_42161_5C6C91DE, - &COTI_42161_D81EA101, - &COW_PROTOCOL_42161_F5C87A04, - &COVALENT_42161_657273BF, - &CRONOS_42161_676F354C, - &CURVE_DAO_TOKEN_42161_FA034978, - &CARTESI_42161_1B476999, - &CRYPTEX_FINANCE_42161_0425E12B, - &CIVIC_42161_1DDBF144, - &CONVEX_FINANCE_42161_520829C5, - &DAI_STABLECOIN_42161_C9000DA1, - &DEXTOOLS_42161_9B64E227, - &DIA_42161_E17AC05E, - &DISTRICT0X_42161_A49AD47A, - &DEFI_PULSE_INDEX_42161_B68DD74C, - &DERIVE_42161_90ABB135, - &DYDX_42161_8CC90C5A, - &EIGENLAYER_42161_6F96C248, - &DOGELON_MARS_42161_17077FD4, - ÐENA_42161_8EA977D8, - &ENJIN_COIN_42161_63806758, - ÐEREUM_NAME_SERVICE_42161_E70D7C28, - ÐERNITY_CHAIN_42161_4D667F96, - &ESPRESSO_42161_065C94F1, - ÐER_FI_42161_4DFD5736, - &EURO_COIN_42161_1FC52A48, - &HARVEST_FINANCE_42161_24C83C70, - &FETCH_AI_42161_7DCC4CC9, - &STAFI_42161_767C7282, - &FLOKI_42161_B4905FAE, - &FLUX_42161_D685710A, - &FORTA_42161_CC3D2923, - &SHAPESHIFT_FOX_TOKEN_42161_9E513C73, - &FRAX_42161_0BC51305, - &FANTOM_42161_D4C2DF37, - &FRAX_SHARE_42161_AFFFDEA4, - &GALXE_42161_9BFD1182, - &GALA_42161_2827FF8C, - &GMX, - &GNOSIS_TOKEN_42161_4DEB6CF1, - &THE_GRAPH_42161_EA7E88C7, - &GITCOIN_42161_C437DEE0, - &GYEN_42161_D9B6D5F7, - &HIGHSTREET_42161_615BCEEA, - &HOPR_42161_70294EF7, - &IDOS_TOKEN, - &ILLUVIUM_42161_05488673, - &IMMUTABLE_X_42161_FCA7783E, - &INJECTIVE_42161_DF608F80, - &JASMYCOIN_42161_73E27083, - &KINTO, - &KRYLL_42161_B7307B69, - &KUJIRA_42161_5671E7CA, - &LIDO_DAO_42161_D85EFA60, - &CHAINLINK_TOKEN_42161_58539FB4, - &LITENTRY_42161_30A40B25, - &LIVEPEER_42161_1CB8A839, - &LIQUITY_42161_CE3E1449, - &LOOPRINGCOIN_V2_42161_1BAE7FBE, - &LIQUITY_USD_42161_2541425B, - &MAGIC, - &DECENTRALAND_42161_A165E231, - &MASK_NETWORK_42161_5C313739, - &MATH_42161_B17AC332, - &POLYGON_42161_18BE0766, - &METIS_42161_D2E33769, - &MAGIC_INTERNET_MONEY_42161_0C04DAF2, - &MAKER_42161_6F8F2879, - &MELON_42161_7AE4B514, - &MANTLE_42161_EDF6C53A, - &MOG_COIN_42161_206AABAC, - &MORPHO_TOKEN_42161_02F620AC, - &MAPLE_42161_097F0CA0, - &MULTICHAIN_42161_ECD9A39A, - &GENSOKISHI_METAVERSE_42161_3E15992F, - &MXC_42161_B6862ED6, - &POLYSWARM_42161_FB920D5B, - &NKN_42161_0406177B, - &NUMERAIRE_42161_6B569711, - &OCEAN_PROTOCOL_42161_AD8234DF, - &ORIGIN_PROTOCOL_42161_58AE423E, - &OMG_NETWORK_42161_61421E8E, - &ONDO_FINANCE_42161_8B37A5E7, - &ORION_PROTOCOL_42161_551E6218, - &PENDLE_42161_B9A8C9E8, - &PEPE_42161_33959CBB, - &PERPETUAL_PROTOCOL_42161_F61D3DAC, - &PIRATE_NATION_42161_43D77CBF, - &PLUME_42161_CB15BA13, - &POLYGON_ECOSYSTEM_TOKEN_42161_68FE08CC, - &POLKASTARTER_42161_8B016B64, - &POLYMATH_42161_B33809E9, - &MARLIN_42161_C8BD9DDD, - &PORTAL_42161_9DB991DE, - &POWER_LEDGER_42161_D423E4A6, - &PRIME_42161_E7AC5067, - &PARSIQ_42161_CAF60CD2, - &PAYPAL_USD_42161_0967342E, - &QUANT_42161_3C7EFF85, - &RADICLE_42161_12155E49, - &RAI_REFLEX_INDEX_42161_78D419F2, - &RARIBLE_42161_63C1B8E0, - &RUBIC_42161_5CBC335F, - &REPUBLIC_TOKEN_42161_1C79A204, - &REQUEST_42161_8BB92171, - &RARI_GOVERNANCE_TOKEN_42161_CD794794, - &IEXEC_RLC_42161_5D794E66, - &RENDER_TOKEN_42161_6F21E279, - &ROCKET_POOL_PROTOCOL_42161_1D0CC507, - &RESERVE_RIGHTS_42161_DBD2E594, - &THE_SANDBOX_42161_D64E3DAC, - &STADER_42161_92F34B63, - &SHIBA_INU_42161_E3872FD1, - &SKALE_42161_37267878, - &STATUS_42161_A6415160, - &SYNTHETIX_NETWORK_TOKEN_42161_BCA37D60, - &UNISOCKS_42161_A3B264E7, - &SOL_WORMHOLE_42161_EC617124, - &SPELL_TOKEN_42161_FE15D2AF, - &SPX6900_42161_5D2BA901, - &SQD, - &STARGATE_FINANCE_42161_A16313EC, - &STORJ_TOKEN_42161_7AA2FCC2, - &SUPERFARM_42161_26498956, - &SYNTH_SUSD_42161_9D112F95, - &SUSHI_42161_0D85C61A, - &SWELL_42161_A58F2571, - &SYNAPSE_42161_375EAD84, - &THRESHOLD_NETWORK_42161_DEC21F55, - &TBTC_42161_0A572594, - &TELLOR_42161_10D88242, - &TRIBE_42161_03914A5A, - &TURBO_42161_EDE4576A, - &UMA_VOTING_TOKEN_V1_42161_9B0C3B22, - &UNISWAP_42161_72F1F7F0, - &WORLD_LIBERTY_FINANCIAL_USD_42161_DD217A33, - &USDCOIN_42161_268E5831, - &BRIDGED_USDC_42161_BDDB5CC8, - &PAX_DOLLAR_42161_B699DF8F, - &USDS_STABLECOIN_42161_749B876B, - &USUAL_42161_2140ABBB, - &WRAPPED_AMPLEFORTH_42161_8AE650BB, - &WRAPPED_BTC_42161_AEFC5B0F, - &WRAPPED_ETHER_42161_523FBAB1, - &WORLD_LIBERTY_FINANCIAL_42161_0E1980BF, - &WOO_NETWORK_42161_3AEFD07B, - &TETHER_GOLD_42161_CFC6C9D3, - &CHAIN_42161_4DEEAFED, - &XSGD_42161_4C1C4302, - &YEARN_FINANCE_42161_085B1582, - &ZETACHAIN_42161_47B88954, - &LAYERZERO_42161_F13271CD, - &TOKEN_0X_PROTOCOL_TOKEN_42161_19235AE2, - &WRAPPED_BITCOIN, - &CELO, - &USDCOIN_42220_8B32118C, - &TETHER_USD_42220_87483D5E, - &WRAPPED_ETHER_42220_622F4361, - &TOKEN_1INCH_43114_8B28F267, - &AAVE_43114_E5D386D9, - &AGEUR_43114_F1F96C57, - &ALPHA_VENTURE_DAO_43114_7A8E208F, - &ANKR_43114_2C84B4DE, - &AXELAR_43114_CE194C5D, - &BASIC_ATTENTION_TOKEN_43114_A4690588, - &BINANCE_USD_43114_39D2DB39, - &COMPOUND_43114_906E2437, - &CARTESI_43114_0FABF552, - &DAI_E_TOKEN, - &DEFI_YIELD_PROTOCOL_43114_91BCEF17, - &EURO_COIN_43114_505C2ACD, - &FLUX_43114_C20DAF55, - &FRAX_43114_21A1DA64, - &FRAX_SHARE_43114_3FC8E387, - &GMX_43114_5011C661, - &THE_GRAPH_43114_69E85CB9, - &GUNZ, - &CHAINLINK_TOKEN_43114_413227A3, - &MAGIC_INTERNET_MONEY_43114_8CB8C18D, - &MAKER_43114_AAB72D42, - &MULTICHAIN_43114_3C8764E3, - &PENDLE_43114_62EA213B, - &RAI_REFLEX_INDEX_43114_031BFF7D, - &SYNTHETIX_NETWORK_TOKEN_43114_BA4B209B, - &SOL_WORMHOLE_43114_06D2478F, - &SPELL_TOKEN_43114_1A2F7814, - &STARGATE_FINANCE_43114_F56E7590, - &SUSHI_43114_722E4F76, - &SYNAPSE_43114_E09CA251, - &UMA_VOTING_TOKEN_V1_43114_0A5B2339, - &UNI_E_TOKEN, - &USDC_TOKEN, - &TETHER_USD_43114_4DF4A8C7, - &WRAPPED_AVAX, - &WRAPPED_BTC_43114_5187B218, - &WRAPPED_ETHER_43114_6BC10BAB, - &WOO_NETWORK_43114_5F58D083, - &YEARN_FINANCE_43114_922F52DC, - &LAYERZERO_43114_F13271CD, - &TOKEN_0X_PROTOCOL_TOKEN_43114_75CDE0D2, - &WRAPPED_ETHER_80001_C5D1C0AA, - &WRAPPED_MATIC_80001_FB032889, - &BLAST, - &USD_COIN_BRIDGED_FROM_ETHEREUM, - &UNISWAP_11155111_4201F984, - &WRAPPED_ETHER_11155111_324D6B14, -]; - -pub fn get_token( - chain_id: alloy::primitives::ChainId, - address: alloy::primitives::Address, -) -> Option<&'static TokenInfo> { - match (chain_id, address) { - (1, addr) if addr == address!("0x111111111117dC0aa78b770fA6A738034120C302") => Some(&TOKEN_1INCH), - (1, addr) if addr == address!("0x3E5A19c91266aD8cE2477B91585d1856B84062dF") => Some(&ANCIENT8), - (1, addr) if addr == address!("0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9") => Some(&AAVE), - (1, addr) if addr == address!("0xB98d4C97425d9908E66E53A6fDf673ACcA0BE986") => Some(&ARCBLOCK), - (1, addr) if addr == address!("0xEd04915c23f00A313a544955524EB7DBD823143d") => Some(&ALCHEMY_PAY), - (1, addr) if addr == address!("0x44108f0223A3C3028F5Fe7AEC7f9bb2E66beF82F") => Some(&ACROSS_PROTOCOL_TOKEN), - (1, addr) if addr == address!("0xADE00C28244d5CE17D72E40330B1c318cD12B7c3") => Some(&AMBIRE_ADEX), - (1, addr) if addr == address!("0x91Af0fBB28ABA7E31403Cb457106Ce79397FD4E6") => Some(&AERGO), - (1, addr) if addr == address!("0xB528edBef013aff855ac3c50b381f253aF13b997") => Some(&AEVO), - (1, addr) if addr == address!("0x1a7e4e63778B4f12a199C062f3eFdD288afCBce8") => Some(&AGEUR), - (1, addr) if addr == address!("0x32353A6C91143bfd6C7d363B546e62a9A2489A20") => Some(&ADVENTURE_GOLD), - (1, addr) if addr == address!("0x626E8036dEB333b408Be468F951bdB42433cBF18") => Some(&AIOZ_NETWORK), - (1, addr) if addr == address!("0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF") => Some(&ALCHEMIX), - (1, addr) if addr == address!("0x27702a26126e0B3702af63Ee09aC4d1A084EF628") => Some(&ALEPH_IM), - (1, addr) if addr == address!("0x6B0b3a982b4634aC68dD83a4DBF02311cE324181") => Some(&ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE), - (1, addr) if addr == address!("0xAC51066d7bEC65Dc4589368da368b212745d63E8") => Some(&MY_NEIGHBOR_ALICE), - (1, addr) if addr == address!("0x8408D45b61f5823298F19a09B53b7339c0280489") => Some(&ALLORA), - (1, addr) if addr == address!("0xa1faa113cbE53436Df28FF0aEe54275c13B40975") => Some(&ALPHA_VENTURE_DAO), - (1, addr) if addr == address!("0x8457CA5040ad67fdebbCC8EdCE889A335Bc0fbFB") => Some(&ALTLAYER), - (1, addr) if addr == address!("0xfF20817765cB7f73d4bde2e66e067E58D11095C2") => Some(&), - (1, addr) if addr == address!("0x8290333ceF9e6D528dD5618Fb97a76f268f3EDD4") => Some(&ANKR), - (1, addr) if addr == address!("0xa117000000f279D81A1D3cc75430fAA017FA5A2e") => Some(&ARAGON), - (1, addr) if addr == address!("0x4d224452801ACEd8B2F0aebE155379bb5D594381") => Some(&APECOIN), - (1, addr) if addr == address!("0x0b38210ea11411557c13457D4dA7dC6ea731B88a") => Some(&API3), - (1, addr) if addr == address!("0x5A9610919f5e81183823A2be4Bd1BeB2B4da2a20") => Some(&APRIORI), - (1, addr) if addr == address!("0x594DaaD7D77592a2b97b725A7AD59D7E188b5bFa") => Some(&APU_APUSTAJA), - (1, addr) if addr == address!("0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1") => Some(&ARBITRUM), - (1, addr) if addr == address!("0x6E2a43be0B1d33b726f0CA3b8de60b3482b8b050") => Some(&ARKHAM), - (1, addr) if addr == address!("0xBA50933C268F567BDC86E1aC131BE072C6B0b71a") => Some(&ARPA_CHAIN), - (1, addr) if addr == address!("0x64D91f12Ece7362F91A6f8E7940Cd55F05060b92") => Some(&ASH), - (1, addr) if addr == address!("0x2565ae0385659badCada1031DB704442E1b69982") => Some(&ASSEMBLE_PROTOCOL), - (1, addr) if addr == address!("0x27054b13b1B798B345b591a4d22e6562d47eA75a") => Some(&AIRSWAP), - (1, addr) if addr == address!("0xA2120b9e674d3fC3875f415A7DF52e382F141225") => Some(&AUTOMATA), - (1, addr) if addr == address!("0xbe0Ed4138121EcFC5c0E56B40517da27E6c5226B") => Some(&AETHIR_TOKEN), - (1, addr) if addr == address!("0xA9B1Eb5908CfC3cdf91F9B8B3a74108598009096") => Some(&BOUNCE), - (1, addr) if addr == address!("0x4cCe605eD955295432958d8951D0B176C10720d5") => Some(&AUDD), - (1, addr) if addr == address!("0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998") => Some(&AUDIUS), - (1, addr) if addr == address!("0x845576c64f9754CF09d87e45B720E82F3EeF522C") => Some(&ARTVERSE_TOKEN), - (1, addr) if addr == address!("0x467719aD09025FcC6cF6F8311755809d45a5E5f3") => Some(&AXELAR), - (1, addr) if addr == address!("0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b") => Some(&AXIE_INFINITY), - (1, addr) if addr == address!("0xA27EC0006e59f245217Ff08CD52A7E8b169E62D2") => Some(&AZTEC), - (1, addr) if addr == address!("0x3472A5A71965499acd81997a54BBA8D852C6E53d") => Some(&BADGER_DAO), - (1, addr) if addr == address!("0xba100000625a3754423978a60c9317c58a424e3D") => Some(&BALANCER), - (1, addr) if addr == address!("0xBA11D00c5f74255f56a5E366F4F77f5A186d7f55") => Some(&BAND_PROTOCOL), - (1, addr) if addr == address!("0xf0DB65D17e30a966C2ae6A21f6BBA71cea6e9754") => Some(&LOMBARD), - (1, addr) if addr == address!("0x0D8775F648430679A709E98d2b0Cb6250d2887EF") => Some(&BASIC_ATTENTION_TOKEN), - (1, addr) if addr == address!("0x62D0A8458eD7719FDAF978fe5929C6D342B0bFcE") => Some(&BEAM), - (1, addr) if addr == address!("0xF17e65822b568B3903685a7c9F496CF7656Cc6C2") => Some(&BICONOMY), - (1, addr) if addr == address!("0x64Bc2cA1Be492bE7185FAA2c8835d9b824c8a194") => Some(&BIG_TIME), - (1, addr) if addr == address!("0xcb1592591996765Ec0eFc1f92599A19767ee5ffA") => Some(&BIO), - (1, addr) if addr == address!("0x1A4b46696b2bB4794Eb3D4c26f1c55F9170fa4C5") => Some(&BITDAO), - (1, addr) if addr == address!("0x72e4f9F808C49A2a61dE9C5896298920Dc4EEEa9") => Some(&HARRYPOTTEROBAMASONIC10INU), - (1, addr) if addr == address!("0x5283D291DBCF85356A21bA090E6db59121208b44") => Some(&BLUR), - (1, addr) if addr == address!("0x5732046A883704404F284Ce41FfADd5b007FD668") => Some(&BLUZELLE), - (1, addr) if addr == address!("0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C") => Some(&BANCOR_NETWORK_TOKEN), - (1, addr) if addr == address!("0x42bBFa2e77757C645eeaAd1655E0911a7553Efbc") => Some(&BOBA_NETWORK), - (1, addr) if addr == address!("0xC9746F73cC33a36c2cD55b8aEFD732586946Cedd") => Some(&BOB), - (1, addr) if addr == address!("0x0391D2021f89DC339F60Fff84546EA23E337750f") => Some(&BARNBRIDGE), - (1, addr) if addr == address!("0x086F405146Ce90135750Bbec9A063a8B20A8bfFb") => Some(&BREVIS), - (1, addr) if addr == address!("0x799ebfABE77a6E34311eeEe9825190B9ECe32824") => Some(&BRAINTRUST), - (1, addr) if addr == address!("0x4Fabb145d64652a948d72533023f6E7A623C7C53") => Some(&BINANCE_USD), - (1, addr) if addr == address!("0xAE12C5930881c53715B369ceC7606B70d8EB229f") => Some(&COIN98), - (1, addr) if addr == address!("0x152649eA73beAb28c5b49B26eb48f7EAD6d4c898") => Some(&PANCAKESWAP), - (1, addr) if addr == address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf") => Some(&COINBASE_WRAPPED_BTC), - (1, addr) if addr == address!("0xBe9895146f7AF43049ca1c1AE358B0541Ea49704") => Some(&COINBASE_WRAPPED_STAKED_ETH), - (1, addr) if addr == address!("0x3294395e62F4eB6aF3f1Fcf89f5602D90Fb3Ef69") => Some(&CELO_NATIVE_ASSET_WORMHOLE), - (1, addr) if addr == address!("0x4F9254C83EB525f9FCf346490bbb3ed28a81C667") => Some(&CELER_NETWORK), - (1, addr) if addr == address!("0xcccCCCcCCC33D538DBC2EE4fEab0a7A1FF4e8A94") => Some(&CENTRIFUGE), - (1, addr) if addr == address!("0x8A2279d4A90B6fe1C4B30fa660cC9f926797bAA2") => Some(&CHROMIA), - (1, addr) if addr == address!("0x3506424F91fD33084466F402d5D97f05F8e3b4AF") => Some(&CHILIZ), - (1, addr) if addr == address!("0x80C62FE4487E1351b47Ba49809EBD60ED085bf52") => Some(&CLOVER_FINANCE), - (1, addr) if addr == address!("0xc00e94Cb662C3520282E6f5717214004A7f26888") => Some(&COMPOUND), - (1, addr) if addr == address!("0x44f49ff0da2498bCb1D3Dc7C0f999578F67FD8C6") => Some(&CORN), - (1, addr) if addr == address!("0xDDB3422497E61e13543BeA06989C0789117555c5") => Some(&COTI), - (1, addr) if addr == address!("0x3D658390460295FB963f54dC0899cfb1c30776Df") => Some(&CIRCUITS_OF_VALUE), - (1, addr) if addr == address!("0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB") => Some(&COW_PROTOCOL), - (1, addr) if addr == address!("0x66761Fa41377003622aEE3c7675Fc7b5c1C2FaC5") => Some(&CLEARPOOL), - (1, addr) if addr == address!("0xD417144312DbF50465b1C641d016962017Ef6240") => Some(&COVALENT), - (1, addr) if addr == address!("0xA0b73E1Ff0B80914AB6fe0444E65848C4C34450b") => Some(&CRONOS), - (1, addr) if addr == address!("0x08389495D7456E1951ddF7c3a1314A4bfb646d8B") => Some(&CRYPTERIUM), - (1, addr) if addr == address!("0xD533a949740bb3306d119CC777fa900bA034cd52") => Some(&CURVE_DAO_TOKEN), - (1, addr) if addr == address!("0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D") => Some(&CARTESI), - (1, addr) if addr == address!("0x321C2fE4446C7c963dc41Dd58879AF648838f98D") => Some(&CRYPTEX_FINANCE), - (1, addr) if addr == address!("0xDf801468a808a32656D2eD2D2d80B72A129739f4") => Some(&SOMNIUM_SPACE_CUBES), - (1, addr) if addr == address!("0x41e5560054824eA6B0732E656E3Ad64E20e94E45") => Some(&CIVIC), - (1, addr) if addr == address!("0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B") => Some(&CONVEX_FINANCE), - (1, addr) if addr == address!("0x7ABc8A5768E6bE61A6c693a6e4EAcb5B60602C4D") => Some(&COVALENT_X_TOKEN), - (1, addr) if addr == address!("0x6B175474E89094C44Da98b954EedeAC495271d0F") => Some(&DAI_STABLECOIN), - (1, addr) if addr == address!("0x081131434f93063751813C619Ecca9C4dC7862a3") => Some(&MINES_OF_DALARNIA), - (1, addr) if addr == address!("0x3A880652F47bFaa771908C07Dd8673A787dAEd3A") => Some(&DERIVADAO), - (1, addr) if addr == address!("0x3597bfD533a99c9aa083587B074434E61Eb0A258") => Some(&DENT), - (1, addr) if addr == address!("0xfB7B4564402E5500dB5bB6d63Ae671302777C75a") => Some(&DEXTOOLS), - (1, addr) if addr == address!("0x84cA8bc7997272c7CfB4D0Cd3D55cd942B3c9419") => Some(&DIA), - (1, addr) if addr == address!("0x0AbdAce70D3790235af448C88547603b945604ea") => Some(&DISTRICT0X), - (1, addr) if addr == address!("0x0F81001eF0A83ecCE5ccebf63EB302c70a39a654") => Some(&DOLOMITE), - (1, addr) if addr == address!("0x2aeAbde1aB736c59E9A19BeD67681869eEF39526") => Some(&DOVU), - (1, addr) if addr == address!("0x1494CA1F11D487c2bBe4543E90080AeBa4BA3C2b") => Some(&DEFI_PULSE_INDEX), - (1, addr) if addr == address!("0x3Ab6Ed69Ef663bd986Ee59205CCaD8A20F98b4c2") => Some(&DREP), - (1, addr) if addr == address!("0xB1D1eae60EEA9525032a6DCb4c1CE336a1dE71BE") => Some(&DERIVE), - (1, addr) if addr == address!("0x92D6C1e31e14520e676a687F0a93788B716BEff5") => Some(&DYDX), - (1, addr) if addr == address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17") => Some(&DEFI_YIELD_PROTOCOL), - (1, addr) if addr == address!("0xec53bF9167f50cDEB3Ae105f56099aaaB9061F83") => Some(&EIGENLAYER), - (1, addr) if addr == address!("0xe6fd75ff38Adca4B97FBCD938c86b98772431867") => Some(&ELASTOS), - (1, addr) if addr == address!("0x761D38e5ddf6ccf6Cf7c55759d5210750B5D60F3") => Some(&DOGELON_MARS), - (1, addr) if addr == address!("0x57e114B691Db790C35207b2e685D4A43181e6061") => Some(ÐENA), - (1, addr) if addr == address!("0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c") => Some(&ENJIN_COIN), - (1, addr) if addr == address!("0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72") => Some(ÐEREUM_NAME_SERVICE), - (1, addr) if addr == address!("0xE2AD0BF751834f2fbdC62A41014f84d67cA1de2A") => Some(&CALDERA), - (1, addr) if addr == address!("0xBBc2AE13b23d715c30720F079fcd9B4a74093505") => Some(ÐERNITY_CHAIN), - (1, addr) if addr == address!("0x031De51F3E8016514Bd0963d0B2AB825A591Db9A") => Some(&ESPRESSO), - (1, addr) if addr == address!("0xFe0c30065B384F05761f15d0CC899D4F9F9Cc0eB") => Some(ÐER_FI), - (1, addr) if addr == address!("0xd9Fcd98c322942075A5C3860693e9f4f03AAE07b") => Some(&EULER), - (1, addr) if addr == address!("0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c") => Some(&EURO_COIN), - (1, addr) if addr == address!("0x888883b5F5D21fb10Dfeb70e8f9722B9FB0E5E51") => Some(&SCHUMAN_EUR_P), - (1, addr) if addr == address!("0x8dF723295214Ea6f21026eeEb4382d475f146F9f") => Some(&QUANTOZ_EURQ), - (1, addr) if addr == address!("0x50753CfAf86c094925Bf976f218D043f8791e408") => Some(&STABLR_EURO), - (1, addr) if addr == address!("0xa0246c9032bC3A600820415aE600c6388619A14D") => Some(&HARVEST_FINANCE), - (1, addr) if addr == address!("0xaea46A60368A7bD060eec7DF8CBa43b7EF41Ad85") => Some(&FETCH_AI), - (1, addr) if addr == address!("0x7C135549504245B5eAe64fc0E99Fa5ebabb8e35D") => Some(&FIDELITY_DIGITAL_DOLLAR), - (1, addr) if addr == address!("0xef3A930e1FfFFAcd2fc13434aC81bD278B0ecC8d") => Some(&STAFI), - (1, addr) if addr == address!("0xcf0C122c6b73ff809C693DB761e7BaeBe62b6a2E") => Some(&FLOKI), - (1, addr) if addr == address!("0x720CD16b011b987Da3518fbf38c3071d4F0D1495") => Some(&FLUX), - (1, addr) if addr == address!("0x41545f8b9472D758bB669ed8EaEEEcD7a9C4Ec29") => Some(&FORTA), - (1, addr) if addr == address!("0x77FbA179C79De5B7653F68b5039Af940AdA60ce0") => Some(&LEFORTH_GOVERNANCE_TOKEN), - (1, addr) if addr == address!("0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d") => Some(&SHAPESHIFT_FOX_TOKEN), - (1, addr) if addr == address!("0x853d955aCEf822Db058eb8505911ED77F175b99e") => Some(&FRAX), - (1, addr) if addr == address!("0x4E15361FD6b4BB609Fa63C81A2be19d873717870") => Some(&FANTOM), - (1, addr) if addr == address!("0x8c15Ef5b4B21951d50E53E4fbdA8298FFAD25057") => Some(&FUNCTION_X), - (1, addr) if addr == address!("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0") => Some(&FRAX_SHARE), - (1, addr) if addr == address!("0x9C7BEBa8F6eF6643aBd725e45a4E8387eF260649") => Some(&GRAVITY), - (1, addr) if addr == address!("0x5fAa989Af96Af85384b8a938c2EdE4A7378D9875") => Some(&GALXE), - (1, addr) if addr == address!("0xd1d2Eb1B1e90B638588728b4130137D262C87cae") => Some(&GALA), - (1, addr) if addr == address!("0xdab396cCF3d84Cf2D07C4454e10C8A6F5b008D2b") => Some(&GOLDFINCH), - (1, addr) if addr == address!("0x3F382DbD960E3a9bbCeaE22651E88158d2791550") => Some(&AAVEGOTCHI), - (1, addr) if addr == address!("0x7DD9c5Cba05E151C895FDe1CF355C9A1D5DA6429") => Some(&GOLEM), - (1, addr) if addr == address!("0x6810e776880C02933D47DB1b9fc05908e5386b96") => Some(&GNOSIS_TOKEN), - (1, addr) if addr == address!("0xccC8cb5229B0ac8069C51fd58367Fd1e622aFD97") => Some(&GODS_UNCHAINED), - (1, addr) if addr == address!("0xc944E90C64B2c07662A292be6244BDf05Cda44a7") => Some(&THE_GRAPH), - (1, addr) if addr == address!("0xDe30da39c46104798bB5aA3fe8B9e0e1F348163F") => Some(&GITCOIN), - (1, addr) if addr == address!("0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd") => Some(&GEMINI_DOLLAR), - (1, addr) if addr == address!("0x2798b1cC5A993085E8A9D46e80499F1B63f42204") => Some(ÐGAS), - (1, addr) if addr == address!("0xC08512927D12348F6620a698105e1BAac6EcD911") => Some(&GYEN), - (1, addr) if addr == address!("0xb3999F658C0391d94A37f7FF328F3feC942BcADC") => Some(&HASHFLOW), - (1, addr) if addr == address!("0x71Ab77b7dbB4fa7e017BC15090b2163221420282") => Some(&HIGHSTREET), - (1, addr) if addr == address!("0xF5581dFeFD8Fb0e4aeC526bE659CFaB1f8c781dA") => Some(&HOPR), - (1, addr) if addr == address!("0xB705268213D593B8FD88d3FDEFF93AFF5CbDcfAE") => Some(&IDEX), - (1, addr) if addr == address!("0x767FE9EDC9E0dF98E07454847909b5E959D7ca0E") => Some(&ILLUVIUM), - (1, addr) if addr == address!("0xb48c6B24f36307c7A1f2a9281E978a9ef2902BA5") => Some(&IMMUNEFI), - (1, addr) if addr == address!("0xF57e7e7C23978C3cAEC3C3548E3D615c346e79fF") => Some(&IMMUTABLE_X), - (1, addr) if addr == address!("0x0954906da0Bf32d5479e25f46056d22f08464cab") => Some(&INDEX_COOPERATIVE), - (1, addr) if addr == address!("0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30") => Some(&INJECTIVE), - (1, addr) if addr == address!("0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68") => Some(&INVERSE_FINANCE), - (1, addr) if addr == address!("0xdeF1b2D939EdC0E4d35806c59b3166F790175afe") => Some(&INFINEX), - (1, addr) if addr == address!("0x6fB3e0A217407EFFf7Ca062D46c26E5d60a14d69") => Some(&IOTEX), - (1, addr) if addr == address!("0x50f41F589aFACa2EF41FDF590FE7b90cD26DEe64") => Some(&IRYS), - (1, addr) if addr == address!("0x23894DC9da6c94ECb439911cAF7d337746575A72") => Some(&GEOJAM), - (1, addr) if addr == address!("0x7420B4b9a0110cdC71fB720908340C03F9Bc03EC") => Some(&JASMYCOIN), - (1, addr) if addr == address!("0x4B1E80cAC91e2216EEb63e29B957eB91Ae9C2Be8") => Some(&JUPITER), - (1, addr) if addr == address!("0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC") => Some(&KEEP_NETWORK), - (1, addr) if addr == address!("0x3f80B1c54Ae920Be41a77f8B902259D48cf24cCf") => Some(&KERNELDAO), - (1, addr) if addr == address!("0x4CC19356f2D37338b9802aa8E8fc58B0373296E7") => Some(&SELFKEY), - (1, addr) if addr == address!("0x904567252D8F48555b7447c67dCA23F0372E16be") => Some(&KITE), - (1, addr) if addr == address!("0xdd974D5C2e2928deA5F71b9825b8b646686BD200") => Some(&KYBER_NETWORK_CRYSTAL), - (1, addr) if addr == address!("0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44") => Some(&KEEP3RV1), - (1, addr) if addr == address!("0x464eBE77c293E473B48cFe96dDCf88fcF7bFDAC0") => Some(&KRYLL), - (1, addr) if addr == address!("0x96543ef8d2C75C26387c1a319ae69c0BEE6f3fe7") => Some(&KUJIRA), - (1, addr) if addr == address!("0x88909D489678dD17aA6D9609F89B0419Bf78FD9a") => Some(&LAYER3), - (1, addr) if addr == address!("0x0fc2a55d5BD13033f1ee0cdd11f60F7eFe66f467") => Some(&LAGRANGE), - (1, addr) if addr == address!("0x037A54AaB062628C9Bbae1FDB1583c195585fe41") => Some(&LCX), - (1, addr) if addr == address!("0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32") => Some(&LIDO_DAO), - (1, addr) if addr == address!("0x1789e0043623282D5DCc7F213d703C6D8BAfBB04") => Some(&LINEA), - (1, addr) if addr == address!("0x514910771AF9Ca656af840dff83E8264EcF986CA") => Some(&CHAINLINK_TOKEN), - (1, addr) if addr == address!("0xb59490aB09A0f526Cc7305822aC65f2Ab12f9723") => Some(&LITENTRY), - (1, addr) if addr == address!("0x232CE3bd40fCd6f80f3d55A522d03f25Df784Ee2") => Some(&LIGHTER), - (1, addr) if addr == address!("0x61E90A50137E1F645c9eF4a0d3A4f01477738406") => Some(&LEAGUE_OF_KINGDOMS), - (1, addr) if addr == address!("0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0") => Some(&LOOM_NETWORK), - (1, addr) if addr == address!("0x58b6A8A3302369DAEc383334672404Ee733aB239") => Some(&LIVEPEER), - (1, addr) if addr == address!("0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D") => Some(&LIQUITY), - (1, addr) if addr == address!("0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD") => Some(&LOOPRINGCOIN_V2), - (1, addr) if addr == address!("0xd0a6053f087E87a25dC60701ba6E663b1a548E85") => Some(&BLOCKLORDS), - (1, addr) if addr == address!("0x8c1BEd5b9a0928467c9B1341Da1D7BD5e10b6549") => Some(&LIQUID_STAKED_ETH), - (1, addr) if addr == address!("0x6033F7f88332B8db6ad452B7C6D5bB643990aE3f") => Some(&LISK), - (1, addr) if addr == address!("0x5f98805A4E8be255a32880FDeC7F6728C6568bA0") => Some(&LIQUITY_USD), - (1, addr) if addr == address!("0x0F5D2fB29fb7d3CFeE444a200298f468908cC942") => Some(&DECENTRALAND), - (1, addr) if addr == address!("0x69af81e73A73B40adF4f3d4223Cd9b1ECE623074") => Some(&MASK_NETWORK), - (1, addr) if addr == address!("0x08d967bb0134F2d07f7cfb6E246680c53927DD30") => Some(&MATH), - (1, addr) if addr == address!("0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0") => Some(&POLYGON), - (1, addr) if addr == address!("0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6") => Some(&MERIT_CIRCLE), - (1, addr) if addr == address!("0xfC98e825A2264D890F9a1e68ed50E1526abCcacD") => Some(&MOSS_CARBON_CREDIT), - (1, addr) if addr == address!("0x814e0908b12A99FeCf5BC101bB5d0b8B5cDf7d26") => Some(&MEASURABLE_DATA_TOKEN), - (1, addr) if addr == address!("0xb131f4A55907B10d1F0A50d8ab8FA09EC342cd74") => Some(&MEMECOIN), - (1, addr) if addr == address!("0x9E32b13ce7f2E80A01932B42553652E053D6ed8e") => Some(&METIS), - (1, addr) if addr == address!("0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3") => Some(&MAGIC_INTERNET_MONEY), - (1, addr) if addr == address!("0x09a3EcAFa817268f77BE1283176B946C4ff2E608") => Some(&MIRROR_PROTOCOL), - (1, addr) if addr == address!("0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2") => Some(&MAKER), - (1, addr) if addr == address!("0xec67005c4E498Ec7f55E092bd1d35cbC47C91892") => Some(&MELON), - (1, addr) if addr == address!("0x3c3a81e81dc49A522A592e7622A7E711c06bf354") => Some(&MANTLE), - (1, addr) if addr == address!("0xaaeE1A9723aaDB7afA2810263653A34bA2C21C7a") => Some(&MOG_COIN), - (1, addr) if addr == address!("0x275f5Ad03be0Fa221B4C6649B8AeE09a42D9412A") => Some(&MONAVALE), - (1, addr) if addr == address!("0x58D97B57BB95320F9a05dC918Aef65434969c2B2") => Some(&MORPHO_TOKEN), - (1, addr) if addr == address!("0x3073f7aAA4DB83f95e9FFf17424F71D4751a3073") => Some(&MOVEMENT), - (1, addr) if addr == address!("0x33349B282065b0284d756F0577FB39c158F935e6") => Some(&MAPLE), - (1, addr) if addr == address!("0xF433089366899D83a9f26A773D59ec7eCF30355e") => Some(&METAL), - (1, addr) if addr == address!("0x65Ef703f5594D2573eb71Aaf55BC0CB548492df4") => Some(&MULTICHAIN), - (1, addr) if addr == address!("0xe2f2a5C287993345a840Db3B0845fbC70f5935a5") => Some(&MSTABLE_USD), - (1, addr) if addr == address!("0xB6Ca7399B4F9CA56FC27cBfF44F4d2e4Eef1fc81") => Some(&MUSE_DAO), - (1, addr) if addr == address!("0xAE788F80F2756A86aa2F410C651F2aF83639B95b") => Some(&GENSOKISHI_METAVERSE), - (1, addr) if addr == address!("0x5Ca381bBfb58f0092df149bD3D243b08B9a8386e") => Some(&MXC), - (1, addr) if addr == address!("0x9E46A38F5DaaBe8683E10793b06749EEF7D733d1") => Some(&POLYSWARM), - (1, addr) if addr == address!("0x812Ba41e071C7b7fA4EBcFB62dF5F45f6fA853Ee") => Some(&NEIRO), - (1, addr) if addr == address!("0xD0eC028a3D21533Fdd200838F39c85B03679285D") => Some(&NEWTON), - (1, addr) if addr == address!("0x5Cf04716BA20127F1E2297AdDCf4B5035000c9eb") => Some(&NKN), - (1, addr) if addr == address!("0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671") => Some(&NUMERAIRE), - (1, addr) if addr == address!("0x6e6F6d696e61decd6605bD4a57836c5DB6923340") => Some(&NOMINA), - (1, addr) if addr == address!("0x4fE83213D56308330EC302a8BD641f1d0113A4Cc") => Some(&NUCYPHER), - (1, addr) if addr == address!("0x967da4048cD07aB37855c090aAF366e4ce1b9F48") => Some(&OCEAN_PROTOCOL), - (1, addr) if addr == address!("0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26") => Some(&ORIGIN_PROTOCOL), - (1, addr) if addr == address!("0xd26114cd6EE289AccF82350c8d8487fedB8A0C07") => Some(&OMG_NETWORK), - (1, addr) if addr == address!("0x36E66fbBce51e4cD5bd3C62B637Eb411b18949D4") => Some(&OMNI_NETWORK), - (1, addr) if addr == address!("0xfAbA6f8e4a5E8Ab82F62fe7C39859FA577269BE3") => Some(&ONDO_FINANCE), - (1, addr) if addr == address!("0x6F59e0461Ae5E2799F1fB3847f05a63B16d0DbF8") => Some(&ORCA_ALLIANCE), - (1, addr) if addr == address!("0x0258F474786DdFd37ABCE6df6BBb1Dd5dfC4434a") => Some(&ORION_PROTOCOL), - (1, addr) if addr == address!("0x4575f41308EC1483f3d399aa9a2826d74Da13Deb") => Some(&ORCHID), - (1, addr) if addr == address!("0xc1D204d77861dEf49b6E769347a883B15EC397Ff") => Some(&PAYPEREX), - (1, addr) if addr == address!("0x45804880De22913dAFE09f4980848ECE6EcbAf78") => Some(&PAX_GOLD), - (1, addr) if addr == address!("0x0D3CbED3f69EE050668ADF3D9Ea57241cBa33A2B") => Some(&PLAYDAPP), - (1, addr) if addr == address!("0x808507121B80c02388fAd14726482e061B8da827") => Some(&PENDLE), - (1, addr) if addr == address!("0x6982508145454Ce325dDbE47a25d4ec3d2311933") => Some(&PEPE), - (1, addr) if addr == address!("0xbC396689893D065F41bc2C6EcbeE5e0085233447") => Some(&PERPETUAL_PROTOCOL), - (1, addr) if addr == address!("0x7613C48E0cd50E42dD9Bf0f6c235063145f6f8DC") => Some(&PIRATE_NATION), - (1, addr) if addr == address!("0xD8912C10681D8B21Fd3742244f44658dBA12264E") => Some(&PLUTON), - (1, addr) if addr == address!("0x4C1746A800D224393fE2470C70A35717eD4eA5F1") => Some(&PLUME), - (1, addr) if addr == address!("0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6") => Some(&POLYGON_ECOSYSTEM_TOKEN), - (1, addr) if addr == address!("0x83e6f1E41cdd28eAcEB20Cb649155049Fac3D5Aa") => Some(&POLKASTARTER), - (1, addr) if addr == address!("0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC") => Some(&POLYMATH), - (1, addr) if addr == address!("0x57B946008913B82E4dF85f501cbAeD910e58D26C") => Some(&MARLIN), - (1, addr) if addr == address!("0x1Bbe973BeF3a977Fc51CbED703E8ffDEfE001Fed") => Some(&PORTAL), - (1, addr) if addr == address!("0x595832F8FC6BF59c85C527fEC3740A1b7a361269") => Some(&POWER_LEDGER), - (1, addr) if addr == address!("0xb23d80f5FefcDDaa212212F028021B41DEd428CF") => Some(&PRIME), - (1, addr) if addr == address!("0x226bb599a12C826476e3A771454697EA52E9E220") => Some(&PROPY), - (1, addr) if addr == address!("0x6BEF15D938d4E72056AC92Ea4bDD0D76B1C4ad29") => Some(&SUCCINCT), - (1, addr) if addr == address!("0x362bc847A3a9637d3af6624EeC853618a43ed7D2") => Some(&PARSIQ), - (1, addr) if addr == address!("0xfB5c6815cA3AC72Ce9F5006869AE67f18bF77006") => Some(&PSTAKE_FINANCE), - (1, addr) if addr == address!("0x4d1C297d39C5c1277964D0E3f8Aa901493664530") => Some(&PUFFER_FINANCE), - (1, addr) if addr == address!("0x6c3ea9036406852006290770BEdFcAbA0e23A0e8") => Some(&PAYPAL_USD), - (1, addr) if addr == address!("0x4a220E6096B25EADb88358cb44068A3248254675") => Some(&QUANT), - (1, addr) if addr == address!("0x4123a133ae3c521FD134D7b13A2dEC35b56c2463") => Some(&QREDO), - (1, addr) if addr == address!("0x99ea4dB9EE77ACD40B119BD1dC4E33e1C070b80d") => Some(&QUANTSTAMP), - (1, addr) if addr == address!("0x6c28AeF8977c9B773996d0e8376d2EE379446F2f") => Some(&QUICKSWAP), - (1, addr) if addr == address!("0x31c8EAcBFFdD875c74b94b077895Bd78CF1E64A3") => Some(&RADICLE), - (1, addr) if addr == address!("0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919") => Some(&RAI_REFLEX_INDEX), - (1, addr) if addr == address!("0xba5BDe662c17e2aDFF1075610382B9B691296350") => Some(&SUPERRARE), - (1, addr) if addr == address!("0xFca59Cd816aB1eaD66534D82bc21E7515cE441CF") => Some(&RARIBLE), - (1, addr) if addr == address!("0xA4EED63db85311E22dF4473f87CcfC3DaDCFA3E3") => Some(&RUBIC), - (1, addr) if addr == address!("0x6123B0049F904d730dB3C36a31167D9d4121fA6B") => Some(&RIBBON_FINANCE), - (1, addr) if addr == address!("0xc43C6bfeDA065fE2c4c11765Bf838789bd0BB5dE") => Some(&REDSTONE), - (1, addr) if addr == address!("0x408e41876cCCDC0F92210600ef50372656052a38") => Some(&REPUBLIC_TOKEN), - (1, addr) if addr == address!("0x1985365e9f78359a9B6AD760e32412f4a445E862") => Some(&REPUTATION_AUGUR_V1), - (1, addr) if addr == address!("0x221657776846890989a759BA2973e427DfF5C9bB") => Some(&REPUTATION_AUGUR_V2), - (1, addr) if addr == address!("0x8f8221aFbB33998d8584A2B05749bA73c37a938a") => Some(&REQUEST), - (1, addr) if addr == address!("0x557B933a7C2c45672B610F8954A3deB39a51A8Ca") => Some(&REVV), - (1, addr) if addr == address!("0x3B50805453023a91a8bf641e279401a0b23FA6F9") => Some(&RENZO), - (1, addr) if addr == address!("0xD291E7a03283640FDc51b121aC401383A46cC623") => Some(&RARI_GOVERNANCE_TOKEN), - (1, addr) if addr == address!("0x607F4C5BB672230e8672085532f7e901544a7375") => Some(&IEXEC_RLC), - (1, addr) if addr == address!("0xB5F7b021a78f470d31D762C1DDA05ea549904fbd") => Some(&RAYLS), - (1, addr) if addr == address!("0x8292Bb45bf1Ee4d140127049757C2E0fF06317eD") => Some(&RLUSD), - (1, addr) if addr == address!("0xf1f955016EcbCd7321c7266BccFB96c68ea5E49b") => Some(&RALLY), - (1, addr) if addr == address!("0x6De037ef9aD2725EB40118Bb1702EBb27e4Aeb24") => Some(&RENDER_TOKEN), - (1, addr) if addr == address!("0x32b4d049fE4c888D2b92eEcaf729F44DF6B1F36E") => Some(&ROBO_TOKEN), - (1, addr) if addr == address!("0xfA5047c9c78B8877af97BDcb85Db743fD7313d4a") => Some(&ROOK), - (1, addr) if addr == address!("0xD33526068D116cE69F19A9ee46F0bd304F21A51f") => Some(&ROCKET_POOL_PROTOCOL), - (1, addr) if addr == address!("0x320623b8E4fF03373931769A31Fc52A4E78B5d70") => Some(&RESERVE_RIGHTS), - (1, addr) if addr == address!("0x5aFE3855358E112B5647B952709E6165e1c1eEEe") => Some(&SAFE), - (1, addr) if addr == address!("0x3845badAde8e6dFF049820680d1F14bD3903a5d0") => Some(&THE_SANDBOX), - (1, addr) if addr == address!("0x30D20208d987713f46DFD34EF128Bb16C404D10f") => Some(&STADER), - (1, addr) if addr == address!("0x56A3BA04E95d34268A19b2a4474DC979baBDaf76") => Some(&SENTIENT), - (1, addr) if addr == address!("0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE") => Some(&SHIBA_INU), - (1, addr) if addr == address!("0x7C84e62859D0715eb77d1b1C4154Ecd6aBB21BEC") => Some(&SHPING), - (1, addr) if addr == address!("0x00c83aeCC790e8a4453e5dD3B0B4b3680501a7A7") => Some(&SKALE), - (1, addr) if addr == address!("0x56072C95FAA701256059aa122697B133aDEd9279") => Some(&SKY_GOVERNANCE_TOKEN), - (1, addr) if addr == address!("0xCC8Fa225D80b9c7D42F96e9570156c65D6cAAa25") => Some(&SMOOTH_LOVE_POTION), - (1, addr) if addr == address!("0x744d70FDBE2Ba4CF95131626614a1763DF805B9E") => Some(&STATUS), - (1, addr) if addr == address!("0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F") => Some(&SYNTHETIX_NETWORK_TOKEN), - (1, addr) if addr == address!("0x23B608675a2B2fB1890d3ABBd85c5775c51691d5") => Some(&UNISOCKS), - (1, addr) if addr == address!("0xD31a59c85aE9D8edEFeC411D448f90841571b89c") => Some(&SOL_WORMHOLE), - (1, addr) if addr == address!("0x090185f2135308BaD17527004364eBcC2D37e5F6") => Some(&SPELL_TOKEN), - (1, addr) if addr == address!("0xc20059e0317DE91738d13af027DfC4a50781b066") => Some(&SPARK), - (1, addr) if addr == address!("0xE0f63A424a4439cBE457D80E4f4b51aD25b2c56C") => Some(&SPX6900), - (1, addr) if addr == address!("0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6") => Some(&STARGATE_FINANCE), - (1, addr) if addr == address!("0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC") => Some(&STORJ_TOKEN), - (1, addr) if addr == address!("0xCa14007Eff0dB1f8135f4C25B34De49AB0d42766") => Some(&STARKNET), - (1, addr) if addr == address!("0x006BeA43Baa3f7A6f765F14f10A1a1b08334EF45") => Some(&STOX), - (1, addr) if addr == address!("0x0763fdCCF1aE541A5961815C0872A8c5Bc6DE4d7") => Some(&SUKU), - (1, addr) if addr == address!("0xe53EC727dbDEB9E2d5456c3be40cFF031AB40A55") => Some(&SUPERFARM), - (1, addr) if addr == address!("0x57Ab1ec28D129707052df4dF418D58a2D46d5f51") => Some(&SYNTH_SUSD), - (1, addr) if addr == address!("0x6B3595068778DD592e39A122f4f5a5cF09C90fE2") => Some(&SUSHI), - (1, addr) if addr == address!("0x0a6E7Ba5042B38349e437ec6Db6214AEC7B35676") => Some(&SWELL), - (1, addr) if addr == address!("0x0bb217E40F8a5Cb79Adf04E1aAb60E5abd0dfC1e") => Some(&SWFTCOIN), - (1, addr) if addr == address!("0x8CE9137d39326AD0cD6491fb5CC0CbA0e089b6A9") => Some(&SWIPE), - (1, addr) if addr == address!("0xE6Bfd33F52d82Ccb5b37E16D3dD81f9FFDAbB195") => Some(&SPACE_AND_TIME), - (1, addr) if addr == address!("0xf293d23BF2CDc05411Ca0edDD588eb1977e8dcd4") => Some(&SYLO), - (1, addr) if addr == address!("0x0f2D719407FdBeFF09D87557AbB7232601FD9F29") => Some(&SYNAPSE), - (1, addr) if addr == address!("0x643C4E15d7d62Ad0aBeC4a9BD4b001aA3Ef52d66") => Some(&SYRUP_TOKEN), - (1, addr) if addr == address!("0xCdF7028ceAB81fA0C6971208e83fa7872994beE5") => Some(&THRESHOLD_NETWORK), - (1, addr) if addr == address!("0x18084fbA666a33d37592fA2633fD49a74DD93a88") => Some(&TBTC), - (1, addr) if addr == address!("0xC3d21f79C3120A4fFda7A535f8005a7c297799bF") => Some(&TERM_FINANCE), - (1, addr) if addr == address!("0xafFbe9a60F1F45E057FD9b6DC70004Bb0Ccc8b99") => Some(&THEORIQ), - (1, addr) if addr == address!("0x485d17A6f1B8780392d53D64751824253011A260") => Some(&CHRONOTECH), - (1, addr) if addr == address!("0x888888848B652B3E3a0f34c96E00EEC0F3a23F72") => Some(&ALIEN_WORLDS), - (1, addr) if addr == address!("0x2e9d63788249371f1DFC918a52f8d799F4a38C94") => Some(&TOKEMAK), - (1, addr) if addr == address!("0x4507cEf57C46789eF8d1a19EA45f4216bae2B528") => Some(&TOKENFI), - (1, addr) if addr == address!("0x2Ab6Bb8408ca3199B8Fa6C92d5b455F820Af03c4") => Some(&TE_FOOD), - (1, addr) if addr == address!("0xaA7a9CA87d3694B5755f213B5D04094b8d0F0A6F") => Some(&ORIGINTRAIL), - (1, addr) if addr == address!("0x88dF592F8eb5D7Bd38bFeF7dEb0fBc02cf3778a0") => Some(&TELLOR), - (1, addr) if addr == address!("0x77146784315Ba81904d654466968e3a7c196d1f3") => Some(&TREEHOUSE_TOKEN), - (1, addr) if addr == address!("0x228bEC415adE4b61D7CaF0adf8C91EAc587BA369") => Some(&TRIA), - (1, addr) if addr == address!("0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B") => Some(&TRIBE), - (1, addr) if addr == address!("0x4C19596f5aAfF459fA38B0f7eD92F11AE6543784") => Some(&TRUEFI), - (1, addr) if addr == address!("0xA35923162C49cF95e6BF26623385eb431ad920D3") => Some(&TURBO), - (1, addr) if addr == address!("0xd084B83C305daFD76AE3E1b4E1F1fe2eCcCb3988") => Some(&THE_VIRTUA_KOLECT), - (1, addr) if addr == address!("0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828") => Some(&UMA_VOTING_TOKEN_V1), - (1, addr) if addr == address!("0x441761326490cACF7aF299725B6292597EE822c2") => Some(&UNIFI_PROTOCOL_DAO), - (1, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP), - (1, addr) if addr == address!("0x70D2b7C19352bB76e4409858FF5746e500f2B67c") => Some(&PAWTOCOL), - (1, addr) if addr == address!("0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d") => Some(&WORLD_LIBERTY_FINANCIAL_USD), - (1, addr) if addr == address!("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") => Some(&USDCOIN), - (1, addr) if addr == address!("0xe343167631d89B6Ffc58B88d6b7fB0228795491D") => Some(&GLOBAL_DOLLAR), - (1, addr) if addr == address!("0x8E870D67F660D95d5be530380D0eC0bd388289E1") => Some(&PAX_DOLLAR), - (1, addr) if addr == address!("0xc83e27f270cce0A3A3A29521173a83F402c1768b") => Some(&QUANTOZ_USDQ), - (1, addr) if addr == address!("0x7B43E3875440B44613DC3bC08E7763e6Da63C8f8") => Some(&STABLR_USD), - (1, addr) if addr == address!("0xdC035D45d973E3EC169d2276DDab16f1e407384F") => Some(&USDS_STABLECOIN), - (1, addr) if addr == address!("0xdAC17F958D2ee523a2206206994597C13D831ec7") => Some(&TETHER_USD), - (1, addr) if addr == address!("0xC4441c2BE5d8fA8126822B9929CA0b81Ea0DE38E") => Some(&USUAL), - (1, addr) if addr == address!("0x8DE5B80a0C1B02Fe4976851D030B36122dbb8624") => Some(&VANRY), - (1, addr) if addr == address!("0x3C4B6E6e1eA3D4863700D7F76b36B7f3D3f13E3d") => Some(&VOYAGER_TOKEN), - (1, addr) if addr == address!("0xEDB171C18cE90B633DB442f2A6F72874093b49Ef") => Some(&WRAPPED_AMPLEFORTH), - (1, addr) if addr == address!("0xf983da3ca66964C02628189Ea8Ca99fa9E24f66c") => Some(&WRAPPED_ANALOG_ONE_TOKEN), - (1, addr) if addr == address!("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599") => Some(&WRAPPED_BTC), - (1, addr) if addr == address!("0xc221b7E65FfC80DE234bbB6667aBDd46593D34F0") => Some(&WRAPPED_CENTRIFUGE), - (1, addr) if addr == address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945") => Some(&WALLETCONNECT_TOKEN), - (1, addr) if addr == address!("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") => Some(&WRAPPED_ETHER), - (1, addr) if addr == address!("0xdA5e1988097297dCdc1f90D4dFE7909e847CBeF6") => Some(&WORLD_LIBERTY_FINANCIAL), - (1, addr) if addr == address!("0x4691937a7508860F876c9c0a2a617E7d9E945D4B") => Some(&WOO_NETWORK), - (1, addr) if addr == address!("0xCEDbEA37C8872c4171259Cdfd5255CB8923Cf8e7") => Some(&ANOMA), - (1, addr) if addr == address!("0x68749665FF8D2d112Fa859AA293F07A622782F38") => Some(&TETHER_GOLD), - (1, addr) if addr == address!("0xA2cd3D43c775978A96BdBf12d733D5A1ED94fb18") => Some(&CHAIN), - (1, addr) if addr == address!("0x70e8dE73cE538DA2bEEd35d14187F6959a8ecA96") => Some(&XSGD), - (1, addr) if addr == address!("0x55296f69f40Ea6d20E478533C15A6B08B654E758") => Some(&XYO_NETWORK), - (1, addr) if addr == address!("0x01791F726B4103694969820be083196cC7c045fF") => Some(&YIELD_BASIS), - (1, addr) if addr == address!("0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e") => Some(&YEARN_FINANCE), - (1, addr) if addr == address!("0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83") => Some(&DFI_MONEY), - (1, addr) if addr == address!("0x25f8087EAD173b73D6e8B84329989A8eEA16CF73") => Some(&YIELD_GUILD_GAMES), - (1, addr) if addr == address!("0xA12CC123ba206d4031D1c7f6223D1C2Ec249f4f3") => Some(&ZAMA), - (1, addr) if addr == address!("0xf091867EC603A6628eD83D274E835539D82e9cc8") => Some(&ZETACHAIN), - (1, addr) if addr == address!("0x000006c2A22ff4A44ff1f5d0F2ed65F781F55555") => Some(&BOUNDLESS), - (1, addr) if addr == address!("0xe1Be424F442D0687129128C6c38aAce44F8c8Dbc") => Some(&ZKPASS), - (1, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO), - (1, addr) if addr == address!("0xE41d2489571d322189246DaFA5ebDe1F4699F498") => Some(&TOKEN_0X_PROTOCOL_TOKEN), - (3, addr) if addr == address!("0xaD6D458402F60fD3Bd25163575031ACDce07538D") => Some(&DAI_STABLECOIN_3_CE07538D), - (3, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP_3_4201F984), - (3, addr) if addr == address!("0xc778417E063141139Fce010982780140Aa0cD5Ab") => Some(&WRAPPED_ETHER_3_AA0CD5AB), - (4, addr) if addr == address!("0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735") => Some(&DAI_STABLECOIN_4_A8FC4735), - (4, addr) if addr == address!("0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85") => Some(&MAKER_4_359AAD85), - (4, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP_4_4201F984), - (4, addr) if addr == address!("0xc778417E063141139Fce010982780140Aa0cD5Ab") => Some(&WRAPPED_ETHER_4_AA0CD5AB), - (5, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP_5_4201F984), - (5, addr) if addr == address!("0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6") => Some(&WRAPPED_ETHER_5_2B2208D6), - (10, addr) if addr == address!("0xAd42D013ac31486B73b6b059e748172994736426") => Some(&TOKEN_1INCH_10_94736426), - (10, addr) if addr == address!("0x76FB31fb4af56892A25e32cFC43De717950c9278") => Some(&AAVE_10_950C9278), - (10, addr) if addr == address!("0xFf733b2A3557a7ed6697007ab5D11B79FdD1b76B") => Some(&ACROSS_PROTOCOL_TOKEN_10_FDD1B76B), - (10, addr) if addr == address!("0x334cc734866E97D8452Ae6261d68Fd9bc9BFa31E") => Some(&ARPA_CHAIN_10_C9BFA31E), - (10, addr) if addr == address!("0xFE8B128bA8C78aabC59d4c64cEE7fF28e9379921") => Some(&BALANCER_10_E9379921), - (10, addr) if addr == address!("0xd6909e9e702024eb93312B989ee46794c0fB1C9D") => Some(&BICONOMY_10_C0FB1C9D), - (10, addr) if addr == address!("0x07ad578FF86B135bE19A12759064b802Cb88854D") => Some(&BOBA_NETWORK_10_CB88854D), - (10, addr) if addr == address!("0x3e7eF8f50246f725885102E8238CBba33F276747") => Some(&BARNBRIDGE_10_3F276747), - (10, addr) if addr == address!("0xEd50aCE88bd42B45cB0F49be15395021E141254e") => Some(&BRAINTRUST_10_E141254E), - (10, addr) if addr == address!("0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39") => Some(&BINANCE_USD_10_39D2DB39), - (10, addr) if addr == address!("0xadDb6A0412DE1BA0F936DCaeb8Aaa24578dcF3B2") => Some(&COINBASE_WRAPPED_STAKED_ETH_10_78DCF3B2), - (10, addr) if addr == address!("0x9b88D293b7a791E40d36A39765FFd5A1B9b5c349") => Some(&CELO_NATIVE_ASSET_WORMHOLE_10_B9B5C349), - (10, addr) if addr == address!("0x0994206dfE8De6Ec6920FF4D779B0d950605Fb53") => Some(&CURVE_DAO_TOKEN_10_0605FB53), - (10, addr) if addr == address!("0xEc6adef5E1006bb305bB1975333e8fc4071295bf") => Some(&CARTESI_10_071295BF), - (10, addr) if addr == address!("0x14778860E937f509e651192a90589dE711Fb88a9") => Some(&CYBER), - (10, addr) if addr == address!("0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1") => Some(&DAI_STABLECOIN_10_C9000DA1), - (10, addr) if addr == address!("0x33800De7E817A70A694F31476313A7c572BBa100") => Some(&DERIVE_10_72BBA100), - (10, addr) if addr == address!("0x65559aA14915a70190438eF90104769e5E890A00") => Some(ÐEREUM_NAME_SERVICE_10_5E890A00), - (10, addr) if addr == address!("0xD8737CA46aa6285dE7B8777a8e3db232911baD41") => Some(&STAFI_10_911BAD41), - (10, addr) if addr == address!("0xF1a0DA3367BC7aa04F8D94BA57B862ff37CeD174") => Some(&SHAPESHIFT_FOX_TOKEN_10_37CED174), - (10, addr) if addr == address!("0x2E3D870790dC77A83DD1d18184Acc7439A53f475") => Some(&FRAX_10_9A53F475), - (10, addr) if addr == address!("0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be") => Some(&FRAX_SHARE_10_1C2205BE), - (10, addr) if addr == address!("0x1EBA7a6a72c894026Cd654AC5CDCF83A46445B08") => Some(&GITCOIN_10_46445B08), - (10, addr) if addr == address!("0x589d35656641d6aB57A545F08cf473eCD9B6D5F7") => Some(&GYEN_10_D9B6D5F7), - (10, addr) if addr == address!("0x2ed6222CB75E353b8789bec7Bb443b7eC9022021") => Some(&KRYLL_10_C9022021), - (10, addr) if addr == address!("0x3A18dcC9745eDcD1Ef33ecB93b0b6eBA5671e7Ca") => Some(&KUJIRA_10_5671E7CA), - (10, addr) if addr == address!("0xFdb794692724153d1488CcdBE0C56c252596735F") => Some(&LIDO_DAO_10_2596735F), - (10, addr) if addr == address!("0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6") => Some(&CHAINLINK_TOKEN_10_38FFA7F6), - (10, addr) if addr == address!("0xFEaA9194F9F8c1B65429E31341a103071464907E") => Some(&LOOPRINGCOIN_V2_10_1464907E), - (10, addr) if addr == address!("0xc40F949F8a4e094D1b49a23ea9241D289B7b2819") => Some(&LIQUITY_USD_10_9B7B2819), - (10, addr) if addr == address!("0x3390108E913824B8eaD638444cc52B9aBdF63798") => Some(&MASK_NETWORK_10_BDF63798), - (10, addr) if addr == address!("0xab7bAdEF82E9Fe11f6f33f87BC9bC2AA27F2fCB5") => Some(&MAKER_10_27F2FCB5), - (10, addr) if addr == address!("0x2561aa2bB1d2Eb6629EDd7b0938d7679B8b49f9E") => Some(&OCEAN_PROTOCOL_10_B8B49F9E), - (10, addr) if addr == address!("0x4200000000000000000000000000000000000042") => Some(&OPTIMISM), - (10, addr) if addr == address!("0xBC7B1Ff1c6989f006a1185318eD4E7b5796e66E1") => Some(&PENDLE_10_796E66E1), - (10, addr) if addr == address!("0xC1c167CC44f7923cd0062c4370Df962f9DDB16f5") => Some(&PEPE_10_9DDB16F5), - (10, addr) if addr == address!("0x9e1028F5F1D5eDE59748FFceE5532509976840E0") => Some(&PERPETUAL_PROTOCOL_10_976840E0), - (10, addr) if addr == address!("0x7FB688CCf682d58f86D7e38e03f9D22e7705448B") => Some(&RAI_REFLEX_INDEX_10_7705448B), - (10, addr) if addr == address!("0xB548f63D4405466B36C0c0aC3318a22fDcec711a") => Some(&RARI_GOVERNANCE_TOKEN_10_DCEC711A), - (10, addr) if addr == address!("0xC81D1F0EB955B0c020E5d5b264E1FF72c14d1401") => Some(&ROCKET_POOL_PROTOCOL_10_C14D1401), - (10, addr) if addr == address!("0x650AF3C15AF43dcB218406d30784416D64Cfb6B2") => Some(&STATUS_10_64CFB6B2), - (10, addr) if addr == address!("0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4") => Some(&SYNTHETIX_NETWORK_TOKEN_10_3D7599B4), - (10, addr) if addr == address!("0xba1Cf949c382A32a09A17B2AdF3587fc7fA664f1") => Some(&SOL_WORMHOLE_10_7FA664F1), - (10, addr) if addr == address!("0xEf6301DA234fC7b0545c6E877D3359FE0B9E50a4") => Some(&SUKU_10_0B9E50A4), - (10, addr) if addr == address!("0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9") => Some(&SYNTH_SUSD_10_751EC8D9), - (10, addr) if addr == address!("0x3eaEb77b03dBc0F6321AE1b72b2E9aDb0F60112B") => Some(&SUSHI_10_0F60112B), - (10, addr) if addr == address!("0x747e42Eb0591547a0ab429B3627816208c734EA7") => Some(&THRESHOLD_NETWORK_10_8C734EA7), - (10, addr) if addr == address!("0xaf8cA653Fa2772d58f4368B0a71980e9E3cEB888") => Some(&TELLOR_10_E3CEB888), - (10, addr) if addr == address!("0xE7798f023fC62146e8Aa1b36Da45fb70855a77Ea") => Some(&UMA_VOTING_TOKEN_V1_10_855A77EA), - (10, addr) if addr == address!("0x6fd9d7AD17242c41f7131d257212c54A0e816691") => Some(&UNISWAP_10_0E816691), - (10, addr) if addr == address!("0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85") => Some(&USDCOIN_10_D097FF85), - (10, addr) if addr == address!("0x7F5c764cBc14f9669B88837ca1490cCa17c31607") => Some(&USDCOIN_BRIDGED_FROM_ETHEREUM), - (10, addr) if addr == address!("0x94b008aA00579c1307B0EF2c499aD98a8ce58e58") => Some(&TETHER_USD_10_8CE58E58), - (10, addr) if addr == address!("0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db") => Some(&VELODROME_FINANCE), - (10, addr) if addr == address!("0x68f180fcCe6836688e9084f035309E29Bf0A2095") => Some(&WRAPPED_BTC_10_BF0A2095), - (10, addr) if addr == address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945") => Some(&WALLETCONNECT_TOKEN_10_DD927945), - (10, addr) if addr == address!("0x4200000000000000000000000000000000000006") => Some(&WRAPPED_ETHER_10_00000006), - (10, addr) if addr == address!("0xdC6fF44d5d932Cbd77B52E5612Ba0529DC6226F1") => Some(&WORLDCOIN), - (10, addr) if addr == address!("0x871f2F2ff935FD1eD867842FF2a7bfD051A5E527") => Some(&WOO_NETWORK_10_51A5E527), - (10, addr) if addr == address!("0x9db118D43069B73B8a252bF0be49d50Edbd81fc8") => Some(&XYO_NETWORK_10_DBD81FC8), - (10, addr) if addr == address!("0x9046D36440290FfDE54FE0DD84Db8b1CfEE9107B") => Some(&YEARN_FINANCE_10_FEE9107B), - (10, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_10_F13271CD), - (10, addr) if addr == address!("0xD1917629B3E6A72E6772Aab5dBe58Eb7FA3C2F33") => Some(&TOKEN_0X_PROTOCOL_TOKEN_10_FA3C2F33), - (42, addr) if addr == address!("0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa") => Some(&DAI_STABLECOIN_42_B64CA6AA), - (42, addr) if addr == address!("0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD") => Some(&MAKER_42_71A4FFCD), - (42, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP_42_4201F984), - (42, addr) if addr == address!("0xd0A1E359811322d97991E03f863a0C30C2cF029C") => Some(&WRAPPED_ETHER_42_C2CF029C), - (56, addr) if addr == address!("0x111111111117dC0aa78b770fA6A738034120C302") => Some(&TOKEN_1INCH_56_4120C302), - (56, addr) if addr == address!("0xfb6115445Bff7b52FeB98650C87f44907E58f802") => Some(&AAVE_56_7E58F802), - (56, addr) if addr == address!("0xBc7d6B50616989655AfD682fb42743507003056D") => Some(&ALCHEMY_PAY_56_7003056D), - (56, addr) if addr == address!("0x6bfF4Fb161347ad7de4A625AE5aa3A1CA7077819") => Some(&AMBIRE_ADEX_56_A7077819), - (56, addr) if addr == address!("0x12f31B73D812C6Bb0d735a218c086d44D5fe5f89") => Some(&AGEUR_56_D5FE5F89), - (56, addr) if addr == address!("0x33d08D8C7a168333a85285a68C0042b39fC3741D") => Some(&AIOZ_NETWORK_56_9FC3741D), - (56, addr) if addr == address!("0x82D2f8E02Afb160Dd5A480a617692e62de9038C4") => Some(&ALEPH_IM_56_DE9038C4), - (56, addr) if addr == address!("0xAC51066d7bEC65Dc4589368da368b212745d63E8") => Some(&MY_NEIGHBOR_ALICE_56_745D63E8), - (56, addr) if addr == address!("0xa1faa113cbE53436Df28FF0aEe54275c13B40975") => Some(&ALPHA_VENTURE_DAO_56_13B40975), - (56, addr) if addr == address!("0xf307910A4c7bbc79691fD374889b36d8531B08e3") => Some(&ANKR_56_531B08E3), - (56, addr) if addr == address!("0x6F769E65c14Ebd1f68817F5f1DcDb61Cfa2D6f7e") => Some(&ARPA_CHAIN_56_FA2D6F7E), - (56, addr) if addr == address!("0x000Ae314E2A2172a039B26378814C252734f556A") => Some(&ASTER), - (56, addr) if addr == address!("0xA2120b9e674d3fC3875f415A7DF52e382F141225") => Some(&AUTOMATA_56_2F141225), - (56, addr) if addr == address!("0x8b1f4432F943c465A973FeDC6d7aa50Fc96f1f65") => Some(&AXELAR_56_C96F1F65), - (56, addr) if addr == address!("0x715D400F88C167884bbCc41C5FeA407ed4D2f8A0") => Some(&AXIE_INFINITY_56_D4D2F8A0), - (56, addr) if addr == address!("0x935a544Bf5816E3A7C13DB2EFe3009Ffda0aCdA2") => Some(&BLUZELLE_56_DA0ACDA2), - (56, addr) if addr == address!("0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56") => Some(&BINANCE_USD_56_DD087D56), - (56, addr) if addr == address!("0xaEC945e04baF28b135Fa7c640f624f8D90F1C3a6") => Some(&COIN98_56_90F1C3A6), - (56, addr) if addr == address!("0xf9CeC8d50f6c8ad3Fb6dcCEC577e05aA32B224FE") => Some(&CHROMIA_56_32B224FE), - (56, addr) if addr == address!("0x09E889BB4D5b474f561db0491C38702F367A4e4d") => Some(&CLOVER_FINANCE_56_367A4E4D), - (56, addr) if addr == address!("0x52CE071Bd9b1C4B00A0b92D298c512478CaD67e8") => Some(&COMPOUND_56_8CAD67E8), - (56, addr) if addr == address!("0xd15CeE1DEaFBad6C0B3Fd7489677Cc102B141464") => Some(&CIRCUITS_OF_VALUE_56_2B141464), - (56, addr) if addr == address!("0x8dA443F84fEA710266C8eB6bC34B71702d033EF2") => Some(&CARTESI_56_2D033EF2), - (56, addr) if addr == address!("0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3") => Some(&DAI_STABLECOIN_56_58B1DBC3), - (56, addr) if addr == address!("0x23CE9e926048273eF83be0A3A8Ba9Cb6D45cd978") => Some(&MINES_OF_DALARNIA_56_D45CD978), - (56, addr) if addr == address!("0xe91a8D2c584Ca93C7405F15c22CdFE53C29896E3") => Some(&DEXTOOLS_56_C29896E3), - (56, addr) if addr == address!("0x99956D38059cf7bEDA96Ec91Aa7BB2477E0901DD") => Some(&DIA_56_7E0901DD), - (56, addr) if addr == address!("0xEC583f25A049CC145dA9A256CDbE9B6201a705Ff") => Some(&DREP_56_01A705FF), - (56, addr) if addr == address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17") => Some(&DEFI_YIELD_PROTOCOL_56_91BCEF17), - (56, addr) if addr == address!("0x7bd6FaBD64813c48545C9c0e312A0099d9be2540") => Some(&DOGELON_MARS_56_D9BE2540), - (56, addr) if addr == address!("0x4B5C23cac08a567ecf0c1fFcA8372A45a5D33743") => Some(&HARVEST_FINANCE_56_A5D33743), - (56, addr) if addr == address!("0x031b41e504677879370e9DBcF937283A8691Fa7f") => Some(&FETCH_AI_56_8691FA7F), - (56, addr) if addr == address!("0xfb5B838b6cfEEdC2873aB27866079AC55363D37E") => Some(&FLOKI_56_5363D37E), - (56, addr) if addr == address!("0x90C97F71E18723b0Cf0dfa30ee176Ab653E89F40") => Some(&FRAX_56_53E89F40), - (56, addr) if addr == address!("0xAD29AbB318791D579433D831ed122aFeAf29dcfe") => Some(&FANTOM_56_AF29DCFE), - (56, addr) if addr == address!("0xe48A3d7d0Bc88d552f730B62c006bC925eadB9eE") => Some(&FRAX_SHARE_56_5EADB9EE), - (56, addr) if addr == address!("0xe4Cc45Bb5DBDA06dB6183E8bf016569f40497Aa5") => Some(&GALXE_56_40497AA5), - (56, addr) if addr == address!("0x30117E4bC17d7B044194b76A38365C53b72F7D49") => Some(ÐGAS_56_B72F7D49), - (56, addr) if addr == address!("0x44Ec807ce2F4a6F2737A92e985f318d035883e47") => Some(&HASHFLOW_56_35883E47), - (56, addr) if addr == address!("0x5f4Bde007Dc06b867f86EBFE4802e34A1fFEEd63") => Some(&HIGHSTREET_56_1FFEED63), - (56, addr) if addr == address!("0xa2B726B1145A4773F68593CF171187d8EBe4d495") => Some(&INJECTIVE_56_EBE4D495), - (56, addr) if addr == address!("0x0231f91e02DebD20345Ae8AB7D71A41f8E140cE7") => Some(&JUPITER_56_8E140CE7), - (56, addr) if addr == address!("0x073690e6CE25bE816E68F32dCA3e11067c9FB5Cc") => Some(&KUJIRA_56_7C9FB5CC), - (56, addr) if addr == address!("0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD") => Some(&CHAINLINK_TOKEN_56_111A51BD), - (56, addr) if addr == address!("0x2eD9a5C8C13b93955103B9a7C167B67Ef4d568a3") => Some(&MASK_NETWORK_56_F4D568A3), - (56, addr) if addr == address!("0xF218184Af829Cf2b0019F8E6F0b2423498a36983") => Some(&MATH_56_98A36983), - (56, addr) if addr == address!("0xCC42724C6683B7E57334c4E856f4c9965ED682bD") => Some(&POLYGON_56_5ED682BD), - (56, addr) if addr == address!("0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6") => Some(&MERIT_CIRCLE_56_4EF9E5D6), - (56, addr) if addr == address!("0xe552Fb52a4F19e44ef5A967632DBc320B0820639") => Some(&METIS_56_B0820639), - (56, addr) if addr == address!("0xfE19F0B51438fd612f6FD59C1dbB3eA319f433Ba") => Some(&MAGIC_INTERNET_MONEY_56_19F433BA), - (56, addr) if addr == address!("0x5B6DcF557E2aBE2323c48445E8CC948910d8c2c9") => Some(&MIRROR_PROTOCOL_56_10D8C2C9), - (56, addr) if addr == address!("0x9Fb9a33956351cf4fa040f65A13b835A3C8764E3") => Some(&MULTICHAIN_56_3C8764E3), - (56, addr) if addr == address!("0x4e7f408be2d4E9D60F49A64B89Bb619c84C7c6F5") => Some(&PERPETUAL_PROTOCOL_56_84C7C6F5), - (56, addr) if addr == address!("0x7e624FA0E1c4AbFD309cC15719b7E2580887f570") => Some(&POLKASTARTER_56_0887F570), - (56, addr) if addr == address!("0xd21d29B38374528675C34936bf7d5Dd693D2a577") => Some(&PARSIQ_56_93D2A577), - (56, addr) if addr == address!("0x4C882ec256823eE773B25b414d36F92ef58a7c0C") => Some(&PSTAKE_FINANCE_56_F58A7C0C), - (56, addr) if addr == address!("0x833F307aC507D47309fD8CDD1F835BeF8D702a93") => Some(&REVV_56_8D702A93), - (56, addr) if addr == address!("0x3BC5AC0dFdC871B365d159f728dd1B9A0B5481E8") => Some(&STADER_56_0B5481E8), - (56, addr) if addr == address!("0xfA54fF1a158B5189Ebba6ae130CEd6bbd3aEA76e") => Some(&SOL_WORMHOLE_56_D3AEA76E), - (56, addr) if addr == address!("0xB0D502E938ed5f4df2E681fE6E419ff29631d62b") => Some(&STARGATE_FINANCE_56_9631D62B), - (56, addr) if addr == address!("0x51BA0b044d96C3aBfcA52B64D733603CCC4F0d4D") => Some(&SUPERFARM_56_CC4F0D4D), - (56, addr) if addr == address!("0x947950BcC74888a40Ffa2593C5798F11Fc9124C4") => Some(&SUSHI_56_FC9124C4), - (56, addr) if addr == address!("0xE64E30276C2F826FEbd3784958d6Da7B55DfbaD3") => Some(&SWFTCOIN_56_55DFBAD3), - (56, addr) if addr == address!("0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A") => Some(&SWIPE_56_FABA485A), - (56, addr) if addr == address!("0xa4080f1778e69467E905B8d6F72f6e441f9e9484") => Some(&SYNAPSE_56_1F9E9484), - (56, addr) if addr == address!("0x3b198e26E473b8faB2085b37978e36c9DE5D7f68") => Some(&CHRONOTECH_56_DE5D7F68), - (56, addr) if addr == address!("0x2222227E22102Fe3322098e4CBfE18cFebD57c95") => Some(&ALIEN_WORLDS_56_EBD57C95), - (56, addr) if addr == address!("0x728C5baC3C3e370E372Fc4671f9ef6916b814d8B") => Some(&UNIFI_PROTOCOL_DAO_56_6B814D8B), - (56, addr) if addr == address!("0xBf5140A22578168FD562DCcF235E5D43A02ce9B1") => Some(&UNISWAP_56_A02CE9B1), - (56, addr) if addr == address!("0x0D35A2B85c5A63188d566D104bEbf7C694334Ee4") => Some(&PAWTOCOL_56_94334EE4), - (56, addr) if addr == address!("0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d") => Some(&USDCOIN_56_32CD580D), - (56, addr) if addr == address!("0x55d398326f99059fF775485246999027B3197955") => Some(&TETHER_USD_56_B3197955), - (56, addr) if addr == address!("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c") => Some(&WRAPPED_BNB), - (56, addr) if addr == address!("0x2170Ed0880ac9A755fd29B2688956BD959F933F8") => Some(&WRAPPED_ETHER_56_59F933F8), - (56, addr) if addr == address!("0x4691937a7508860F876c9c0a2a617E7d9E945D4B") => Some(&WOO_NETWORK_56_9E945D4B), - (56, addr) if addr == address!("0x7324c7C0d95CEBC73eEa7E85CbAac0dBdf88a05b") => Some(&CHAIN_56_DF88A05B), - (56, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_56_F13271CD), - (130, addr) if addr == address!("0xbe41cde1C5e75a7b6c2c70466629878aa9ACd06E") => Some(&TOKEN_1INCH_130_A9ACD06E), - (130, addr) if addr == address!("0x44D618C366D7bC85945Bfc922ACad5B1feF7759A") => Some(&ANCIENT8_130_FEF7759A), - (130, addr) if addr == address!("0x02a24C380dA560E4032Dc6671d8164cfbEEAAE1e") => Some(&AAVE_130_BEEAAE1E), - (130, addr) if addr == address!("0xDDCe42b89215548beCaA160048460747Fe5675bC") => Some(&ARCBLOCK_130_FE5675BC), - (130, addr) if addr == address!("0xb8A8e137A2dAa25EF1B3577b6598fE8Be66Ecf77") => Some(&ALCHEMY_PAY_130_E66ECF77), - (130, addr) if addr == address!("0x34424B3352af905e41078a4029b61EDe62BbB32C") => Some(&ACROSS_PROTOCOL_TOKEN_130_62BBB32C), - (130, addr) if addr == address!("0x3e1C572d8b069fc2f14ac4f8bdCE6e8eA299A500") => Some(&AMBIRE_ADEX_130_A299A500), - (130, addr) if addr == address!("0xfd38ac2316f6d3631a86065aDb3292f6f15873B5") => Some(&AERGO_130_F15873B5), - (130, addr) if addr == address!("0x54FA9210cCB765639b7Fd532f25bCb1060D60F8B") => Some(&AEVO_130_60D60F8B), - (130, addr) if addr == address!("0xA4eeF95995F40aD0b3D63a474293Fc7CC681A118") => Some(&AGEUR_130_C681A118), - (130, addr) if addr == address!("0x14421614587A2A3e9C3Aa3131Fc396aF412721CF") => Some(&ADVENTURE_GOLD_130_412721CF), - (130, addr) if addr == address!("0x5F891E74947b0FC400128E5E85333d7a6cF99b1A") => Some(&AIOZ_NETWORK_130_6CF99B1A), - (130, addr) if addr == address!("0xbf194C82A5Bb9180f9280c1832f886a65Aebdcd6") => Some(&ALCHEMIX_130_5AEBDCD6), - (130, addr) if addr == address!("0xa3E646211a456e08829C33fcE21cC3DC4c15Bb5c") => Some(&ALEPH_IM_130_4C15BB5C), - (130, addr) if addr == address!("0x2a87dd1e1F849ed88C18565AFDa98e2EEEc73780") => Some(&ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_130_EEC73780), - (130, addr) if addr == address!("0xBb72B8031F590748d8910Aad7e25F8B18860960a") => Some(&MY_NEIGHBOR_ALICE_130_8860960A), - (130, addr) if addr == address!("0x44c3E7c49C4Bb6f4f5eCD87E035176dFceBD78d3") => Some(&ALPHA_VENTURE_DAO_130_CEBD78D3), - (130, addr) if addr == address!("0x6D5De04F1a3E0e554B9A15059d03e20cb3589153") => Some(&ALTLAYER_130_B3589153), - (130, addr) if addr == address!("0x4D6B8ecb576dF9BB4bF6E6764A469a762bBc967F") => Some(&_130_2BBC967F), - (130, addr) if addr == address!("0xf081Fc8E0878D7eBe6ec381E5d7279d6EFf97622") => Some(&ANKR_130_EFF97622), - (130, addr) if addr == address!("0x865d184885200B8e86eb2a3Da8b3B4a7d4A31308") => Some(&ARAGON_130_D4A31308), - (130, addr) if addr == address!("0xD1b8423FdE5F37464FadE603f80903cB314046cf") => Some(&APECOIN_130_314046CF), - (130, addr) if addr == address!("0xA63122b27308EED0C1D83DD355ADdaA7f678961b") => Some(&API3_130_F678961B), - (130, addr) if addr == address!("0xcDfcE5eb357E8976A80Be84E94a03BA963b9e379") => Some(&APU_APUSTAJA_130_63B9E379), - (130, addr) if addr == address!("0x5cC70a9DF8E293aFFb14DFCa1e7F851418a4b40d") => Some(&ARBITRUM_130_18A4B40D), - (130, addr) if addr == address!("0x59F16BaA7A22f49c32680661e0041A53442Ef089") => Some(&ARKHAM_130_442EF089), - (130, addr) if addr == address!("0xE911A809F87490406AB34fad701aabCA88e30b45") => Some(&ARPA_CHAIN_130_88E30B45), - (130, addr) if addr == address!("0x4b355De6Ea44711f0353Ed89545705395a30d7Fb") => Some(&ASH_130_5A30D7FB), - (130, addr) if addr == address!("0x1e196D83e2c562de0b1f270Eb72220335bA0ADa7") => Some(&ASSEMBLE_PROTOCOL_130_5BA0ADA7), - (130, addr) if addr == address!("0x7F3F14A49FE5D5009E4e0a09e76cB8468C09Ae56") => Some(&AIRSWAP_130_8C09AE56), - (130, addr) if addr == address!("0xBAAa314d2f5Af29B00867a612F24F816d890C4B2") => Some(&AUTOMATA_130_D890C4B2), - (130, addr) if addr == address!("0xa249732271cbA6E06Be4ac8B20f0D465FeE183Ab") => Some(&AETHIR_TOKEN_130_FEE183AB), - (130, addr) if addr == address!("0x82F90996a4F67Eb388116B3C6F35B6Ea91BeF68E") => Some(&BOUNCE_130_91BEF68E), - (130, addr) if addr == address!("0x48b8441dE79cEE3604b805093B41028d3c81684B") => Some(&AUDIUS_130_3C81684B), - (130, addr) if addr == address!("0x38DBf47e2a012a4b83823f15E3F3352A00939999") => Some(&ARTVERSE_TOKEN_130_00939999), - (130, addr) if addr == address!("0xbF678793522638F7439aFE3B94d2D2A3a4cBF2C9") => Some(&AXELAR_130_A4CBF2C9), - (130, addr) if addr == address!("0xDA63AdA216d2079B54F2047B2FdC2576D188f927") => Some(&AXIE_INFINITY_130_D188F927), - (130, addr) if addr == address!("0xc2a564b44b441D03f09f5B6B2b358B4a17388406") => Some(&BADGER_DAO_130_17388406), - (130, addr) if addr == address!("0x01625E26274Ed828Ac1d47694c97221b34a8ADdF") => Some(&BALANCER_130_34A8ADDF), - (130, addr) if addr == address!("0xa264F2b88C630f260AbDcAb577eAB7266A8857d5") => Some(&BAND_PROTOCOL_130_6A8857D5), - (130, addr) if addr == address!("0x4e373C99199773f9D92d32B8c8Bc0C81508ea589") => Some(&BASIC_ATTENTION_TOKEN_130_508EA589), - (130, addr) if addr == address!("0xe5ECB192f1aE5839eD49886F36dFA670f9500824") => Some(&BEAM_130_F9500824), - (130, addr) if addr == address!("0x604Ff88ADC02325EFb7f93DB3E442dc81D0588E7") => Some(&BICONOMY_130_1D0588E7), - (130, addr) if addr == address!("0x17f3AfE72cAa6b9090801b60607918b6D2Fa7cdc") => Some(&BIG_TIME_130_D2FA7CDC), - (130, addr) if addr == address!("0xA4Cb2aaf7503641B441e80fC353e6748fb523A5C") => Some(&BITDAO_130_FB523A5C), - (130, addr) if addr == address!("0x41f6e69166e81A9583DBc96604B01D2E9B3D706f") => Some(&HARRYPOTTEROBAMASONIC10INU_130_9B3D706F), - (130, addr) if addr == address!("0x942fC6b61686e06fB411cB1bCf5d16DC2b9255eA") => Some(&BLUR_130_2B9255EA), - (130, addr) if addr == address!("0xe7b3Ca9d9Db06E1867781fd1C5F02E6c8eF471ee") => Some(&BLUZELLE_130_8EF471EE), - (130, addr) if addr == address!("0xf2Cc2D274dA528AB64DA86bE3f8416E5472c5a62") => Some(&BANCOR_NETWORK_TOKEN_130_472C5A62), - (130, addr) if addr == address!("0xBE8E46422fB7F9Ca9D639B3109492D64BbB41b05") => Some(&BOBA_NETWORK_130_BBB41B05), - (130, addr) if addr == address!("0x4d5b7e9CCE3Ab81298dA7E1F52b48c9a61Df8972") => Some(&BARNBRIDGE_130_61DF8972), - (130, addr) if addr == address!("0xBbE97f3522101e5B6976cBf77376047097BA837F") => Some(&BONK), - (130, addr) if addr == address!("0x6A4a359C7453F5892392FCb8eAB7A9A100986B71") => Some(&BRAINTRUST_130_00986B71), - (130, addr) if addr == address!("0xa4da5c92F44422dFA3E2E309b53d93bbbDa9f9c6") => Some(&BINANCE_USD_130_BDA9F9C6), - (130, addr) if addr == address!("0x29129fa2e0F35594ca7b362fFA8c80f5f8e4f8E1") => Some(&COIN98_130_F8E4F8E1), - (130, addr) if addr == address!("0xb6A3E8e5715fd4c99EcEDaaAe121bDe4Ab6a1Ef1") => Some(&COINBASE_WRAPPED_BTC_130_AB6A1EF1), - (130, addr) if addr == address!("0xEb64b50FeF2A363940369285F86Ae9a68211db59") => Some(&COINBASE_WRAPPED_STAKED_ETH_130_8211DB59), - (130, addr) if addr == address!("0x6008F5BaD83742fDbFf5AAc55e3c51b65A8A8D9C") => Some(&CELO_NATIVE_ASSET_WORMHOLE_130_5A8A8D9C), - (130, addr) if addr == address!("0x5AD5d6B1AE6761Aab12066b51D21729248035703") => Some(&CELER_NETWORK_130_48035703), - (130, addr) if addr == address!("0xAC930Be88cFAc775A937E9291c4234Bf210a4e5b") => Some(&CHROMIA_130_210A4E5B), - (130, addr) if addr == address!("0xb0C69e24450e29afa8008962052007E08b2396b0") => Some(&CHILIZ_130_8B2396B0), - (130, addr) if addr == address!("0xD7212097f6d6B195a9Bc350b8dCE28a7fA41404C") => Some(&CLOVER_FINANCE_130_FA41404C), - (130, addr) if addr == address!("0xdf78e4F0A8279942ca68046476919A90f2288656") => Some(&COMPOUND_130_F2288656), - (130, addr) if addr == address!("0xc63612B3e697AEeC61C3Ce9baEc0f9Db32F499C3") => Some(&COTI_130_32F499C3), - (130, addr) if addr == address!("0x2562DC34c21371613CEF236b321EE63fCC295beC") => Some(&CIRCUITS_OF_VALUE_130_CC295BEC), - (130, addr) if addr == address!("0xC3a97c76AA194711E05Ff1d181534090B26D3996") => Some(&COW_PROTOCOL_130_B26D3996), - (130, addr) if addr == address!("0xF8E7B485CE10D3C7Ac30B8444B98a0cC423dFb57") => Some(&CLEARPOOL_130_423DFB57), - (130, addr) if addr == address!("0x6C28eeB9E018011d3841f42c5b458713621F90C1") => Some(&COVALENT_130_621F90C1), - (130, addr) if addr == address!("0x73c63A80Ec77BFe31eEc6663828C4beaA30dE818") => Some(&CRONOS_130_A30DE818), - (130, addr) if addr == address!("0x7e7784f13029c7C4BF4746112B1A503818B0D066") => Some(&CRYPTERIUM_130_18B0D066), - (130, addr) if addr == address!("0xAC73671a1762FE835208Fb93b7aE7490d1c2cCb3") => Some(&CURVE_DAO_TOKEN_130_D1C2CCB3), - (130, addr) if addr == address!("0xa7073F530856cD32c2037150dd9763B9BAaED2C5") => Some(&CARTESI_130_BAAED2C5), - (130, addr) if addr == address!("0x36fA435F6def83cbB7a0706d035C9eA062fCb619") => Some(&CRYPTEX_FINANCE_130_62FCB619), - (130, addr) if addr == address!("0xE60e9b2E68297d5DF6B383fEe787B7fB92c2F8aF") => Some(&SOMNIUM_SPACE_CUBES_130_92C2F8AF), - (130, addr) if addr == address!("0x35C458aD1e3e68d2717C8349b985384Be85a01Ed") => Some(&CIVIC_130_E85A01ED), - (130, addr) if addr == address!("0x1C6789F30e7E335c2Eca2c75EC193aDBF0087Ea5") => Some(&CONVEX_FINANCE_130_F0087EA5), - (130, addr) if addr == address!("0x8E29E12B46FeE20E034fE1e812bc12EFf14E5A09") => Some(&COVALENT_X_TOKEN_130_F14E5A09), - (130, addr) if addr == address!("0x20CAb320A855b39F724131C69424240519573f81") => Some(&DAI_STABLECOIN_130_19573F81), - (130, addr) if addr == address!("0x2ef0775A19d1bc2258653fc5529F8f8490288086") => Some(&MINES_OF_DALARNIA_130_90288086), - (130, addr) if addr == address!("0x91ED4bb192e3461E45575730508525083A270265") => Some(&DERIVADAO_130_3A270265), - (130, addr) if addr == address!("0x45a4f750d806498A4c7f7B5267815aaC328e874C") => Some(&DENT_130_328E874C), - (130, addr) if addr == address!("0x17C38207334011a131b0Acf200E35Cd81723cddd") => Some(&DEXTOOLS_130_1723CDDD), - (130, addr) if addr == address!("0x4bdc8553cf14EEBCD489cD1d75b7FF463f9543c2") => Some(&DIA_130_3F9543C2), - (130, addr) if addr == address!("0x0eb07cE7a28FF84DF132fb5ee5F56Aabc1b9E545") => Some(&DISTRICT0X_130_C1B9E545), - (130, addr) if addr == address!("0x12E96C2BFEA6E835CF8Dd38a5834fa61Cf723736") => Some(&DOGECOIN), - (130, addr) if addr == address!("0xE274f564c37aE15fd2570D544102eD4ACd2f84f1") => Some(&DEFI_PULSE_INDEX_130_CD2F84F1), - (130, addr) if addr == address!("0x56aF109D597eb0a0F79ebCD0786Dd88C38EA9Ee7") => Some(&DREP_130_38EA9EE7), - (130, addr) if addr == address!("0x601b11907EAa8d3785C0b10b41C3a7315faeB82c") => Some(&DYDX_130_5FAEB82C), - (130, addr) if addr == address!("0xBdaD8E37a9600F0A35976fE61608a4C89D598610") => Some(&DEFI_YIELD_PROTOCOL_130_9D598610), - (130, addr) if addr == address!("0xc89ab9B82610BB9b748F6757b8F3ac59d016C47D") => Some(&EIGENLAYER_130_D016C47D), - (130, addr) if addr == address!("0x24aBc32215354Ba3eD224bfa6312E31dD8E8c1ab") => Some(&ELASTOS_130_D8E8C1AB), - (130, addr) if addr == address!("0x91441fE1415B00bEA8930A4354Fe00c426C1DE05") => Some(&DOGELON_MARS_130_26C1DE05), - (130, addr) if addr == address!("0x9116E70d613860D349495d9Ef8e2AE1cA6cBD2dd") => Some(ÐENA_130_A6CBD2DD), - (130, addr) if addr == address!("0x9A0D1b7594CAAF0A9e4687cAc9fF4E0B84a6d0A6") => Some(&ENJIN_COIN_130_84A6D0A6), - (130, addr) if addr == address!("0x80756FAf1e7Fec5678bf505670eF176AB5F0383a") => Some(ÐEREUM_NAME_SERVICE_130_B5F0383A), - (130, addr) if addr == address!("0x5E5903C236E6873EB8400C3d1979271Fa93cdB03") => Some(ÐERNITY_CHAIN_130_A93CDB03), - (130, addr) if addr == address!("0xF8740269F121327D03ff77BeD03a9A3258880821") => Some(ÐER_FI_130_58880821), - (130, addr) if addr == address!("0x6319F47719b6713b1624C1b3A8e2DBf15b5D03FE") => Some(&EULER_130_5B5D03FE), - (130, addr) if addr == address!("0x72f34BC403a005A9Be390762EAa46ED42813B0a8") => Some(&EURO_COIN_130_2813B0A8), - (130, addr) if addr == address!("0xEc42461D9BbDF4eFB6481099253bBB7324D7d72d") => Some(&QUANTOZ_EURQ_130_24D7D72D), - (130, addr) if addr == address!("0x7A1ef7fD6E0d708295D8FD0C30Fd437d9C36FB5f") => Some(&STABLR_EURO_130_9C36FB5F), - (130, addr) if addr == address!("0x472E8be16Cc9823b9f6a73A34EA55c0c31ee825F") => Some(&HARVEST_FINANCE_130_31EE825F), - (130, addr) if addr == address!("0x45343279DefDAd803d81C06fBCf87936DDD7DFE7") => Some(&FETCH_AI_130_DDD7DFE7), - (130, addr) if addr == address!("0xec9Be303f204864145CCC193aEb21B5fa10764A6") => Some(&STAFI_130_A10764A6), - (130, addr) if addr == address!("0x1b3EC249dc44a64bF5Cb8Afdd70e30c26c51fA81") => Some(&FLOKI_130_6C51FA81), - (130, addr) if addr == address!("0xB20fD6fD28e1430f98a8C1e9A83C88E5D87D94e5") => Some(&FORTA_130_D87D94E5), - (130, addr) if addr == address!("0xFa004fa2ad8Ef993C2B0412baB776b182220F12e") => Some(&LEFORTH_GOVERNANCE_TOKEN_130_2220F12E), - (130, addr) if addr == address!("0xe0BB1924C17b39B71758F49a00D7c0363B7a318E") => Some(&SHAPESHIFT_FOX_TOKEN_130_3B7A318E), - (130, addr) if addr == address!("0x8c7879bf25D678D9949F305857bD4437d74132B9") => Some(&FRAX_130_D74132B9), - (130, addr) if addr == address!("0xe99235A02958637a5e01575297fBBa3790dC7F0e") => Some(&FANTOM_130_90DC7F0E), - (130, addr) if addr == address!("0x6F32725F82Bbb06FFdC04974db437fec1d7af1Af") => Some(&FUNCTION_X_130_1D7AF1AF), - (130, addr) if addr == address!("0x79301DF2117C7F56859fD01b28bBAA61062021D6") => Some(&FRAX_SHARE_130_062021D6), - (130, addr) if addr == address!("0x481cB2C560fc3351833b582b92b965626fd8803C") => Some(&GRAVITY_130_6FD8803C), - (130, addr) if addr == address!("0x70b2b785061d4c91C76CF87692f85B5c443d8675") => Some(&GALXE_130_443D8675), - (130, addr) if addr == address!("0x31A71801291774d267615f74b3a44FCEB560FAc9") => Some(&GALA_130_B560FAC9), - (130, addr) if addr == address!("0x0328A0255866706547B79072DEE54976b157d3D0") => Some(&GOLDFINCH_130_B157D3D0), - (130, addr) if addr == address!("0x4aE5712A153fDfDE81C305fF7f2E4e59840aD24B") => Some(&AAVEGOTCHI_130_840AD24B), - (130, addr) if addr == address!("0x04b747f478AE09AC797d026C8402f409E2C9f2b9") => Some(&GOLEM_130_E2C9F2B9), - (130, addr) if addr == address!("0xC4c6c3A3043Ad5ECe5c91290630A7735e125a938") => Some(&GNOSIS_TOKEN_130_E125A938), - (130, addr) if addr == address!("0x6E74EA6546e1f21Abf581b59114f2Bf5d3683f48") => Some(&GODS_UNCHAINED_130_D3683F48), - (130, addr) if addr == address!("0xBb2272Ffc0Ef8F439373aDffD45c3591B3204D71") => Some(&THE_GRAPH_130_B3204D71), - (130, addr) if addr == address!("0x592620d454a10c47274dBfe3BD922b9a8fE5cf48") => Some(&GITCOIN_130_8FE5CF48), - (130, addr) if addr == address!("0xEbA12eC786Cdc21b4bd5ba601B595b6A5C0920a9") => Some(&GEMINI_DOLLAR_130_5C0920A9), - (130, addr) if addr == address!("0xad173F5B5FE39DD1183a0d3C49C57629A574c36F") => Some(&GYEN_130_A574C36F), - (130, addr) if addr == address!("0x656104f2028BbFD7144C8f71Fa15daaA8c34A28b") => Some(&HASHFLOW_130_8C34A28B), - (130, addr) if addr == address!("0x99F64C3Db98a4870eFf637315d5C86dcb1374879") => Some(&HIGHSTREET_130_B1374879), - (130, addr) if addr == address!("0xc32C0c5a52F36D244C552E45C485cBceaf385B36") => Some(&HOPR_130_AF385B36), - (130, addr) if addr == address!("0x15D0e0c55a3E7eE67152aD7E89acf164253Ff68d") => Some(&HYPERLIQUID), - (130, addr) if addr == address!("0x4eA052BcAeE7d7ef2E3D61D601e878A560eaBe8e") => Some(&IDEX_130_60EABE8E), - (130, addr) if addr == address!("0xa76195FA77304Bba4cD8946198f5a90E42F3E51F") => Some(&ILLUVIUM_130_42F3E51F), - (130, addr) if addr == address!("0xc4Fc8cF76883094404DDb875d2AF15D1F5AA8053") => Some(&IMMUTABLE_X_130_F5AA8053), - (130, addr) if addr == address!("0xa5Afe7646f07d2C41AA82Bb6AE09e99E121e39B7") => Some(&INDEX_COOPERATIVE_130_121E39B7), - (130, addr) if addr == address!("0x9361cA28625E12C7f088523B274A25059A89f9F8") => Some(&INJECTIVE_130_9A89F9F8), - (130, addr) if addr == address!("0xD326ACaB8799fb44C3A5B7f7eFbAaB5f9F7b54fb") => Some(&INVERSE_FINANCE_130_9F7B54FB), - (130, addr) if addr == address!("0xD749094Bc62615f0c8645467e241b71Ae2B6843F") => Some(&IOTEX_130_E2B6843F), - (130, addr) if addr == address!("0x428c2B7Fa7a7821891fb529BAE4d80a71d5c61A8") => Some(&GEOJAM_130_1D5C61A8), - (130, addr) if addr == address!("0x8EF0686F380dD07f3e2121831839371922720708") => Some(&JASMYCOIN_130_22720708), - (130, addr) if addr == address!("0x781CC305fCBFe7cde376C9Ef5469d5a7E5CaB8b2") => Some(&JUPITER_130_E5CAB8B2), - (130, addr) if addr == address!("0xbe51A5e8FA434F09663e8fB4CCe79d0B2381Afad") => Some(&JUPITER_130_2381AFAD), - (130, addr) if addr == address!("0x05DBd720fc26F732c8d42Ea89BD7F442EA6AFE80") => Some(&KEEP_NETWORK_130_EA6AFE80), - (130, addr) if addr == address!("0x68Cea24F675e4F25584607F6c9feFb353f1bBfDc") => Some(&SELFKEY_130_3F1BBFDC), - (130, addr) if addr == address!("0xB0E4Ad2dFe3754e4a2443A7a828Eda5bB7Cd2284") => Some(&KYBER_NETWORK_CRYSTAL_130_B7CD2284), - (130, addr) if addr == address!("0x9C41547e404942C173E28bB2B6abE4cf5fad6A74") => Some(&KEEP3RV1_130_5FAD6A74), - (130, addr) if addr == address!("0x14CFFAD448AeB0876c56B7aa28999C9a4f002943") => Some(&KRYLL_130_4F002943), - (130, addr) if addr == address!("0x2206cdcC9B94fF7dB7A9eAbeC77b5cE430258681") => Some(&KUJIRA_130_30258681), - (130, addr) if addr == address!("0x1201209f55634bdDb67034efE4e8aA4D1B7B482C") => Some(&LAYER3_130_1B7B482C), - (130, addr) if addr == address!("0xb34b3DE63D22ffC90419c1a439de6C7d46687782") => Some(&LCX_130_46687782), - (130, addr) if addr == address!("0x68A6dbc7214a0F2b0d875963663F1613814E8829") => Some(&LIDO_DAO_130_814E8829), - (130, addr) if addr == address!("0x5a53B6D19D8EDCb7923F0D840EeBB3f09BBeEfB7") => Some(&CHAINLINK_TOKEN_130_9BBEEFB7), - (130, addr) if addr == address!("0x68648F52B85407806bC1d349B745D13C91be0fDf") => Some(&LITENTRY_130_91BE0FDF), - (130, addr) if addr == address!("0x1D1BFCFC6ae6FE045f151C7e589fB241AAC89733") => Some(&LEAGUE_OF_KINGDOMS_130_AAC89733), - (130, addr) if addr == address!("0xc68992e0514968BfbA3Dad201fef91f6009f523c") => Some(&LOOM_NETWORK_130_009F523C), - (130, addr) if addr == address!("0x11c6B34caDC550B65A9666497d7FCb39f35B73E3") => Some(&LIVEPEER_130_F35B73E3), - (130, addr) if addr == address!("0x0176B38b7767451b1B682236eCe2fae853C71a60") => Some(&LIQUITY_130_53C71A60), - (130, addr) if addr == address!("0xA2af802b95D7e20167e5aeaC7Fe8fDf4a8aB158A") => Some(&LOOPRINGCOIN_V2_130_A8AB158A), - (130, addr) if addr == address!("0xD7eb7348Ba44c5A2f9f1D1d3534623230c7bee3F") => Some(&BLOCKLORDS_130_0C7BEE3F), - (130, addr) if addr == address!("0xf81B7485B4cB59645F74528D702c7f8CD72577FB") => Some(&LIQUITY_USD_130_D72577FB), - (130, addr) if addr == address!("0x276361c863903751771e9DabA6dDfaAf00FE358b") => Some(&DECENTRALAND_130_00FE358B), - (130, addr) if addr == address!("0xC42B642F5010a2A3bD3CA2396Fe6f2e21B9512C4") => Some(&MASK_NETWORK_130_1B9512C4), - (130, addr) if addr == address!("0xB999b66186d7a48BF0Eb5d22f4E7053A99eD2C97") => Some(&MATH_130_99ED2C97), - (130, addr) if addr == address!("0xF6AC97B05B3bC92f829c7584b25839906507176b") => Some(&POLYGON_130_6507176B), - (130, addr) if addr == address!("0x460ec1C67e1614Bf1feAb84b98795BAE2d657399") => Some(&MERIT_CIRCLE_130_2D657399), - (130, addr) if addr == address!("0x68619Bc0C709FB63555Fe988ed14e78f7E6ACc40") => Some(&MOSS_CARBON_CREDIT_130_7E6ACC40), - (130, addr) if addr == address!("0xB29FddC20D5e4bacE9F54c1d9237953331BFeFF4") => Some(&MEASURABLE_DATA_TOKEN_130_31BFEFF4), - (130, addr) if addr == address!("0x397E34AFF8bFc8Ec14aa78F378074F6d8E3E7d06") => Some(&MEMECOIN_130_8E3E7D06), - (130, addr) if addr == address!("0xBfBa2A8745e5C85544DB7C8824C6962aB3A8f102") => Some(&METIS_130_B3A8F102), - (130, addr) if addr == address!("0x397C1f55FefF63C8947624b0d457a2CA3e3602ab") => Some(&MAGIC_INTERNET_MONEY_130_3E3602AB), - (130, addr) if addr == address!("0x5FE989EaB3021d7e742099d05a7937bA4A72D717") => Some(&MIRROR_PROTOCOL_130_4A72D717), - (130, addr) if addr == address!("0xf7A581f6e26EEa790225d76Af8821EA34Dc3c117") => Some(&MELON_130_4DC3C117), - (130, addr) if addr == address!("0x58d68e179864605fEA06EAADF1185c6e78921Ebd") => Some(&MOG_COIN_130_78921EBD), - (130, addr) if addr == address!("0xAe6065FB0244A68036C82deC9a8dE5501c7A1087") => Some(&MONAVALE_130_1C7A1087), - (130, addr) if addr == address!("0xaa2109f14Bb155766cBA9E7fa8B8D4bF0ff19949") => Some(&MOVEMENT_130_0FF19949), - (130, addr) if addr == address!("0x587e0E022b074015F4e81eCa489c0C41d752A219") => Some(&MAPLE_130_D752A219), - (130, addr) if addr == address!("0x71d69d07914d087f1C3536F7A5006a256CfAd9Ea") => Some(&METAL_130_6CFAD9EA), - (130, addr) if addr == address!("0x1C3a8fB65Ab82D73e26B6403bf505B99d82b4701") => Some(&MULTICHAIN_130_D82B4701), - (130, addr) if addr == address!("0x10F109379E231d5c294ee6A5f9Abb2F8b40A8Dd1") => Some(&MSTABLE_USD_130_B40A8DD1), - (130, addr) if addr == address!("0xe3d92FB06a4EEbaC5879D3C1073e0eAB81D5f345") => Some(&MUSE_DAO_130_81D5F345), - (130, addr) if addr == address!("0xD6ec6A24d5365A1811B05099f8D353c0Ff182974") => Some(&GENSOKISHI_METAVERSE_130_FF182974), - (130, addr) if addr == address!("0xCF7c45Ccc1327ac1E9Cb9E098898c59402727794") => Some(&MXC_130_02727794), - (130, addr) if addr == address!("0x328Ed7736871F863C8216Ca6CbB6f29B795032Df") => Some(&POLYSWARM_130_795032DF), - (130, addr) if addr == address!("0xc1C06527E810C4A198D8C5d35e1dDBc987696276") => Some(&NEIRO_130_87696276), - (130, addr) if addr == address!("0x75b93cED9627Cd172912304Fb79Cd3e7336BaF62") => Some(&NKN_130_336BAF62), - (130, addr) if addr == address!("0x931e587542b8603EA3C6420dD8d3b22eDbdA20FC") => Some(&NUMERAIRE_130_DBDA20FC), - (130, addr) if addr == address!("0x2AEB5256de25ECed47797b82d2F5C404AACEA6b9") => Some(&NUCYPHER_130_AACEA6B9), - (130, addr) if addr == address!("0x652293F4e9b0ef61C52a78D6615D9f5f3cD79208") => Some(&OCEAN_PROTOCOL_130_3CD79208), - (130, addr) if addr == address!("0xa60CE8f7ec6A091535b4708569B39DF5eE18c880") => Some(&ORIGIN_PROTOCOL_130_EE18C880), - (130, addr) if addr == address!("0x5949b9200dF1e77878dB3D061e43cF878Ee37383") => Some(&OMG_NETWORK_130_8EE37383), - (130, addr) if addr == address!("0xf5614D20c13D5BF2F9e640f00B7B2B76959Eb0E3") => Some(&OMNI_NETWORK_130_959EB0E3), - (130, addr) if addr == address!("0xaD0bae21db0b471dFfC6f8F9EEacFe9A85321557") => Some(&ONDO_FINANCE_130_85321557), - (130, addr) if addr == address!("0xCF2050ebC80B74370C1C2B71bDB635d11be3E8c0") => Some(&ORCA_ALLIANCE_130_1BE3E8C0), - (130, addr) if addr == address!("0x3C5319013FD75976F0f13b0bc0852537B6eaF396") => Some(&ORION_PROTOCOL_130_B6EAF396), - (130, addr) if addr == address!("0x9775C2b4f245248dE5596252Ac69311152B98042") => Some(&ORCHID_130_52B98042), - (130, addr) if addr == address!("0x3614c8d98Bf905AbE075BfA289231bbc0D292327") => Some(&PAYPEREX_130_0D292327), - (130, addr) if addr == address!("0xeC37cdfC9a692b3cCd5c85696D14aaA31E75d6aC") => Some(&PLAYDAPP_130_1E75D6AC), - (130, addr) if addr == address!("0xD9b5DA95B3D97c3E9872102fDb47d4c09074952B") => Some(&PEPE_130_9074952B), - (130, addr) if addr == address!("0x5944D2728d5fea7D1F4AA4958E3aEbb3CCFEc7D5") => Some(&PERPETUAL_PROTOCOL_130_CCFEC7D5), - (130, addr) if addr == address!("0xd0F77df9a8f0e855F910361f5f59958118d064c6") => Some(&PIRATE_NATION_130_18D064C6), - (130, addr) if addr == address!("0x5441619a9754Aee0665c939743cf7611abB6F6C7") => Some(&PLUTON_130_ABB6F6C7), - (130, addr) if addr == address!("0xF6A49aEdbD7861DeD0DA2BE1f21C6954E5682E95") => Some(&POLYGON_ECOSYSTEM_TOKEN_130_E5682E95), - (130, addr) if addr == address!("0x82a98121eaf30b0E135b08d4208c837Cdc306503") => Some(&POLKASTARTER_130_DC306503), - (130, addr) if addr == address!("0x2f5cfdC89fb96f2cf6c0FB1Ca6e3501Dd538D863") => Some(&POLYMATH_130_D538D863), - (130, addr) if addr == address!("0xA2a36541c5a54bd2815985418105091B4D4782d5") => Some(&MARLIN_130_4D4782D5), - (130, addr) if addr == address!("0x562E588471cA0e710b2b1217867FFb2E0F2a5642") => Some(&PORTAL_130_0F2A5642), - (130, addr) if addr == address!("0xf265af514762286A63d015FeE382B90edfFa6bff") => Some(&POWER_LEDGER_130_DFFA6BFF), - (130, addr) if addr == address!("0xD17D5f0DA4200bBfd3D6626AC6aEA2eccbf9fEE0") => Some(&PRIME_130_CBF9FEE0), - (130, addr) if addr == address!("0xC6Fbf362a12804FEca22000f37DB5EFC1F41A7c9") => Some(&PROPY_130_1F41A7C9), - (130, addr) if addr == address!("0xc7B7dcF3c6CAcAAc13F92c9173f9A0060ABf3def") => Some(&PARSIQ_130_0ABF3DEF), - (130, addr) if addr == address!("0x13FE2c4504f3AA18708561250e2F20E4E7D7CAa2") => Some(&PSTAKE_FINANCE_130_E7D7CAA2), - (130, addr) if addr == address!("0xAdf70dc4AaeFbC6D1E7A6cF0B02b0F2138b560d2") => Some(&PUFFER_FINANCE_130_38B560D2), - (130, addr) if addr == address!("0x0D2f98904D88909072eA6e61105CBBf78e6207c5") => Some(&PAYPAL_USD_130_8E6207C5), - (130, addr) if addr == address!("0x3a8723f2929F370c61EaC583d6652e5C98C360d4") => Some(&QUANT_130_98C360D4), - (130, addr) if addr == address!("0x006254C4664C678e64c3265da28304cc8c1068b8") => Some(&QREDO_130_8C1068B8), - (130, addr) if addr == address!("0xb019a038eaDCB2F96321D236F6633C8d6Bb5eAbB") => Some(&QUANTSTAMP_130_6BB5EABB), - (130, addr) if addr == address!("0xD815958F92E6aBe63437BCe166E97027f8E6caC2") => Some(&QUICKSWAP_130_F8E6CAC2), - (130, addr) if addr == address!("0x3F9A30c86DC7F0c657eA17d52Efe09Eff08a1a45") => Some(&RADICLE_130_F08A1A45), - (130, addr) if addr == address!("0x6164A78F7B2aC49cf9b76c49e5B6909e89f34a66") => Some(&RAI_REFLEX_INDEX_130_89F34A66), - (130, addr) if addr == address!("0xe8a0078aA52ac7e93aE43818DdD64591E025BB6F") => Some(&SUPERRARE_130_E025BB6F), - (130, addr) if addr == address!("0x16F01392Ed7fC6F3C345CF544cf1172103C8561C") => Some(&RARIBLE_130_03C8561C), - (130, addr) if addr == address!("0x29EA5682024c8C62Cd8BDf691C4f0c5D66B403E3") => Some(&RUBIC_130_66B403E3), - (130, addr) if addr == address!("0x75B2dBb2a7C70073133E42F64366a986c841cd3e") => Some(&RIBBON_FINANCE_130_C841CD3E), - (130, addr) if addr == address!("0x560603E0bFC941063D1375Ec4E3f9FE38261617E") => Some(&REPUBLIC_TOKEN_130_8261617E), - (130, addr) if addr == address!("0x097ca3FC389697080C84148C455Ca839b2816Fc4") => Some(&REPUTATION_AUGUR_V1_130_B2816FC4), - (130, addr) if addr == address!("0xE86B1E5613a5761D005a2D00D8a1B4ad1e72A8c4") => Some(&REPUTATION_AUGUR_V2_130_1E72A8C4), - (130, addr) if addr == address!("0x9FcC3133779F2039c29908c915b6EFaE9d8663Cd") => Some(&REQUEST_130_9D8663CD), - (130, addr) if addr == address!("0xc14a68015fA6396eF97B57839da544910f9Ca657") => Some(&REVV_130_0F9CA657), - (130, addr) if addr == address!("0x2178f07c1d585C39272CAf69A72beF08aAD6c9AB") => Some(&RENZO_130_AAD6C9AB), - (130, addr) if addr == address!("0x8c9606001CF1787CEb80E03DEF3F9BaF946CF284") => Some(&RARI_GOVERNANCE_TOKEN_130_946CF284), - (130, addr) if addr == address!("0x538fB2719135740b8877607217Dc391FB3347ACb") => Some(&IEXEC_RLC_130_B3347ACB), - (130, addr) if addr == address!("0x7Ad899b7C793743fDE692d982F190f443F88c889") => Some(&RALLY_130_3F88C889), - (130, addr) if addr == address!("0x965C6DeBFa700F53a38d42DbaeD922c58d649868") => Some(&RENDER_TOKEN_130_8D649868), - (130, addr) if addr == address!("0x682B2f07e61022A80Ac2753448f7D95E9de41D99") => Some(&ROOK_130_9DE41D99), - (130, addr) if addr == address!("0x993A565A1E6219951323cA3c34Cee0A3b1889066") => Some(&RESERVE_RIGHTS_130_B1889066), - (130, addr) if addr == address!("0x47B72717E48Da346C3F1ED1311c8DCDe10EfD888") => Some(&SAFE_130_10EFD888), - (130, addr) if addr == address!("0x6A654A2ec95fB988Ea37746dBCca10772CAf25CA") => Some(&THE_SANDBOX_130_2CAF25CA), - (130, addr) if addr == address!("0x7ccc67C7b232aa6417d9422e90D91ec4b32d72E5") => Some(&STADER_130_B32D72E5), - (130, addr) if addr == address!("0xaa571d01057cdF477D73433D36D86fCb5664158e") => Some(&SHIBA_INU_130_5664158E), - (130, addr) if addr == address!("0x45Bda7bA10DaC525a86DBEaB3135701A66024F2F") => Some(&SHPING_130_66024F2F), - (130, addr) if addr == address!("0x486Bbb6f250343AdB4782F50Dd09766f8aD20c01") => Some(&SKALE_130_8AD20C01), - (130, addr) if addr == address!("0x5A6058002d0d336e5E8860652e7054a6d07074E4") => Some(&SKY_GOVERNANCE_TOKEN_130_D07074E4), - (130, addr) if addr == address!("0xbD2DD310FECBFb1111fC3262F3a97bA696cb03B3") => Some(&SMOOTH_LOVE_POTION_130_96CB03B3), - (130, addr) if addr == address!("0x914f7CE2B080B2186159C2213B1e193E265aBF5F") => Some(&STATUS_130_265ABF5F), - (130, addr) if addr == address!("0x022D952aBCc6C8271F26e59e37A65dC359E6bc88") => Some(&SYNTHETIX_NETWORK_TOKEN_130_59E6BC88), - (130, addr) if addr == address!("0x5e03C123D829505F4DEa87cf679F77c9dC4627ab") => Some(&UNISOCKS_130_DC4627AB), - (130, addr) if addr == address!("0x4Ff3E944D5Cb54f6f4A1dd035782BE59c3d054FE") => Some(&SOL_WORMHOLE_130_C3D054FE), - (130, addr) if addr == address!("0xbdE8A5331E8Ac4831cf8ea9e42e229219EafaB97") => Some(&SOLANA), - (130, addr) if addr == address!("0x739316C7bc4A39Eb39dcFa1b181b64abc17fEF7F") => Some(&SPELL_TOKEN_130_C17FEF7F), - (130, addr) if addr == address!("0x51A7b9a11f10D04C16306D90dc4EC22b036DD629") => Some(&SPX6900_130_036DD629), - (130, addr) if addr == address!("0x77c8A8E1dd3b5270d3Ab589543e9A83319373135") => Some(&STARGATE_FINANCE_130_19373135), - (130, addr) if addr == address!("0xf13B5B21555092882e69b22282DAf891c9951835") => Some(&STORJ_TOKEN_130_C9951835), - (130, addr) if addr == address!("0x09f705405677970E509d606348D4635D2332c72e") => Some(&STARKNET_130_2332C72E), - (130, addr) if addr == address!("0xEf86E70E534E02AADEAE95b843973d4AcacCeA22") => Some(&STOX_130_CACCEA22), - (130, addr) if addr == address!("0xc05B416738DDEBd14D5A9B790a6e1ce782176525") => Some(&SUKU_130_82176525), - (130, addr) if addr == address!("0x0c288302629Fc22504D59Ddf8fbf8AA92bD86D3D") => Some(&SUPERFARM_130_2BD86D3D), - (130, addr) if addr == address!("0x7251d204c2e867b31096D5c7091298239B3A6a0F") => Some(&SYNTH_SUSD_130_9B3A6A0F), - (130, addr) if addr == address!("0x2982Be2D0c6ae4A7D5BC1c8fe7B630E3BDfb3ce5") => Some(&SUSHI_130_BDFB3CE5), - (130, addr) if addr == address!("0xa8015cbc9f7c58788BA00854c330F027028A5870") => Some(&SWELL_130_028A5870), - (130, addr) if addr == address!("0x0610cDF9856b8825213672981056CD4945Af1616") => Some(&SWFTCOIN_130_45AF1616), - (130, addr) if addr == address!("0xDcA295E850666753c6332D6B0E0445B09785c2E1") => Some(&SWIPE_130_9785C2E1), - (130, addr) if addr == address!("0x1BAAc1979527A38F367c6f89bE081aBfcFFCF85E") => Some(&SYLO_130_CFFCF85E), - (130, addr) if addr == address!("0xCeb1F5671C47cee096C3B40353863b6781888A48") => Some(&SYNAPSE_130_81888A48), - (130, addr) if addr == address!("0x8f7F997ba304f426E3138999919c23f68cD6FA96") => Some(&SYRUP_TOKEN_130_8CD6FA96), - (130, addr) if addr == address!("0x8F43Ab8648F1a3BAEea3782Ba5f562a148f2Ad54") => Some(&THRESHOLD_NETWORK_130_48F2AD54), - (130, addr) if addr == address!("0xFdCa15bd55F350a36E63C47661914d80411d2C22") => Some(&BITTENSOR), - (130, addr) if addr == address!("0xAd497996Dc33DC8E8e552824CcEe199420BC7814") => Some(&TBTC_130_20BC7814), - (130, addr) if addr == address!("0xD9Cbd701bbEA8e9Aaee7d82aa60748451eDa749c") => Some(&CHRONOTECH_130_1EDA749C), - (130, addr) if addr == address!("0xd649b9AD2104418B5b032a5899fBcd54a9a46c68") => Some(&ALIEN_WORLDS_130_A9A46C68), - (130, addr) if addr == address!("0x5eD5DA180bB125f229AB7b825E34D2b936213e0B") => Some(&TOKEMAK_130_36213E0B), - (130, addr) if addr == address!("0x502865ECDd2a2929Aa9418297bE7d3C4a7BD5Ac6") => Some(&TE_FOOD_130_A7BD5AC6), - (130, addr) if addr == address!("0x1ac70C9e29bC19640E64D938DD8D6A46dbAe6f2e") => Some(&ORIGINTRAIL_130_DBAE6F2E), - (130, addr) if addr == address!("0x8e902FDeA73e5CF9621D2Bee82cD79196d8ec63b") => Some(&TELLOR_130_6D8EC63B), - (130, addr) if addr == address!("0x437dD6360Bd17FB353c67376371133Cd33dacdBD") => Some(&TRIBE_130_33DACDBD), - (130, addr) if addr == address!("0x55C65102C26b173696e935B1325e5AaeF30cFE0e") => Some(&TRUEFI_130_F30CFE0E), - (130, addr) if addr == address!("0x1E4339318EcE1d6D9d2Fb129b31C06b9F2d202A1") => Some(&TURBO_130_F2D202A1), - (130, addr) if addr == address!("0x756fb781389DCaF9D3BC5468927F06A913bD9D5D") => Some(&THE_VIRTUA_KOLECT_130_13BD9D5D), - (130, addr) if addr == address!("0x478923278640a10A60951E379aFFb60772435f8C") => Some(&UMA_VOTING_TOKEN_V1_130_72435F8C), - (130, addr) if addr == address!("0xe9225a870b54f8FBA42c8188D211271f0408a30B") => Some(&UNIFI_PROTOCOL_DAO_130_0408A30B), - (130, addr) if addr == address!("0x8f187aA05619a017077f5308904739877ce9eA21") => Some(&UNISWAP_130_7CE9EA21), - (130, addr) if addr == address!("0x5EAFF8Fa6f3831Bb86FeEB701E6f98293E264D36") => Some(&PAWTOCOL_130_3E264D36), - (130, addr) if addr == address!("0x078D782b760474a361dDA0AF3839290b0EF57AD6") => Some(&USDCOIN_130_0EF57AD6), - (130, addr) if addr == address!("0x2A22868610610199D43fE93A16661473A9f86f1E") => Some(&GLOBAL_DOLLAR_130_A9F86F1E), - (130, addr) if addr == address!("0xF7E6430137eF8087E0D472343f358e986De0FEFF") => Some(&PAX_DOLLAR_130_6DE0FEFF), - (130, addr) if addr == address!("0xf37748D2Cc6E6d5D05945Ce130C03c147b2F3a5F") => Some(&QUANTOZ_USDQ_130_7B2F3A5F), - (130, addr) if addr == address!("0xaC025d055a6B633992dE1F796b97B97F004c06a7") => Some(&STABLR_USD_130_004C06A7), - (130, addr) if addr == address!("0x116EE4d63847fb295dD919aE57B768EA3B2f7Bb4") => Some(&USDS_STABLECOIN_130_3B2F7BB4), - (130, addr) if addr == address!("0x588CE4F028D8e7B53B687865d6A67b3A54C75518") => Some(&TETHER_USD_130_54C75518), - (130, addr) if addr == address!("0xc7bA59c95ba747a7c374DC7208a0513798BC5950") => Some(&USUAL_130_98BC5950), - (130, addr) if addr == address!("0x286b5Ecea3749c7c7047104aa3C5749901564A0b") => Some(&VANRY_130_01564A0B), - (130, addr) if addr == address!("0x4afd08AC2416450d9c8b84D287dbfFb68FFe537f") => Some(&VOYAGER_TOKEN_130_8FFE537F), - (130, addr) if addr == address!("0xb86a08ec917EeF9f835aC2B26c3a506c06364A49") => Some(&WRAPPED_AMPLEFORTH_130_06364A49), - (130, addr) if addr == address!("0x927B51f251480a681271180DA4de28D44EC4AfB8") => Some(&WRAPPED_BTC_130_4EC4AFB8), - (130, addr) if addr == address!("0xaE87B8eb5E313AC72B306CbA7c1E3f23D72e82C4") => Some(&WRAPPED_CENTRIFUGE_130_D72E82C4), - (130, addr) if addr == address!("0x4200000000000000000000000000000000000006") => Some(&WRAPPED_ETHER_130_00000006), - (130, addr) if addr == address!("0x97Fadb3D000b953360FD011e173F12cDDB5d70Fa") => Some(&DOGWIFHAT), - (130, addr) if addr == address!("0xef22b9df2dDf4246A827575C4Aa46BDaeFd89E62") => Some(&WOO_NETWORK_130_EFD89E62), - (130, addr) if addr == address!("0x15261eEb999eD3C3ae3c5319E0035940dc06a12f") => Some(&CHAIN_130_DC06A12F), - (130, addr) if addr == address!("0x139451953Ef1865c096F89C5e522C081DC3b5f11") => Some(&PLASMA), - (130, addr) if addr == address!("0x2615a94df961278DcbC41Fb0a54fEc5f10a693aE") => Some(&XRP), - (130, addr) if addr == address!("0xb1A9385B500Fe81B58c4d0e3AaCC39d8021265c3") => Some(&XSGD_130_021265C3), - (130, addr) if addr == address!("0x43D5EA0f30Bce3907aAD6783e61D56592AEbE4eA") => Some(&XYO_NETWORK_130_2AEBE4EA), - (130, addr) if addr == address!("0x52Bf54Eb4210F588320f3e4c151Bca81f84a3201") => Some(&YEARN_FINANCE_130_F84A3201), - (130, addr) if addr == address!("0x62ffD4229bb9a327412D1BE518A1dbAe6c18A07E") => Some(&DFI_MONEY_130_6C18A07E), - (130, addr) if addr == address!("0xeA20C2Cf22acBbF3d8311D15bC73FD7076E36f4B") => Some(&YIELD_GUILD_GAMES_130_76E36F4B), - (130, addr) if addr == address!("0x83f31af747189c2FA9E5DeB253200c505eff6ed2") => Some(&ZCASH), - (130, addr) if addr == address!("0x757dCF360f2FE999FAEEBcc6E80f5Eceb3cb3CA4") => Some(&ZETACHAIN_130_B3CB3CA4), - (130, addr) if addr == address!("0x00ad3704d1e101DF76f87738bEfE67737eD29cFb") => Some(&LAYERZERO_130_7ED29CFB), - (130, addr) if addr == address!("0x7e7e8e5f0eDd7ca2ed3D9609cea1FF37a6E7Edf5") => Some(&TOKEN_0X_PROTOCOL_TOKEN_130_A6E7EDF5), - (137, addr) if addr == address!("0xD6DF932A45C0f255f85145f286eA0b292B21C90B") => Some(&AAVE_137_2B21C90B), - (137, addr) if addr == address!("0xE0B52e49357Fd4DAf2c15e02058DCE6BC0057db4") => Some(&AGEUR_137_C0057DB4), - (137, addr) if addr == address!("0x0621d647cecbFb64b79E44302c1933cB4f27054d") => Some(&_137_4F27054D), - (137, addr) if addr == address!("0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3") => Some(&BALANCER_137_3B0E76A3), - (137, addr) if addr == address!("0xA8b1E0764f85f53dfe21760e8AfE5446D82606ac") => Some(&BAND_PROTOCOL_137_D82606AC), - (137, addr) if addr == address!("0xc26D47d5c33aC71AC5CF9F776D63Ba292a4F7842") => Some(&BANCOR_NETWORK_TOKEN_137_2A4F7842), - (137, addr) if addr == address!("0x8505b9d2254A7Ae468c0E9dd10Ccea3A837aef5c") => Some(&COMPOUND_137_837AEF5C), - (137, addr) if addr == address!("0x172370d5Cd63279eFa6d502DAB29171933a610AF") => Some(&CURVE_DAO_TOKEN_137_33A610AF), - (137, addr) if addr == address!("0x66Dc5A08091d1968e08C16aA5b27BAC8398b02Be") => Some(&CIVIC_137_398B02BE), - (137, addr) if addr == address!("0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063") => Some(&DAI_STABLECOIN_137_39C6A063), - (137, addr) if addr == address!("0xbD7A5Cf51d22930B8B3Df6d834F9BCEf90EE7c4f") => Some(ÐEREUM_NAME_SERVICE_137_90EE7C4F), - (137, addr) if addr == address!("0x5FFD62D3C3eE2E81C00A7b9079FB248e7dF024A8") => Some(&GNOSIS_TOKEN_137_7DF024A8), - (137, addr) if addr == address!("0x5fe2B58c013d7601147DcdD68C143A77499f5531") => Some(&THE_GRAPH_137_499F5531), - (137, addr) if addr == address!("0x42f37A1296b2981F7C3cAcEd84c5096b2Eb0C72C") => Some(&KEEP_NETWORK_137_2EB0C72C), - (137, addr) if addr == address!("0x324b28d6565f784d596422B0F2E5aB6e9CFA1Dc7") => Some(&KYBER_NETWORK_CRYSTAL_137_9CFA1DC7), - (137, addr) if addr == address!("0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39") => Some(&CHAINLINK_TOKEN_137_3FABAD39), - (137, addr) if addr == address!("0x66EfB7cC647e0efab02eBA4316a2d2941193F6b3") => Some(&LOOM_NETWORK_137_1193F6B3), - (137, addr) if addr == address!("0x84e1670F61347CDaeD56dcc736FB990fBB47ddC1") => Some(&LOOPRINGCOIN_V2_137_BB47DDC1), - (137, addr) if addr == address!("0xA1c57f48F0Deb89f569dFbE6E2B7f46D33606fD4") => Some(&DECENTRALAND_137_33606FD4), - (137, addr) if addr == address!("0x0000000000000000000000000000000000001010") => Some(&POLYGON_137_00001010), - (137, addr) if addr == address!("0x6f7C932e7684666C9fd1d44527765433e01fF61d") => Some(&MAKER_137_E01FF61D), - (137, addr) if addr == address!("0x0Bf519071b02F22C17E7Ed5F4002ee1911f46729") => Some(&NUMERAIRE_137_11F46729), - (137, addr) if addr == address!("0x9880e3dDA13c8e7D4804691A45160102d31F6060") => Some(&ORCHID_137_D31F6060), - (137, addr) if addr == address!("0x19782D3Dc4701cEeeDcD90f0993f0A9126ed89d0") => Some(&REPUBLIC_TOKEN_137_26ED89D0), - (137, addr) if addr == address!("0x6563c1244820CfBd6Ca8820FBdf0f2847363F733") => Some(&REPUTATION_AUGUR_V2_137_7363F733), - (137, addr) if addr == address!("0x50B728D8D964fd00C2d0AAD81718b71311feF68a") => Some(&SYNTHETIX_NETWORK_TOKEN_137_11FEF68A), - (137, addr) if addr == address!("0xd72357dAcA2cF11A5F155b9FF7880E595A3F5792") => Some(&STORJ_TOKEN_137_5A3F5792), - (137, addr) if addr == address!("0xF81b4Bec6Ca8f9fe7bE01CA734F55B2b6e03A7a0") => Some(&SYNTH_SUSD_137_6E03A7A0), - (137, addr) if addr == address!("0x3066818837c5e6eD6601bd5a91B0762877A6B731") => Some(&UMA_VOTING_TOKEN_V1_137_77A6B731), - (137, addr) if addr == address!("0xb33EaAd8d922B1083446DC23f610c2567fB5180f") => Some(&UNISWAP_137_7FB5180F), - (137, addr) if addr == address!("0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359") => Some(&USDCOIN_137_3D5C3359), - (137, addr) if addr == address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174") => Some(&USDCOIN_POS), - (137, addr) if addr == address!("0xc2132D05D31c914a87C6611C10748AEb04B58e8F") => Some(&TETHER_USD_137_04B58E8F), - (137, addr) if addr == address!("0x8DE5B80a0C1B02Fe4976851D030B36122dbb8624") => Some(&VANAR_CHAIN), - (137, addr) if addr == address!("0xd0258a3fD00f38aa8090dfee343f10A9D4d30D3F") => Some(&VOXIES), - (137, addr) if addr == address!("0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6") => Some(&WRAPPED_BTC_137_47D9BFD6), - (137, addr) if addr == address!("0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619") => Some(&WRAPPED_ETHER_137_F1B9F619), - (137, addr) if addr == address!("0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270") => Some(&WRAPPED_MATIC), - (137, addr) if addr == address!("0xDC3326e71D45186F113a2F448984CA0e8D201995") => Some(&XSGD_137_8D201995), - (137, addr) if addr == address!("0xDA537104D6A5edd53c6fBba9A898708E465260b6") => Some(&YEARN_FINANCE_137_465260B6), - (137, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_137_F13271CD), - (137, addr) if addr == address!("0x5559Edb74751A0edE9DeA4DC23aeE72cCA6bE3D5") => Some(&TOKEN_0X_PROTOCOL_TOKEN_137_CA6BE3D5), - (143, addr) if addr == address!("0xea17E5a9efEBf1477dB45082d67010E2245217f1") => Some(&SOL_WORMHOLE_143_245217F1), - (143, addr) if addr == address!("0x754704Bc059F8C67012fEd69BC8A327a5aafb603") => Some(&USDCOIN_143_5AAFB603), - (143, addr) if addr == address!("0xe7cd86e13AC4309349F30B3435a9d337750fC82D") => Some(&TETHER_USD_143_750FC82D), - (143, addr) if addr == address!("0x0555E30da8f98308EdB960aa94C0Db47230d2B9c") => Some(&WRAPPED_BTC_143_230D2B9C), - (143, addr) if addr == address!("0xEE8c0E9f1BFFb4Eb878d8f15f368A02a35481242") => Some(&WRAPPED_ETHER_143_35481242), - (196, addr) if addr == address!("0x4ae46a509F6b1D9056937BA4500cb143933D2dc8") => Some(&GLOBAL_DOLLAR_196_933D2DC8), - (324, addr) if addr == address!("0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E") => Some(&ZKSYNC), - (480, addr) if addr == address!("0x79A02482A880bCE3F13e09Da970dC34db4CD24d1") => Some(&BRIDGED_USDC), - (480, addr) if addr == address!("0x03C7054BCB39f7b2e5B2c7AcB37583e32D70Cfa3") => Some(&WRAPPED_BTC_480_2D70CFA3), - (480, addr) if addr == address!("0x4200000000000000000000000000000000000006") => Some(&WRAPPED_ETHER_480_00000006), - (1868, addr) if addr == address!("0xbA9986D2381edf1DA03B0B9c1f8b00dc4AacC369") => Some(&USDCOIN_1868_4AACC369), - (1868, addr) if addr == address!("0x3A337a6adA9d885b6Ad95ec48F9b75f197b5AE35") => Some(&TETHER_USD_1868_97B5AE35), - (1868, addr) if addr == address!("0x4200000000000000000000000000000000000006") => Some(&WRAPPED_ETHER_1868_00000006), - (8453, addr) if addr == address!("0xc5fecC3a29Fb57B5024eEc8a2239d4621e111CBE") => Some(&TOKEN_1INCH_8453_1E111CBE), - (8453, addr) if addr == address!("0x63706e401c06ac8513145b7687A14804d17f814b") => Some(&AAVE_8453_D17F814B), - (8453, addr) if addr == address!("0xe2A8cCB00E328a0EC2204CB0c736309D7c1fa556") => Some(&ARCBLOCK_8453_7C1FA556), - (8453, addr) if addr == address!("0x3c87e7AF3cDBAe5bB56b4936325Ea95CA3E0EfD9") => Some(&AMBIRE_ADEX_8453_A3E0EFD9), - (8453, addr) if addr == address!("0x940181a94A35A4569E4529A3CDfB74e38FD98631") => Some(&AERODROME_FINANCE), - (8453, addr) if addr == address!("0x4F9Fd6Be4a90f2620860d680c0d4d5Fb53d1A825") => Some(&AIXBT_BY_VIRTUALS), - (8453, addr) if addr == address!("0x97c806e7665d3AFd84A8Fe1837921403D59F3Dcc") => Some(&ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_8453_D59F3DCC), - (8453, addr) if addr == address!("0x449B3317a6d1efb1Bc3ba0700C9EaA4FFFf4Ae65") => Some(&AUSTRALIAN_DIGITAL_DOLLAR), - (8453, addr) if addr == address!("0x696F9436B67233384889472Cd7cD58A6fB5DF4f1") => Some(&AVANTIS), - (8453, addr) if addr == address!("0x1B4617734C43F6159F3a70b7E06d883647512778") => Some(&AWE_NETWORK), - (8453, addr) if addr == address!("0xB3B32F9f8827D4634fE7d973Fa1034Ec9fdDB3B3") => Some(&B3), - (8453, addr) if addr == address!("0x2a06A17CBC6d0032Cac2c6696DA90f29D39a1a29") => Some(&HARRYPOTTEROBAMASONIC10INU_8453_D39A1A29), - (8453, addr) if addr == address!("0x22aF33FE49fD1Fa80c7149773dDe5890D3c76F3b") => Some(&BANKRCOIN), - (8453, addr) if addr == address!("0xcbADA732173e39521CDBE8bf59a6Dc85A9fc7b8c") => Some(&COINBASE_WRAPPED_ADA), - (8453, addr) if addr == address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf") => Some(&COINBASE_WRAPPED_BTC_8453_0EED33BF), - (8453, addr) if addr == address!("0xcbD06E5A2B0C65597161de254AA074E489dEb510") => Some(&COINBASE_WRAPPED_DOGE), - (8453, addr) if addr == address!("0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22") => Some(&COINBASE_WRAPPED_STAKED_ETH_8453_CF0DEC22), - (8453, addr) if addr == address!("0xcb17C9Db87B595717C857a08468793f5bAb6445F") => Some(&COINBASE_WRAPPED_LTC), - (8453, addr) if addr == address!("0xcb585250f852C6c6bf90434AB21A00f02833a4af") => Some(&COINBASE_WRAPPED_XRP), - (8453, addr) if addr == address!("0x1bc0c42215582d5A085795f4baDbaC3ff36d1Bcb") => Some(&TOKENBOT), - (8453, addr) if addr == address!("0x9e1028F5F1D5eDE59748FFceE5532509976840E0") => Some(&COMPOUND_8453_976840E0), - (8453, addr) if addr == address!("0xC0041EF357B183448B235a8Ea73Ce4E4eC8c265F") => Some(&COOKIE), - (8453, addr) if addr == address!("0x8Ee73c484A26e0A5df2Ee2a4960B789967dd0415") => Some(&CURVE_DAO_TOKEN_8453_67DD0415), - (8453, addr) if addr == address!("0x259Fac10c5CbFEFE3E710e1D9467f70a76138d45") => Some(&CARTESI_8453_76138D45), - (8453, addr) if addr == address!("0xBB22Ff867F8Ca3D5F2251B4084F6Ec86D4666E14") => Some(&CRYPTEX_FINANCE_8453_D4666E14), - (8453, addr) if addr == address!("0xB1E1f3Cc2B6fE4420C1Ac82022b457018Eb628ff") => Some(&COVALENT_X_TOKEN_8453_8EB628FF), - (8453, addr) if addr == address!("0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb") => Some(&DAI_STABLECOIN_8453_917DB0CB), - (8453, addr) if addr == address!("0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed") => Some(&DEGEN), - (8453, addr) if addr == address!("0x6921B130D297cc43754afba22e5EAc0FBf8Db75b") => Some(&DOGINME), - (8453, addr) if addr == address!("0xB38266e0e9D9681b77aEB0A280E98131b953F865") => Some(&DOVU_8453_B953F865), - (8453, addr) if addr == address!("0x9d0E8f5b25384C7310CB8C6aE32C8fbeb645d083") => Some(&DERIVE_8453_B645D083), - (8453, addr) if addr == address!("0xED6E000dEF95780fb89734c07EE2ce9F6dcAf110") => Some(&DEFINITIVE), - (8453, addr) if addr == address!("0x29cC30f9D113B356Ce408667aa6433589CeCBDcA") => Some(&ELSA), - (8453, addr) if addr == address!("0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42") => Some(&EURC), - (8453, addr) if addr == address!("0xb33Ff54b9F7242EF1593d2C9Bcd8f9df46c77935") => Some(&FAI), - (8453, addr) if addr == address!("0x5aB3D4c385B400F3aBB49e80DE2fAF6a88A7B691") => Some(&FLOCK), - (8453, addr) if addr == address!("0x61E030A56D33e8260FdD81f03B162A79Fe3449Cd") => Some(&FLUID), - (8453, addr) if addr == address!("0x16EE7ecAc70d1028E7712751E2Ee6BA808a7dd92") => Some(&SPORT_FUN), - (8453, addr) if addr == address!("0x4BfAa776991E85e5f8b1255461cbbd216cFc714f") => Some(&HOME), - (8453, addr) if addr == address!("0xC9d23ED2ADB0f551369946BD377f8644cE1ca5c4") => Some(&HYPERLANE), - (8453, addr) if addr == address!("0xBCBAf311ceC8a4EAC0430193A528d9FF27ae38C1") => Some(&IOTEX_8453_27AE38C1), - (8453, addr) if addr == address!("0xFf9957816c813C5Ad0b9881A8990Df1E3AA2a057") => Some(&GEOJAM_8453_3AA2A057), - (8453, addr) if addr == address!("0x98d0baa52b2D063E780DE12F615f963Fe8537553") => Some(&KAITO), - (8453, addr) if addr == address!("0x9a26F5433671751C3276a065f57e5a02D2817973") => Some(&KEYBOARD_CAT), - (8453, addr) if addr == address!("0xDAE49C25fAd3a62a8e8bFB6dA12c46bE611f9f7a") => Some(&KRYLL_8453_611F9F7A), - (8453, addr) if addr == address!("0xc0634090F2Fe6c6d75e61Be2b949464aBB498973") => Some(&KEETA), - (8453, addr) if addr == address!("0xd7468c14ae76C3Fc308aEAdC223D5D1F71d3c171") => Some(&LCX_8453_71D3C171), - (8453, addr) if addr == address!("0x5259384690aCF240e9b0A8811bD0FFbFBDdc125C") => Some(&LIQUITY_8453_BDDC125C), - (8453, addr) if addr == address!("0x7300B37DfdfAb110d83290A29DfB31B1740219fE") => Some(&MAMO), - (8453, addr) if addr == address!("0x9Cb41FD9dC6891BAe8187029461bfAADF6CC0C69") => Some(&NOICE), - (8453, addr) if addr == address!("0xca73ed1815e5915489570014e024b7EbE65dE679") => Some(&ODOS_TOKEN), - (8453, addr) if addr == address!("0xA99F6e6785Da0F5d6fB42495Fe424BCE029Eeb3E") => Some(&PENDLE_8453_029EEB3E), - (8453, addr) if addr == address!("0xB4fDe59a779991bfB6a52253B51947828b982be3") => Some(&PEPE_8453_8B982BE3), - (8453, addr) if addr == address!("0xCD6dDDa305955AcD6b94b934f057E8b0daaD58dE") => Some(&PERPETUAL_PROTOCOL_8453_DAAD58DE), - (8453, addr) if addr == address!("0xfA980cEd6895AC314E7dE34Ef1bFAE90a5AdD21b") => Some(&PRIME_8453_A5ADD21B), - (8453, addr) if addr == address!("0x18dD5B087bCA9920562aFf7A0199b96B9230438b") => Some(&PROPY_8453_9230438B), - (8453, addr) if addr == address!("0x30c7235866872213F68cb1F08c37Cb9eCCB93452") => Some(&PROMPT), - (8453, addr) if addr == address!("0x1aA8fD5BCce2231C6100d55Bf8B377cff33Acfc3") => Some(&RAVEDAO), - (8453, addr) if addr == address!("0x1f16e03C1a5908818F47f6EE7bB16690b40D0671") => Some(&RECALL_NETWORK), - (8453, addr) if addr == address!("0xa53887F7e7c1bf5010b8627F1C1ba94fE7a5d6E0") => Some(&RAINBOW), - (8453, addr) if addr == address!("0xFbB75A59193A3525a8825BeBe7D4b56899E2f7e1") => Some(&RESEARCHCOIN), - (8453, addr) if addr == address!("0xaB36452DbAC151bE02b16Ca17d8919826072f64a") => Some(&RESERVE_RIGHTS_8453_6072F64A), - (8453, addr) if addr == address!("0xC729777d0470F30612B1564Fd96E8Dd26f5814E3") => Some(&SAPIEN), - (8453, addr) if addr == address!("0x1C7a460413dD4e964f96D8dFC56E7223cE88CD85") => Some(&SEAMLESSS), - (8453, addr) if addr == address!("0x662015EC830DF08C0FC45896FaB726542e8AC09E") => Some(&STATUS_8453_2E8AC09E), - (8453, addr) if addr == address!("0x22e6966B799c4D5B13BE962E1D117b56327FDa66") => Some(&SYNTHETIX_NETWORK_TOKEN_8453_327FDA66), - (8453, addr) if addr == address!("0x50dA645f148798F68EF2d7dB7C1CB22A6819bb2C") => Some(&SPX6900_8453_6819BB2C), - (8453, addr) if addr == address!("0xa69f80524381275A7fFdb3AE01c54150644c8792") => Some(&SUPERFLUID_TOKEN), - (8453, addr) if addr == address!("0x7D49a065D17d6d4a55dc13649901fdBB98B2AFBA") => Some(&SUSHI_8453_98B2AFBA), - (8453, addr) if addr == address!("0x11dC28D01984079b7efE7763b533e6ed9E3722B9") => Some(&SYNDICATE), - (8453, addr) if addr == address!("0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b") => Some(&TBTC_8453_22AB794B), - (8453, addr) if addr == address!("0xAC1Bd2486aAf3B5C0fc3Fd868558b082a531B2B4") => Some(&TOSHI), - (8453, addr) if addr == address!("0x00000000A22C618fd6b4D7E9A335C4B96B189a38") => Some(&TOWNS), - (8453, addr) if addr == address!("0x6cd905dF2Ed214b22e0d48FF17CD4200C1C6d8A3") => Some(&INTUITION), - (8453, addr) if addr == address!("0xc3De830EA07524a0761646a6a4e4be0e114a3C83") => Some(&UNISWAP_8453_114A3C83), - (8453, addr) if addr == address!("0x5b2193fDc451C1f847bE09CA9d13A4Bf60f8c86B") => Some(&SUPERFORM), - (8453, addr) if addr == address!("0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA") => Some(&USD_BASE_COIN), - (8453, addr) if addr == address!("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913") => Some(&USD_COIN), - (8453, addr) if addr == address!("0xacfE6019Ed1A7Dc6f7B508C02d1b04ec88cC21bf") => Some(&VENICE_TOKEN), - (8453, addr) if addr == address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945") => Some(&WALLETCONNECT_TOKEN_8453_DD927945), - (8453, addr) if addr == address!("0xA88594D404727625A9437C3f886C7643872296AE") => Some(&MOONWELL), - (8453, addr) if addr == address!("0x4200000000000000000000000000000000000006") => Some(&WRAPPED_ETHER_8453_00000006), - (8453, addr) if addr == address!("0x3e31966d4f81C72D2a55310A6365A56A4393E98D") => Some(&WORLD_MOBILE_TOKEN), - (8453, addr) if addr == address!("0xD7B99ffB8B2afc6fe013a17207cbe50f223aDc94") => Some(&XYO_NETWORK_8453_223ADC94), - (8453, addr) if addr == address!("0x9EaF8C1E34F05a589EDa6BAfdF391Cf6Ad3CB239") => Some(&YEARN_FINANCE_8453_AD3CB239), - (8453, addr) if addr == address!("0xaAC78d1219c08AecC8e37e03858FE885f5EF1799") => Some(&YIELD_GUILD_GAMES_8453_F5EF1799), - (8453, addr) if addr == address!("0xf43eB8De897Fbc7F2502483B2Bef7Bb9EA179229") => Some(&HORIZEN), - (8453, addr) if addr == address!("0xAA61bB7777bD01B684347961918f1E07fBbCe7CF") => Some(&BOUNDLESS_8453_FBBCE7CF), - (8453, addr) if addr == address!("0x1111111111166b7FE7bd91427724B487980aFc69") => Some(&ZORA), - (8453, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_8453_F13271CD), - (8453, addr) if addr == address!("0x3bB4445D30AC020a84c1b5A8A2C6248ebC9779D0") => Some(&TOKEN_0X_PROTOCOL_TOKEN_8453_BC9779D0), - (42161, addr) if addr == address!("0x6314C31A7a1652cE482cffe247E9CB7c3f4BB9aF") => Some(&TOKEN_1INCH_42161_3F4BB9AF), - (42161, addr) if addr == address!("0xba5DdD1f9d7F570dc94a51479a000E3BCE967196") => Some(&AAVE_42161_CE967196), - (42161, addr) if addr == address!("0x53691596d1BCe8CEa565b84d4915e69e03d9C99d") => Some(&ACROSS_PROTOCOL_TOKEN_42161_03D9C99D), - (42161, addr) if addr == address!("0x377c1Fc73D4D0f5600cd943776CED07c2B9783cd") => Some(&AEVO_42161_2B9783CD), - (42161, addr) if addr == address!("0xFA5Ed56A203466CbBC2430a43c66b9D8723528E7") => Some(&AGEUR_42161_723528E7), - (42161, addr) if addr == address!("0xb7910E8b16e63EFD51d5D1a093d56280012A3B9C") => Some(&ADVENTURE_GOLD_42161_012A3B9C), - (42161, addr) if addr == address!("0xeC76E8fe6e2242e6c2117caA244B9e2DE1569923") => Some(&AIOZ_NETWORK_42161_E1569923), - (42161, addr) if addr == address!("0xe7dcD50836d0A28c959c72D72122fEDB8E245A6C") => Some(&ALEPH_IM_42161_8E245A6C), - (42161, addr) if addr == address!("0xeF6124368c0B56556667e0de77eA008DfC0a71d1") => Some(&ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_42161_FC0A71D1), - (42161, addr) if addr == address!("0xC9CBf102c73fb77Ec14f8B4C8bd88e050a6b2646") => Some(&ALPHA_VENTURE_DAO_42161_0A6B2646), - (42161, addr) if addr == address!("0x1bfc5d35bf0f7B9e15dc24c78b8C02dbC1e95447") => Some(&ANKR_42161_C1E95447), - (42161, addr) if addr == address!("0x74885b4D524d497261259B38900f54e6dbAd2210") => Some(&APECOIN_42161_DBAD2210), - (42161, addr) if addr == address!("0xF01dB12F50D0CDF5Fe360ae005b9c52F92CA7811") => Some(&API3_42161_92CA7811), - (42161, addr) if addr == address!("0x912CE59144191C1204E64559FE8253a0e49E6548") => Some(&ARBITRUM_42161_E49E6548), - (42161, addr) if addr == address!("0xDac5094B7D59647626444a4F905060FCda4E656E") => Some(&ARKHAM_42161_DA4E656E), - (42161, addr) if addr == address!("0xAC9Ac2C17cdFED4AbC80A53c5553388575714d03") => Some(&AUTOMATA_42161_75714D03), - (42161, addr) if addr == address!("0xc7dEf82Ba77BAF30BbBc9b6162DC075b49092fb4") => Some(&AETHIR_TOKEN_42161_49092FB4), - (42161, addr) if addr == address!("0x23ee2343B892b1BB63503a4FAbc840E0e2C6810f") => Some(&AXELAR_42161_E2C6810F), - (42161, addr) if addr == address!("0xe88998Fb579266628aF6a03e3821d5983e5D0089") => Some(&AXIE_INFINITY_42161_3E5D0089), - (42161, addr) if addr == address!("0xBfa641051Ba0a0Ad1b0AcF549a89536A0D76472E") => Some(&BADGER_DAO_42161_0D76472E), - (42161, addr) if addr == address!("0x040d1EdC9569d4Bab2D15287Dc5A4F10F56a56B8") => Some(&BALANCER_42161_F56A56B8), - (42161, addr) if addr == address!("0x3450687EF141dCd6110b77c2DC44B008616AeE75") => Some(&BASIC_ATTENTION_TOKEN_42161_616AEE75), - (42161, addr) if addr == address!("0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d") => Some(&BICONOMY_42161_60A8E74D), - (42161, addr) if addr == address!("0x406C8dB506653D882295875F633bEC0bEb921C2A") => Some(&BITDAO_42161_EB921C2A), - (42161, addr) if addr == address!("0xf7e17BA61973bcDB61f471eFb989E47d13bD565D") => Some(&HARRYPOTTEROBAMASONIC10INU_42161_13BD565D), - (42161, addr) if addr == address!("0xEf171a5BA71348eff16616fd692855c2Fe606EB2") => Some(&BLUR_42161_FE606EB2), - (42161, addr) if addr == address!("0x7A24159672b83ED1b89467c9d6A99556bA06D073") => Some(&BANCOR_NETWORK_TOKEN_42161_BA06D073), - (42161, addr) if addr == address!("0x0D81E50bC677fa67341c44D7eaA9228DEE64A4e1") => Some(&BARNBRIDGE_42161_EE64A4E1), - (42161, addr) if addr == address!("0x31190254504622cEFdFA55a7d3d272e6462629a2") => Some(&BINANCE_USD_42161_462629A2), - (42161, addr) if addr == address!("0xCdc343ebf71e38F003eD6c80171F5B8D7cF58860") => Some(&PANCAKESWAP_42161_7CF58860), - (42161, addr) if addr == address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf") => Some(&COINBASE_WRAPPED_BTC_42161_0EED33BF), - (42161, addr) if addr == address!("0x1DEBd73E752bEaF79865Fd6446b0c970EaE7732f") => Some(&COINBASE_WRAPPED_STAKED_ETH_42161_EAE7732F), - (42161, addr) if addr == address!("0x4E51aC49bC5e2d87e0EF713E9e5AB2D71EF4F336") => Some(&CELO_NATIVE_ASSET_WORMHOLE_42161_1EF4F336), - (42161, addr) if addr == address!("0x3a8B787f78D775AECFEEa15706D4221B40F345AB") => Some(&CELER_NETWORK_42161_40F345AB), - (42161, addr) if addr == address!("0x354A6dA3fcde098F8389cad84b0182725c6C91dE") => Some(&COMPOUND_42161_5C6C91DE), - (42161, addr) if addr == address!("0x6FE14d3CC2f7bDdffBa5CdB3BBE7467dd81ea101") => Some(&COTI_42161_D81EA101), - (42161, addr) if addr == address!("0xcb8b5CD20BdCaea9a010aC1F8d835824F5C87A04") => Some(&COW_PROTOCOL_42161_F5C87A04), - (42161, addr) if addr == address!("0x69b937dB799a9BECC9E8A6F0a5d36eA3657273bf") => Some(&COVALENT_42161_657273BF), - (42161, addr) if addr == address!("0x8ea3156f834A0dfC78F1A5304fAC2CdA676F354C") => Some(&CRONOS_42161_676F354C), - (42161, addr) if addr == address!("0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978") => Some(&CURVE_DAO_TOKEN_42161_FA034978), - (42161, addr) if addr == address!("0x319f865b287fCC10b30d8cE6144e8b6D1b476999") => Some(&CARTESI_42161_1B476999), - (42161, addr) if addr == address!("0x84F5c2cFba754E76DD5aE4fB369CfC920425E12b") => Some(&CRYPTEX_FINANCE_42161_0425E12B), - (42161, addr) if addr == address!("0x9DfFB23CAd3322440bCcFF7aB1C58E781dDBF144") => Some(&CIVIC_42161_1DDBF144), - (42161, addr) if addr == address!("0xaAFcFD42c9954C6689ef1901e03db742520829c5") => Some(&CONVEX_FINANCE_42161_520829C5), - (42161, addr) if addr == address!("0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1") => Some(&DAI_STABLECOIN_42161_C9000DA1), - (42161, addr) if addr == address!("0x3Be7cB2e9413Ef8F42b4A202a0114EB59b64e227") => Some(&DEXTOOLS_42161_9B64E227), - (42161, addr) if addr == address!("0xca642467C6Ebe58c13cB4A7091317f34E17ac05e") => Some(&DIA_42161_E17AC05E), - (42161, addr) if addr == address!("0xE3696a02b2C9557639E29d829E9C45EFa49aD47A") => Some(&DISTRICT0X_42161_A49AD47A), - (42161, addr) if addr == address!("0x4667cf53C4eDF659E402B733BEA42B18B68dd74c") => Some(&DEFI_PULSE_INDEX_42161_B68DD74C), - (42161, addr) if addr == address!("0x77b7787a09818502305C95d68A2571F090abb135") => Some(&DERIVE_42161_90ABB135), - (42161, addr) if addr == address!("0x51863cB90Ce5d6dA9663106F292fA27c8CC90c5a") => Some(&DYDX_42161_8CC90C5A), - (42161, addr) if addr == address!("0x606C3e5075e5555e79Aa15F1E9FACB776F96C248") => Some(&EIGENLAYER_42161_6F96C248), - (42161, addr) if addr == address!("0x3e4Cff6E50F37F731284A92d44AE943e17077fD4") => Some(&DOGELON_MARS_42161_17077FD4), - (42161, addr) if addr == address!("0xdf8F0c63D9335A0AbD89F9F752d293A98EA977d8") => Some(ÐENA_42161_8EA977D8), - (42161, addr) if addr == address!("0x7fa9549791EFc9030e1Ed3F25D18014163806758") => Some(&ENJIN_COIN_42161_63806758), - (42161, addr) if addr == address!("0xfeA31d704DEb0975dA8e77Bf13E04239e70d7c28") => Some(ÐEREUM_NAME_SERVICE_42161_E70D7C28), - (42161, addr) if addr == address!("0x2354c8e9Ea898c751F1A15Addeb048714D667f96") => Some(ÐERNITY_CHAIN_42161_4D667F96), - (42161, addr) if addr == address!("0x3b8db18e69d6686Ad9371A423aFe3Dd1065C94f1") => Some(&ESPRESSO_42161_065C94F1), - (42161, addr) if addr == address!("0x07D65C18CECbA423298c0aEB5d2BeDED4DFd5736") => Some(ÐER_FI_42161_4DFD5736), - (42161, addr) if addr == address!("0x863708032B5c328e11aBcbC0DF9D79C71Fc52a48") => Some(&EURO_COIN_42161_1FC52A48), - (42161, addr) if addr == address!("0x8553d254Cb6934b16F87D2e486b64BbD24C83C70") => Some(&HARVEST_FINANCE_42161_24C83C70), - (42161, addr) if addr == address!("0x4BE87C766A7CE11D5Cc864b6C3Abb7457dCC4cC9") => Some(&FETCH_AI_42161_7DCC4CC9), - (42161, addr) if addr == address!("0x849B40AB2469309117Ed1038c5A99894767C7282") => Some(&STAFI_42161_767C7282), - (42161, addr) if addr == address!("0xA8C25FdC09763A176353CC6a76882e05b4905FAe") => Some(&FLOKI_42161_B4905FAE), - (42161, addr) if addr == address!("0x63806C056Fa458c548Fb416B15E358A9D685710A") => Some(&FLUX_42161_D685710A), - (42161, addr) if addr == address!("0x3A1429d50E0cBBc45c997aF600541Fe1cc3D2923") => Some(&FORTA_42161_CC3D2923), - (42161, addr) if addr == address!("0xf929de51D91C77E42f5090069E0AD7A09e513c73") => Some(&SHAPESHIFT_FOX_TOKEN_42161_9E513C73), - (42161, addr) if addr == address!("0x7468a5d8E02245B00E8C0217fCE021C70Bc51305") => Some(&FRAX_42161_0BC51305), - (42161, addr) if addr == address!("0xd42785D323e608B9E99fa542bd8b1000D4c2Df37") => Some(&FANTOM_42161_D4C2DF37), - (42161, addr) if addr == address!("0xd9f9d2Ee2d3EFE420699079f16D9e924affFdEA4") => Some(&FRAX_SHARE_42161_AFFFDEA4), - (42161, addr) if addr == address!("0xc27E7325a6BEA1FcC06de7941473f5279bfd1182") => Some(&GALXE_42161_9BFD1182), - (42161, addr) if addr == address!("0x2A676eeAd159c4C8e8593471c6d666F02827FF8C") => Some(&GALA_42161_2827FF8C), - (42161, addr) if addr == address!("0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a") => Some(&GMX), - (42161, addr) if addr == address!("0xa0b862F60edEf4452F25B4160F177db44DeB6Cf1") => Some(&GNOSIS_TOKEN_42161_4DEB6CF1), - (42161, addr) if addr == address!("0x9623063377AD1B27544C965cCd7342f7EA7e88C7") => Some(&THE_GRAPH_42161_EA7E88C7), - (42161, addr) if addr == address!("0x7f9a7DB853Ca816B9A138AEe3380Ef34c437dEe0") => Some(&GITCOIN_42161_C437DEE0), - (42161, addr) if addr == address!("0x589d35656641d6aB57A545F08cf473eCD9B6D5F7") => Some(&GYEN_42161_D9B6D5F7), - (42161, addr) if addr == address!("0xd12Eeb0142D4Efe7Af82e4f29E5Af382615bcEeA") => Some(&HIGHSTREET_42161_615BCEEA), - (42161, addr) if addr == address!("0x177F394A3eD18FAa85c1462Ae626438a70294EF7") => Some(&HOPR_42161_70294EF7), - (42161, addr) if addr == address!("0x68731d6F14B827bBCfFbEBb62b19Daa18de1d79c") => Some(&IDOS_TOKEN), - (42161, addr) if addr == address!("0x61cA9D186f6b9a793BC08F6C79fd35f205488673") => Some(&ILLUVIUM_42161_05488673), - (42161, addr) if addr == address!("0x3cFD99593a7F035F717142095a3898e3Fca7783e") => Some(&IMMUTABLE_X_42161_FCA7783E), - (42161, addr) if addr == address!("0x2A2053cb633CAD465B4A8975eD3d7f09DF608F80") => Some(&INJECTIVE_42161_DF608F80), - (42161, addr) if addr == address!("0x25f05699548D3A0820b99f93c10c8BB573E27083") => Some(&JASMYCOIN_42161_73E27083), - (42161, addr) if addr == address!("0x010700AB046Dd8e92b0e3587842080Df36364ed3") => Some(&KINTO), - (42161, addr) if addr == address!("0xf75eE6D319741057a82a88Eeff1DbAFAB7307b69") => Some(&KRYLL_42161_B7307B69), - (42161, addr) if addr == address!("0x3A18dcC9745eDcD1Ef33ecB93b0b6eBA5671e7Ca") => Some(&KUJIRA_42161_5671E7CA), - (42161, addr) if addr == address!("0x13Ad51ed4F1B7e9Dc168d8a00cB3f4dDD85EfA60") => Some(&LIDO_DAO_42161_D85EFA60), - (42161, addr) if addr == address!("0xf97f4df75117a78c1A5a0DBb814Af92458539FB4") => Some(&CHAINLINK_TOKEN_42161_58539FB4), - (42161, addr) if addr == address!("0x349fc93da004a63F3B1343361465981330A40B25") => Some(&LITENTRY_42161_30A40B25), - (42161, addr) if addr == address!("0x289ba1701C2F088cf0faf8B3705246331cB8A839") => Some(&LIVEPEER_42161_1CB8A839), - (42161, addr) if addr == address!("0xfb9E5D956D889D91a82737B9bFCDaC1DCE3e1449") => Some(&LIQUITY_42161_CE3E1449), - (42161, addr) if addr == address!("0x46d0cE7de6247b0A95f67b43B589b4041BaE7fbE") => Some(&LOOPRINGCOIN_V2_42161_1BAE7FBE), - (42161, addr) if addr == address!("0x93b346b6BC2548dA6A1E7d98E9a421B42541425b") => Some(&LIQUITY_USD_42161_2541425B), - (42161, addr) if addr == address!("0x539bdE0d7Dbd336b79148AA742883198BBF60342") => Some(&MAGIC), - (42161, addr) if addr == address!("0x442d24578A564EF628A65e6a7E3e7be2a165E231") => Some(&DECENTRALAND_42161_A165E231), - (42161, addr) if addr == address!("0x533A7B414CD1236815a5e09F1E97FC7d5c313739") => Some(&MASK_NETWORK_42161_5C313739), - (42161, addr) if addr == address!("0x99F40b01BA9C469193B360f72740E416B17Ac332") => Some(&MATH_42161_B17AC332), - (42161, addr) if addr == address!("0x561877b6b3DD7651313794e5F2894B2F18bE0766") => Some(&POLYGON_42161_18BE0766), - (42161, addr) if addr == address!("0x7F728F3595db17B0B359f4FC47aE80FAd2e33769") => Some(&METIS_42161_D2E33769), - (42161, addr) if addr == address!("0xB20A02dfFb172C474BC4bDa3fD6f4eE70C04daf2") => Some(&MAGIC_INTERNET_MONEY_42161_0C04DAF2), - (42161, addr) if addr == address!("0x2e9a6Df78E42a30712c10a9Dc4b1C8656f8F2879") => Some(&MAKER_42161_6F8F2879), - (42161, addr) if addr == address!("0x8f5c1A99b1df736Ad685006Cb6ADCA7B7Ae4b514") => Some(&MELON_42161_7AE4B514), - (42161, addr) if addr == address!("0x9c1a1C7bA9c2602123FD7EF3eb41a769edf6C53A") => Some(&MANTLE_42161_EDF6C53A), - (42161, addr) if addr == address!("0x96c42662820F6Ea32f0A61A06a38a72B206aABaC") => Some(&MOG_COIN_42161_206AABAC), - (42161, addr) if addr == address!("0xE390C0B46bd723995BE02640E6F1e1c802F620AC") => Some(&MORPHO_TOKEN_42161_02F620AC), - (42161, addr) if addr == address!("0x29024832eC3baBF5074D4F46102aA988097f0Ca0") => Some(&MAPLE_42161_097F0CA0), - (42161, addr) if addr == address!("0x7b9b94aebe5E2039531af8E31045f377EcD9A39A") => Some(&MULTICHAIN_42161_ECD9A39A), - (42161, addr) if addr == address!("0x5445972E76c5e4CEdD12B6e2BceF69133E15992F") => Some(&GENSOKISHI_METAVERSE_42161_3E15992F), - (42161, addr) if addr == address!("0x91b468Fe3dce581D7a6cFE34189F1314b6862eD6") => Some(&MXC_42161_B6862ED6), - (42161, addr) if addr == address!("0x53236015A675fcB937485F1AE58040e4Fb920d5b") => Some(&POLYSWARM_42161_FB920D5B), - (42161, addr) if addr == address!("0xBE06ca305A5Cb49ABf6B1840da7c42690406177b") => Some(&NKN_42161_0406177B), - (42161, addr) if addr == address!("0x597701b32553b9fa473e21362D480b3a6B569711") => Some(&NUMERAIRE_42161_6B569711), - (42161, addr) if addr == address!("0x933d31561e470478079FEB9A6Dd2691fAD8234DF") => Some(&OCEAN_PROTOCOL_42161_AD8234DF), - (42161, addr) if addr == address!("0x6FEb262FEb0f775B5312D2e009923f7f58AE423E") => Some(&ORIGIN_PROTOCOL_42161_58AE423E), - (42161, addr) if addr == address!("0xd962C1895c46AC0378C502c207748b7061421e8e") => Some(&OMG_NETWORK_42161_61421E8E), - (42161, addr) if addr == address!("0xA2d52A05B8Bead5d824DF54Dd1AA63188B37A5E7") => Some(&ONDO_FINANCE_42161_8B37A5E7), - (42161, addr) if addr == address!("0x1BDCC2075d5370293E248Cab0173eC3E551e6218") => Some(&ORION_PROTOCOL_42161_551E6218), - (42161, addr) if addr == address!("0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8") => Some(&PENDLE_42161_B9A8C9E8), - (42161, addr) if addr == address!("0x35E6A59F786d9266c7961eA28c7b768B33959cbB") => Some(&PEPE_42161_33959CBB), - (42161, addr) if addr == address!("0x753D224bCf9AAFaCD81558c32341416df61D3DAC") => Some(&PERPETUAL_PROTOCOL_42161_F61D3DAC), - (42161, addr) if addr == address!("0xac7CE9F2794e01c0D27b096C52f592e343D77cbf") => Some(&PIRATE_NATION_42161_43D77CBF), - (42161, addr) if addr == address!("0x73efDC761596328461B68E5FC58c3284CB15ba13") => Some(&PLUME_42161_CB15BA13), - (42161, addr) if addr == address!("0x044d8e7F3A17751D521efEa8CCf9282268fE08CC") => Some(&POLYGON_ECOSYSTEM_TOKEN_42161_68FE08CC), - (42161, addr) if addr == address!("0xeeeB5EaC2dB7A7Fc28134aA3248580d48b016b64") => Some(&POLKASTARTER_42161_8B016B64), - (42161, addr) if addr == address!("0xE12F29704F635F4A6E7Ae154838d21F9B33809e9") => Some(&POLYMATH_42161_B33809E9), - (42161, addr) if addr == address!("0xdA0a57B710768ae17941a9Fa33f8B720c8bD9ddD") => Some(&MARLIN_42161_C8BD9DDD), - (42161, addr) if addr == address!("0x6380F3d0C1412a80EB00F49064DA30749DB991DE") => Some(&PORTAL_42161_9DB991DE), - (42161, addr) if addr == address!("0x4e91F2AF1ee0F84B529478f19794F5AFD423e4A6") => Some(&POWER_LEDGER_42161_D423E4A6), - (42161, addr) if addr == address!("0x8d8e1b6ffc6832E8D2eF0DE8a3d957cAE7ac5067") => Some(&PRIME_42161_E7AC5067), - (42161, addr) if addr == address!("0x82164a8B646401a8776F9dC5c8Cba35DcAf60Cd2") => Some(&PARSIQ_42161_CAF60CD2), - (42161, addr) if addr == address!("0x327006c8712FE0AbdbbD55B7999DB39b0967342E") => Some(&PAYPAL_USD_42161_0967342E), - (42161, addr) if addr == address!("0xC7557C73e0eCa2E1BF7348bB6874Aee63C7eFF85") => Some(&QUANT_42161_3C7EFF85), - (42161, addr) if addr == address!("0x3c45038f4807c5bb72F6BC72c2A2B9c012155e49") => Some(&RADICLE_42161_12155E49), - (42161, addr) if addr == address!("0xaeF5bbcbFa438519a5ea80B4c7181B4E78d419f2") => Some(&RAI_REFLEX_INDEX_42161_78D419F2), - (42161, addr) if addr == address!("0xCf78572A8fE97b2B9a4B9709f6a7D9a863c1b8E0") => Some(&RARIBLE_42161_63C1B8E0), - (42161, addr) if addr == address!("0x2E9AE8f178d5Ea81970C7799A377B3985cbC335F") => Some(&RUBIC_42161_5CBC335F), - (42161, addr) if addr == address!("0x9fA891e1dB0a6D1eEAC4B929b5AAE1011C79a204") => Some(&REPUBLIC_TOKEN_42161_1C79A204), - (42161, addr) if addr == address!("0x1Cb5bBc64e148C5b889E3c667B49edF78BB92171") => Some(&REQUEST_42161_8BB92171), - (42161, addr) if addr == address!("0xef888bcA6AB6B1d26dbeC977C455388ecd794794") => Some(&RARI_GOVERNANCE_TOKEN_42161_CD794794), - (42161, addr) if addr == address!("0xE575586566b02A16338c199c23cA6d295D794e66") => Some(&IEXEC_RLC_42161_5D794E66), - (42161, addr) if addr == address!("0xC8a4EeA31E9B6b61c406DF013DD4FEc76f21E279") => Some(&RENDER_TOKEN_42161_6F21E279), - (42161, addr) if addr == address!("0xB766039cc6DB368759C1E56B79AFfE831d0Cc507") => Some(&ROCKET_POOL_PROTOCOL_42161_1D0CC507), - (42161, addr) if addr == address!("0xCa5Ca9083702c56b481D1eec86F1776FDbd2e594") => Some(&RESERVE_RIGHTS_42161_DBD2E594), - (42161, addr) if addr == address!("0xd1318eb19DBF2647743c720ed35174efd64e3DAC") => Some(&THE_SANDBOX_42161_D64E3DAC), - (42161, addr) if addr == address!("0x1629c4112952a7a377cB9B8d7d8c903092f34B63") => Some(&STADER_42161_92F34B63), - (42161, addr) if addr == address!("0x5033833c9fe8B9d3E09EEd2f73d2aaF7E3872fd1") => Some(&SHIBA_INU_42161_E3872FD1), - (42161, addr) if addr == address!("0x4F9b7DEDD8865871dF65c5D26B1c2dD537267878") => Some(&SKALE_42161_37267878), - (42161, addr) if addr == address!("0x707F635951193dDaFBB40971a0fCAAb8A6415160") => Some(&STATUS_42161_A6415160), - (42161, addr) if addr == address!("0xcBA56Cd8216FCBBF3fA6DF6137F3147cBcA37D60") => Some(&SYNTHETIX_NETWORK_TOKEN_42161_BCA37D60), - (42161, addr) if addr == address!("0xb2BE52744a804Cc732d606817C2572C5A3B264e7") => Some(&UNISOCKS_42161_A3B264E7), - (42161, addr) if addr == address!("0xb74Da9FE2F96B9E0a5f4A3cf0b92dd2bEC617124") => Some(&SOL_WORMHOLE_42161_EC617124), - (42161, addr) if addr == address!("0x3E6648C5a70A150A88bCE65F4aD4d506Fe15d2AF") => Some(&SPELL_TOKEN_42161_FE15D2AF), - (42161, addr) if addr == address!("0x53e70cc1d527b524A1C46Eaa892e4CB35d2ba901") => Some(&SPX6900_42161_5D2BA901), - (42161, addr) if addr == address!("0x1337420dED5ADb9980CFc35f8f2B054ea86f8aB1") => Some(&SQD), - (42161, addr) if addr == address!("0xe018C7a3d175Fb0fE15D70Da2c874d3CA16313EC") => Some(&STARGATE_FINANCE_42161_A16313EC), - (42161, addr) if addr == address!("0xE6320ebF209971b4F4696F7f0954b8457Aa2FCC2") => Some(&STORJ_TOKEN_42161_7AA2FCC2), - (42161, addr) if addr == address!("0x7f9cf5a2630a0d58567122217dF7609c26498956") => Some(&SUPERFARM_42161_26498956), - (42161, addr) if addr == address!("0xA970AF1a584579B618be4d69aD6F73459D112F95") => Some(&SYNTH_SUSD_42161_9D112F95), - (42161, addr) if addr == address!("0xd4d42F0b6DEF4CE0383636770eF773390d85c61A") => Some(&SUSHI_42161_0D85C61A), - (42161, addr) if addr == address!("0x2C96bE2612bec20fe2975C3ACFcbBe61a58f2571") => Some(&SWELL_42161_A58F2571), - (42161, addr) if addr == address!("0x1bCfc0B4eE1471674cd6A9F6B363A034375eAD84") => Some(&SYNAPSE_42161_375EAD84), - (42161, addr) if addr == address!("0x0945Cae3ae47cb384b2d47BC448Dc6A9dEC21F55") => Some(&THRESHOLD_NETWORK_42161_DEC21F55), - (42161, addr) if addr == address!("0x7E2a1eDeE171C5B19E6c54D73752396C0A572594") => Some(&TBTC_42161_0A572594), - (42161, addr) if addr == address!("0xd58D345Fd9c82262E087d2D0607624B410D88242") => Some(&TELLOR_42161_10D88242), - (42161, addr) if addr == address!("0xBfAE6fecD8124ba33cbB2180aAb0Fe4c03914A5A") => Some(&TRIBE_42161_03914A5A), - (42161, addr) if addr == address!("0x5C816d4582c857dcadb1bB1F62Ad6c9DEde4576a") => Some(&TURBO_42161_EDE4576A), - (42161, addr) if addr == address!("0xd693Ec944A85eeca4247eC1c3b130DCa9B0C3b22") => Some(&UMA_VOTING_TOKEN_V1_42161_9B0C3B22), - (42161, addr) if addr == address!("0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0") => Some(&UNISWAP_42161_72F1F7F0), - (42161, addr) if addr == address!("0x7550dE0A4b9Fb8CAbA8c32E72Ee356AFdd217A33") => Some(&WORLD_LIBERTY_FINANCIAL_USD_42161_DD217A33), - (42161, addr) if addr == address!("0xaf88d065e77c8cC2239327C5EDb3A432268e5831") => Some(&USDCOIN_42161_268E5831), - (42161, addr) if addr == address!("0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8") => Some(&BRIDGED_USDC_42161_BDDB5CC8), - (42161, addr) if addr == address!("0x78df3a6044Ce3cB1905500345B967788b699dF8f") => Some(&PAX_DOLLAR_42161_B699DF8F), - (42161, addr) if addr == address!("0x6491c05A82219b8D1479057361ff1654749b876b") => Some(&USDS_STABLECOIN_42161_749B876B), - (42161, addr) if addr == address!("0x7639AB8599f1b417CbE4ceD492fB30162140AbbB") => Some(&USUAL_42161_2140ABBB), - (42161, addr) if addr == address!("0x1c8Ec4DE3c2BFD3050695D89853EC6d78AE650bb") => Some(&WRAPPED_AMPLEFORTH_42161_8AE650BB), - (42161, addr) if addr == address!("0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f") => Some(&WRAPPED_BTC_42161_AEFC5B0F), - (42161, addr) if addr == address!("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1") => Some(&WRAPPED_ETHER_42161_523FBAB1), - (42161, addr) if addr == address!("0x4D1d7134B87490AE5eEbdB22A5820d7d0E1980bf") => Some(&WORLD_LIBERTY_FINANCIAL_42161_0E1980BF), - (42161, addr) if addr == address!("0xcAFcD85D8ca7Ad1e1C6F82F651fA15E33AEfD07b") => Some(&WOO_NETWORK_42161_3AEFD07B), - (42161, addr) if addr == address!("0x9B86f3c7d145979ec6b2F42eD7f92D06cfC6C9d3") => Some(&TETHER_GOLD_42161_CFC6C9D3), - (42161, addr) if addr == address!("0x58BbC087e36Db40a84b22c1B93a042294deEAFEd") => Some(&CHAIN_42161_4DEEAFED), - (42161, addr) if addr == address!("0xa05245Ade25cC1063EE50Cf7c083B4524c1C4302") => Some(&XSGD_42161_4C1C4302), - (42161, addr) if addr == address!("0x82e3A8F066a6989666b031d916c43672085b1582") => Some(&YEARN_FINANCE_42161_085B1582), - (42161, addr) if addr == address!("0x6DdBbcE7858D276678FC2B36123fD60547b88954") => Some(&ZETACHAIN_42161_47B88954), - (42161, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_42161_F13271CD), - (42161, addr) if addr == address!("0xBD591Bd4DdB64b77B5f76Eab8f03d02519235Ae2") => Some(&TOKEN_0X_PROTOCOL_TOKEN_42161_19235AE2), - (42220, addr) if addr == address!("0xD629eb00dEced2a080B7EC630eF6aC117e614f1b") => Some(&WRAPPED_BITCOIN), - (42220, addr) if addr == address!("0x471EcE3750Da237f93B8E339c536989b8978a438") => Some(&CELO), - (42220, addr) if addr == address!("0xcebA9300f2b948710d2653dD7B07f33A8B32118C") => Some(&USDCOIN_42220_8B32118C), - (42220, addr) if addr == address!("0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e") => Some(&TETHER_USD_42220_87483D5E), - (42220, addr) if addr == address!("0x2DEf4285787d58a2f811AF24755A8150622f4361") => Some(&WRAPPED_ETHER_42220_622F4361), - (43114, addr) if addr == address!("0xd501281565bf7789224523144Fe5D98e8B28f267") => Some(&TOKEN_1INCH_43114_8B28F267), - (43114, addr) if addr == address!("0x63a72806098Bd3D9520cC43356dD78afe5D386D9") => Some(&AAVE_43114_E5D386D9), - (43114, addr) if addr == address!("0xAEC8318a9a59bAEb39861d10ff6C7f7bf1F96C57") => Some(&AGEUR_43114_F1F96C57), - (43114, addr) if addr == address!("0x2147EFFF675e4A4eE1C2f918d181cDBd7a8E208f") => Some(&ALPHA_VENTURE_DAO_43114_7A8E208F), - (43114, addr) if addr == address!("0x20CF1b6E9d856321ed4686877CF4538F2C84B4dE") => Some(&ANKR_43114_2C84B4DE), - (43114, addr) if addr == address!("0x44c784266cf024a60e8acF2427b9857Ace194C5d") => Some(&AXELAR_43114_CE194C5D), - (43114, addr) if addr == address!("0x98443B96EA4b0858FDF3219Cd13e98C7A4690588") => Some(&BASIC_ATTENTION_TOKEN_43114_A4690588), - (43114, addr) if addr == address!("0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39") => Some(&BINANCE_USD_43114_39D2DB39), - (43114, addr) if addr == address!("0xc3048E19E76CB9a3Aa9d77D8C03c29Fc906e2437") => Some(&COMPOUND_43114_906E2437), - (43114, addr) if addr == address!("0x6b289CCeAA8639e3831095D75A3e43520faBf552") => Some(&CARTESI_43114_0FABF552), - (43114, addr) if addr == address!("0xd586E7F844cEa2F87f50152665BCbc2C279D8d70") => Some(&DAI_E_TOKEN), - (43114, addr) if addr == address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17") => Some(&DEFI_YIELD_PROTOCOL_43114_91BCEF17), - (43114, addr) if addr == address!("0xC891EB4cbdEFf6e073e859e987815Ed1505c2ACD") => Some(&EURO_COIN_43114_505C2ACD), - (43114, addr) if addr == address!("0xc4B06F17ECcB2215a5DBf042C672101Fc20daF55") => Some(&FLUX_43114_C20DAF55), - (43114, addr) if addr == address!("0xD24C2Ad096400B6FBcd2ad8B24E7acBc21A1da64") => Some(&FRAX_43114_21A1DA64), - (43114, addr) if addr == address!("0x214DB107654fF987AD859F34125307783fC8e387") => Some(&FRAX_SHARE_43114_3FC8E387), - (43114, addr) if addr == address!("0x62edc0692BD897D2295872a9FFCac5425011c661") => Some(&GMX_43114_5011C661), - (43114, addr) if addr == address!("0x8a0cAc13c7da965a312f08ea4229c37869e85cB9") => Some(&THE_GRAPH_43114_69E85CB9), - (43114, addr) if addr == address!("0x26deBD39D5eD069770406FCa10A0E4f8d2c743eB") => Some(&GUNZ), - (43114, addr) if addr == address!("0x5947BB275c521040051D82396192181b413227A3") => Some(&CHAINLINK_TOKEN_43114_413227A3), - (43114, addr) if addr == address!("0x130966628846BFd36ff31a822705796e8cb8C18D") => Some(&MAGIC_INTERNET_MONEY_43114_8CB8C18D), - (43114, addr) if addr == address!("0x88128fd4b259552A9A1D457f435a6527AAb72d42") => Some(&MAKER_43114_AAB72D42), - (43114, addr) if addr == address!("0x9Fb9a33956351cf4fa040f65A13b835A3C8764E3") => Some(&MULTICHAIN_43114_3C8764E3), - (43114, addr) if addr == address!("0xfB98B335551a418cD0737375a2ea0ded62Ea213b") => Some(&PENDLE_43114_62EA213B), - (43114, addr) if addr == address!("0x97Cd1CFE2ed5712660bb6c14053C0EcB031Bff7d") => Some(&RAI_REFLEX_INDEX_43114_031BFF7D), - (43114, addr) if addr == address!("0xBeC243C995409E6520D7C41E404da5dEba4b209B") => Some(&SYNTHETIX_NETWORK_TOKEN_43114_BA4B209B), - (43114, addr) if addr == address!("0xFE6B19286885a4F7F55AdAD09C3Cd1f906D2478F") => Some(&SOL_WORMHOLE_43114_06D2478F), - (43114, addr) if addr == address!("0xCE1bFFBD5374Dac86a2893119683F4911a2F7814") => Some(&SPELL_TOKEN_43114_1A2F7814), - (43114, addr) if addr == address!("0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590") => Some(&STARGATE_FINANCE_43114_F56E7590), - (43114, addr) if addr == address!("0x37B608519F91f70F2EeB0e5Ed9AF4061722e4F76") => Some(&SUSHI_43114_722E4F76), - (43114, addr) if addr == address!("0x1f1E7c893855525b303f99bDF5c3c05Be09ca251") => Some(&SYNAPSE_43114_E09CA251), - (43114, addr) if addr == address!("0x3Bd2B1c7ED8D396dbb98DED3aEbb41350a5b2339") => Some(&UMA_VOTING_TOKEN_V1_43114_0A5B2339), - (43114, addr) if addr == address!("0x8eBAf22B6F053dFFeaf46f4Dd9eFA95D89ba8580") => Some(&UNI_E_TOKEN), - (43114, addr) if addr == address!("0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E") => Some(&USDC_TOKEN), - (43114, addr) if addr == address!("0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7") => Some(&TETHER_USD_43114_4DF4A8C7), - (43114, addr) if addr == address!("0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7") => Some(&WRAPPED_AVAX), - (43114, addr) if addr == address!("0x50b7545627a5162F82A992c33b87aDc75187B218") => Some(&WRAPPED_BTC_43114_5187B218), - (43114, addr) if addr == address!("0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB") => Some(&WRAPPED_ETHER_43114_6BC10BAB), - (43114, addr) if addr == address!("0xaBC9547B534519fF73921b1FBA6E672b5f58D083") => Some(&WOO_NETWORK_43114_5F58D083), - (43114, addr) if addr == address!("0x9eAaC1B23d935365bD7b542Fe22cEEe2922f52dc") => Some(&YEARN_FINANCE_43114_922F52DC), - (43114, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_43114_F13271CD), - (43114, addr) if addr == address!("0x596fA47043f99A4e0F122243B841E55375cdE0d2") => Some(&TOKEN_0X_PROTOCOL_TOKEN_43114_75CDE0D2), - (80001, addr) if addr == address!("0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa") => Some(&WRAPPED_ETHER_80001_C5D1C0AA), - (80001, addr) if addr == address!("0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889") => Some(&WRAPPED_MATIC_80001_FB032889), - (81457, addr) if addr == address!("0xb1a5700fA2358173Fe465e6eA4Ff52E36e88E2ad") => Some(&BLAST), - (7777777, addr) if addr == address!("0xCccCCccc7021b32EBb4e8C08314bD62F7c653EC4") => Some(&USD_COIN_BRIDGED_FROM_ETHEREUM), - (11155111, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP_11155111_4201F984), - (11155111, addr) if addr == address!("0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14") => Some(&WRAPPED_ETHER_11155111_324D6B14), - _ => None, - } -} +// Auto-generated from Uniswap token list v18.7.0 +// 1203 tokens +// DO NOT EDIT - regenerate with gen_erc20_registry.py + +pub static TOKEN_1INCH: TokenInfo = TokenInfo { + name: "1inch", + symbol: "1INCH", + decimals: 18, + contract: address!("0x111111111117dC0aa78b770fA6A738034120C302"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), +}; + +pub static ANCIENT8: TokenInfo = TokenInfo { + name: "Ancient8", + symbol: "A8", + decimals: 18, + contract: address!("0x3E5A19c91266aD8cE2477B91585d1856B84062dF"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/39170/standard/A8_Token-04_200x200.png?1720798300"), +}; + +pub static AAVE: TokenInfo = TokenInfo { + name: "Aave", + symbol: "AAVE", + decimals: 18, + contract: address!("0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), +}; + +pub static ARCBLOCK: TokenInfo = TokenInfo { + name: "Arcblock", + symbol: "ABT", + decimals: 18, + contract: address!("0xB98d4C97425d9908E66E53A6fDf673ACcA0BE986"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2341/thumb/arcblock.png?1547036543"), +}; + +pub static ALCHEMY_PAY: TokenInfo = TokenInfo { + name: "Alchemy Pay", + symbol: "ACH", + decimals: 8, + contract: address!("0xEd04915c23f00A313a544955524EB7DBD823143d"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12390/thumb/ACH_%281%29.png?1599691266"), +}; + +pub static ACROSS_PROTOCOL_TOKEN: TokenInfo = TokenInfo { + name: "Across Protocol Token", + symbol: "ACX", + decimals: 18, + contract: address!("0x44108f0223A3C3028F5Fe7AEC7f9bb2E66beF82F"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165"), +}; + +pub static AMBIRE_ADEX: TokenInfo = TokenInfo { + name: "Ambire AdEx", + symbol: "ADX", + decimals: 18, + contract: address!("0xADE00C28244d5CE17D72E40330B1c318cD12B7c3"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540"), +}; + +pub static AERGO: TokenInfo = TokenInfo { + name: "Aergo", + symbol: "AERGO", + decimals: 18, + contract: address!("0x91Af0fBB28ABA7E31403Cb457106Ce79397FD4E6"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/4490/thumb/aergo.png?1647696770"), +}; + +pub static AEVO: TokenInfo = TokenInfo { + name: "Aevo", + symbol: "AEVO", + decimals: 18, + contract: address!("0xB528edBef013aff855ac3c50b381f253aF13b997"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/35893/standard/aevo.png"), +}; + +pub static AGEUR: TokenInfo = TokenInfo { + name: "agEur", + symbol: "agEUR", + decimals: 18, + contract: address!("0x1a7e4e63778B4f12a199C062f3eFdD288afCBce8"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), +}; + +pub static ADVENTURE_GOLD: TokenInfo = TokenInfo { + name: "Adventure Gold", + symbol: "AGLD", + decimals: 18, + contract: address!("0x32353A6C91143bfd6C7d363B546e62a9A2489A20"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/18125/thumb/lpgblc4h_400x400.jpg?1630570955"), +}; + +pub static AIOZ_NETWORK: TokenInfo = TokenInfo { + name: "AIOZ Network", + symbol: "AIOZ", + decimals: 18, + contract: address!("0x626E8036dEB333b408Be468F951bdB42433cBF18"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126"), +}; + +pub static ALCHEMIX: TokenInfo = TokenInfo { + name: "Alchemix", + symbol: "ALCX", + decimals: 18, + contract: address!("0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14113/thumb/Alchemix.png?1614409874"), +}; + +pub static ALEPH_IM: TokenInfo = TokenInfo { + name: "Aleph im", + symbol: "ALEPH", + decimals: 18, + contract: address!("0x27702a26126e0B3702af63Ee09aC4d1A084EF628"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725"), +}; + +pub static ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE: TokenInfo = TokenInfo { + name: "Alethea Artificial Liquid Intelligence", + symbol: "ALI", + decimals: 18, + contract: address!("0x6B0b3a982b4634aC68dD83a4DBF02311cE324181"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848"), +}; + +pub static MY_NEIGHBOR_ALICE: TokenInfo = TokenInfo { + name: "My Neighbor Alice", + symbol: "ALICE", + decimals: 6, + contract: address!("0xAC51066d7bEC65Dc4589368da368b212745d63E8"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14375/thumb/alice_logo.jpg?1615782968"), +}; + +pub static ALLORA: TokenInfo = TokenInfo { + name: "Allora", + symbol: "ALLO", + decimals: 18, + contract: address!("0x8408D45b61f5823298F19a09B53b7339c0280489"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/70609/large/allo-token.png?1763451165"), +}; + +pub static ALPHA_VENTURE_DAO: TokenInfo = TokenInfo { + name: "Alpha Venture DAO", + symbol: "ALPHA", + decimals: 18, + contract: address!("0xa1faa113cbE53436Df28FF0aEe54275c13B40975"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876"), +}; + +pub static ALTLAYER: TokenInfo = TokenInfo { + name: "AltLayer", + symbol: "ALT", + decimals: 18, + contract: address!("0x8457CA5040ad67fdebbCC8EdCE889A335Bc0fbFB"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/34608/standard/Logomark_200x200.png"), +}; + +pub static AMP: TokenInfo = TokenInfo { + name: "Amp", + symbol: "AMP", + decimals: 18, + contract: address!("0xfF20817765cB7f73d4bde2e66e067E58D11095C2"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12409/thumb/amp-200x200.png?1599625397"), +}; + +pub static ANKR: TokenInfo = TokenInfo { + name: "Ankr", + symbol: "ANKR", + decimals: 18, + contract: address!("0x8290333ceF9e6D528dD5618Fb97a76f268f3EDD4"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978"), +}; + +pub static ARAGON: TokenInfo = TokenInfo { + name: "Aragon", + symbol: "ANT", + decimals: 18, + contract: address!("0xa117000000f279D81A1D3cc75430fAA017FA5A2e"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/681/thumb/JelZ58cv_400x400.png?1601449653"), +}; + +pub static APECOIN: TokenInfo = TokenInfo { + name: "ApeCoin", + symbol: "APE", + decimals: 18, + contract: address!("0x4d224452801ACEd8B2F0aebE155379bb5D594381"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/24383/small/apecoin.jpg?1647476455"), +}; + +pub static API3: TokenInfo = TokenInfo { + name: "API3", + symbol: "API3", + decimals: 18, + contract: address!("0x0b38210ea11411557c13457D4dA7dC6ea731B88a"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13256/thumb/api3.jpg?1606751424"), +}; + +pub static APRIORI: TokenInfo = TokenInfo { + name: "aPriori", + symbol: "APR", + decimals: 18, + contract: address!("0x5A9610919f5e81183823A2be4Bd1BeB2B4da2a20"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/70220/large/logo-icon-Gradient.png?1761118006"), +}; + +pub static APU_APUSTAJA: TokenInfo = TokenInfo { + name: "Apu Apustaja", + symbol: "APU", + decimals: 18, + contract: address!("0x594DaaD7D77592a2b97b725A7AD59D7E188b5bFa"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/35986/large/200x200.png?1710308147"), +}; + +pub static ARBITRUM: TokenInfo = TokenInfo { + name: "Arbitrum", + symbol: "ARB", + decimals: 18, + contract: address!("0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1"), + chain: 1, + logo_uri: Some("https://arbitrum.foundation/logo.png"), +}; + +pub static ARKHAM: TokenInfo = TokenInfo { + name: "Arkham", + symbol: "ARKM", + decimals: 18, + contract: address!("0x6E2a43be0B1d33b726f0CA3b8de60b3482b8b050"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/30929/standard/Arkham_Logo_CG.png?1696529771"), +}; + +pub static ARPA_CHAIN: TokenInfo = TokenInfo { + name: "ARPA Chain", + symbol: "ARPA", + decimals: 18, + contract: address!("0xBA50933C268F567BDC86E1aC131BE072C6B0b71a"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357"), +}; + +pub static ASH: TokenInfo = TokenInfo { + name: "ASH", + symbol: "ASH", + decimals: 18, + contract: address!("0x64D91f12Ece7362F91A6f8E7940Cd55F05060b92"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/15714/thumb/omnPqaTY.png?1622820503"), +}; + +pub static ASSEMBLE_PROTOCOL: TokenInfo = TokenInfo { + name: "Assemble Protocol", + symbol: "ASM", + decimals: 18, + contract: address!("0x2565ae0385659badCada1031DB704442E1b69982"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11605/thumb/gpvrlkSq_400x400_%281%29.jpg?1591775789"), +}; + +pub static AIRSWAP: TokenInfo = TokenInfo { + name: "AirSwap", + symbol: "AST", + decimals: 4, + contract: address!("0x27054b13b1B798B345b591a4d22e6562d47eA75a"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1019/thumb/Airswap.png?1630903484"), +}; + +pub static AUTOMATA: TokenInfo = TokenInfo { + name: "Automata", + symbol: "ATA", + decimals: 18, + contract: address!("0xA2120b9e674d3fC3875f415A7DF52e382F141225"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745"), +}; + +pub static AETHIR_TOKEN: TokenInfo = TokenInfo { + name: "Aethir Token", + symbol: "ATH", + decimals: 18, + contract: address!("0xbe0Ed4138121EcFC5c0E56B40517da27E6c5226B"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/36179/large/logogram_circle_dark_green_vb_green_(1).png?1718232706"), +}; + +pub static BOUNCE: TokenInfo = TokenInfo { + name: "Bounce", + symbol: "AUCTION", + decimals: 18, + contract: address!("0xA9B1Eb5908CfC3cdf91F9B8B3a74108598009096"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13860/thumb/1_KtgpRIJzuwfHe0Rl0avP_g.jpeg?1612412025"), +}; + +pub static AUDD: TokenInfo = TokenInfo { + name: "AUDD", + symbol: "AUDD", + decimals: 6, + contract: address!("0x4cCe605eD955295432958d8951D0B176C10720d5"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/33263/large/AUDD-Logo-Blue_512.png?1701319895"), +}; + +pub static AUDIUS: TokenInfo = TokenInfo { + name: "Audius", + symbol: "AUDIO", + decimals: 18, + contract: address!("0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12913/thumb/AudiusCoinLogo_2x.png?1603425727"), +}; + +pub static ARTVERSE_TOKEN: TokenInfo = TokenInfo { + name: "Artverse Token", + symbol: "AVT", + decimals: 18, + contract: address!("0x845576c64f9754CF09d87e45B720E82F3EeF522C"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/19727/thumb/ewnektoB_400x400.png?1635767094"), +}; + +pub static AXELAR: TokenInfo = TokenInfo { + name: "Axelar", + symbol: "AXL", + decimals: 6, + contract: address!("0x467719aD09025FcC6cF6F8311755809d45a5E5f3"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg"), +}; + +pub static AXIE_INFINITY: TokenInfo = TokenInfo { + name: "Axie Infinity", + symbol: "AXS", + decimals: 18, + contract: address!("0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082"), +}; + +pub static AZTEC: TokenInfo = TokenInfo { + name: "Aztec", + symbol: "AZTEC", + decimals: 18, + contract: address!("0xA27EC0006e59f245217Ff08CD52A7E8b169E62D2"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/70681/large/aztec.png?1763091883"), +}; + +pub static BADGER_DAO: TokenInfo = TokenInfo { + name: "Badger DAO", + symbol: "BADGER", + decimals: 18, + contract: address!("0x3472A5A71965499acd81997a54BBA8D852C6E53d"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13287/thumb/badger_dao_logo.jpg?1607054976"), +}; + +pub static BALANCER: TokenInfo = TokenInfo { + name: "Balancer", + symbol: "BAL", + decimals: 18, + contract: address!("0xba100000625a3754423978a60c9317c58a424e3D"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png"), +}; + +pub static BAND_PROTOCOL: TokenInfo = TokenInfo { + name: "Band Protocol", + symbol: "BAND", + decimals: 18, + contract: address!("0xBA11D00c5f74255f56a5E366F4F77f5A186d7f55"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/9545/thumb/band-protocol.png?1568730326"), +}; + +pub static LOMBARD: TokenInfo = TokenInfo { + name: "Lombard", + symbol: "BARD", + decimals: 18, + contract: address!("0xf0DB65D17e30a966C2ae6A21f6BBA71cea6e9754"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/68404/large/bard.png?1755657543"), +}; + +pub static BASIC_ATTENTION_TOKEN: TokenInfo = TokenInfo { + name: "Basic Attention Token", + symbol: "BAT", + decimals: 18, + contract: address!("0x0D8775F648430679A709E98d2b0Cb6250d2887EF"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427"), +}; + +pub static BEAM: TokenInfo = TokenInfo { + name: "Beam", + symbol: "BEAM", + decimals: 18, + contract: address!("0x62D0A8458eD7719FDAF978fe5929C6D342B0bFcE"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/32417/standard/chain-logo.png?1698114384"), +}; + +pub static BICONOMY: TokenInfo = TokenInfo { + name: "Biconomy", + symbol: "BICO", + decimals: 18, + contract: address!("0xF17e65822b568B3903685a7c9F496CF7656Cc6C2"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749"), +}; + +pub static BIG_TIME: TokenInfo = TokenInfo { + name: "Big Time", + symbol: "BIGTIME", + decimals: 18, + contract: address!("0x64Bc2cA1Be492bE7185FAA2c8835d9b824c8a194"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/32251/standard/-6136155493475923781_121.jpg?1696998691"), +}; + +pub static BIO: TokenInfo = TokenInfo { + name: "BIO", + symbol: "BIO", + decimals: 18, + contract: address!("0xcb1592591996765Ec0eFc1f92599A19767ee5ffA"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/53022/large/bio.jpg?1735011002"), +}; + +pub static BITDAO: TokenInfo = TokenInfo { + name: "BitDAO", + symbol: "BIT", + decimals: 18, + contract: address!("0x1A4b46696b2bB4794Eb3D4c26f1c55F9170fa4C5"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/17627/thumb/rI_YptK8.png?1653983088"), +}; + +pub static HARRYPOTTEROBAMASONIC10INU: TokenInfo = TokenInfo { + name: "HarryPotterObamaSonic10Inu", + symbol: "BITCOIN", + decimals: 8, + contract: address!("0x72e4f9F808C49A2a61dE9C5896298920Dc4EEEa9"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224"), +}; + +pub static BLUR: TokenInfo = TokenInfo { + name: "Blur", + symbol: "BLUR", + decimals: 18, + contract: address!("0x5283D291DBCF85356A21bA090E6db59121208b44"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/28453/large/blur.png?1670745921"), +}; + +pub static BLUZELLE: TokenInfo = TokenInfo { + name: "Bluzelle", + symbol: "BLZ", + decimals: 18, + contract: address!("0x5732046A883704404F284Ce41FfADd5b007FD668"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2848/thumb/ColorIcon_3x.png?1622516510"), +}; + +pub static BANCOR_NETWORK_TOKEN: TokenInfo = TokenInfo { + name: "Bancor Network Token", + symbol: "BNT", + decimals: 18, + contract: address!("0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png"), +}; + +pub static BOBA_NETWORK: TokenInfo = TokenInfo { + name: "Boba Network", + symbol: "BOBA", + decimals: 18, + contract: address!("0x42bBFa2e77757C645eeaAd1655E0911a7553Efbc"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/20285/thumb/BOBA.png?1636811576"), +}; + +pub static BOB: TokenInfo = TokenInfo { + name: "BOB", + symbol: "BOBBOB", + decimals: 18, + contract: address!("0xC9746F73cC33a36c2cD55b8aEFD732586946Cedd"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54720/large/BOB_symbol_colour.png?1741195397"), +}; + +pub static BARNBRIDGE: TokenInfo = TokenInfo { + name: "BarnBridge", + symbol: "BOND", + decimals: 18, + contract: address!("0x0391D2021f89DC339F60Fff84546EA23E337750f"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853"), +}; + +pub static BREVIS: TokenInfo = TokenInfo { + name: "Brevis", + symbol: "BREV", + decimals: 18, + contract: address!("0x086F405146Ce90135750Bbec9A063a8B20A8bfFb"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/71219/large/brevis.png?1766454723"), +}; + +pub static BRAINTRUST: TokenInfo = TokenInfo { + name: "Braintrust", + symbol: "BTRST", + decimals: 18, + contract: address!("0x799ebfABE77a6E34311eeEe9825190B9ECe32824"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/18100/thumb/braintrust.PNG?1630475394"), +}; + +pub static BINANCE_USD: TokenInfo = TokenInfo { + name: "Binance USD", + symbol: "BUSD", + decimals: 18, + contract: address!("0x4Fabb145d64652a948d72533023f6E7A623C7C53"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), +}; + +pub static COIN98: TokenInfo = TokenInfo { + name: "Coin98", + symbol: "C98", + decimals: 18, + contract: address!("0xAE12C5930881c53715B369ceC7606B70d8EB229f"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/17117/thumb/logo.png?1626412904"), +}; + +pub static PANCAKESWAP: TokenInfo = TokenInfo { + name: "PancakeSwap", + symbol: "CAKE", + decimals: 18, + contract: address!("0x152649eA73beAb28c5b49B26eb48f7EAD6d4c898"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/12632/large/pancakeswap-cake-logo_%281%29.png?1696512440"), +}; + +pub static COINBASE_WRAPPED_BTC: TokenInfo = TokenInfo { + name: "Coinbase Wrapped BTC", + symbol: "cbBTC", + decimals: 8, + contract: address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/40143/standard/cbbtc.webp"), +}; + +pub static COINBASE_WRAPPED_STAKED_ETH: TokenInfo = TokenInfo { + name: "Coinbase Wrapped Staked ETH", + symbol: "cbETH", + decimals: 18, + contract: address!("0xBe9895146f7AF43049ca1c1AE358B0541Ea49704"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/27008/large/cbeth.png"), +}; + +pub static CELO_NATIVE_ASSET_WORMHOLE: TokenInfo = TokenInfo { + name: "Celo native asset (Wormhole)", + symbol: "CELO", + decimals: 18, + contract: address!("0x3294395e62F4eB6aF3f1Fcf89f5602D90Fb3Ef69"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png"), +}; + +pub static CELER_NETWORK: TokenInfo = TokenInfo { + name: "Celer Network", + symbol: "CELR", + decimals: 18, + contract: address!("0x4F9254C83EB525f9FCf346490bbb3ed28a81C667"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/4379/thumb/Celr.png?1554705437"), +}; + +pub static CENTRIFUGE: TokenInfo = TokenInfo { + name: "Centrifuge", + symbol: "CFG", + decimals: 18, + contract: address!("0xcccCCCcCCC33D538DBC2EE4fEab0a7A1FF4e8A94"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/55913/large/centrifuge.jpg?1747707741"), +}; + +pub static CHROMIA: TokenInfo = TokenInfo { + name: "Chromia", + symbol: "CHR", + decimals: 6, + contract: address!("0x8A2279d4A90B6fe1C4B30fa660cC9f926797bAA2"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/5000/thumb/Chromia.png?1559038018"), +}; + +pub static CHILIZ: TokenInfo = TokenInfo { + name: "Chiliz", + symbol: "CHZ", + decimals: 18, + contract: address!("0x3506424F91fD33084466F402d5D97f05F8e3b4AF"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/8834/thumb/Chiliz.png?1561970540"), +}; + +pub static CLOVER_FINANCE: TokenInfo = TokenInfo { + name: "Clover Finance", + symbol: "CLV", + decimals: 18, + contract: address!("0x80C62FE4487E1351b47Ba49809EBD60ED085bf52"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/15278/thumb/clover.png?1645084454"), +}; + +pub static COMPOUND: TokenInfo = TokenInfo { + name: "Compound", + symbol: "COMP", + decimals: 18, + contract: address!("0xc00e94Cb662C3520282E6f5717214004A7f26888"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), +}; + +pub static CORN: TokenInfo = TokenInfo { + name: "Corn", + symbol: "CORN", + decimals: 18, + contract: address!("0x44f49ff0da2498bCb1D3Dc7C0f999578F67FD8C6"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54471/large/corn.jpg?1739933588"), +}; + +pub static COTI: TokenInfo = TokenInfo { + name: "COTI", + symbol: "COTI", + decimals: 18, + contract: address!("0xDDB3422497E61e13543BeA06989C0789117555c5"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2962/thumb/Coti.png?1559653863"), +}; + +pub static CIRCUITS_OF_VALUE: TokenInfo = TokenInfo { + name: "Circuits of Value", + symbol: "COVAL", + decimals: 8, + contract: address!("0x3D658390460295FB963f54dC0899cfb1c30776Df"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/588/thumb/coval-logo.png?1599493950"), +}; + +pub static COW_PROTOCOL: TokenInfo = TokenInfo { + name: "CoW Protocol", + symbol: "COW", + decimals: 18, + contract: address!("0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/24384/large/CoW-token_logo.png?1719524382"), +}; + +pub static CLEARPOOL: TokenInfo = TokenInfo { + name: "Clearpool", + symbol: "CPOOL", + decimals: 18, + contract: address!("0x66761Fa41377003622aEE3c7675Fc7b5c1C2FaC5"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/19252/large/photo_2022-08-31_12.45.02.jpeg?1696518697"), +}; + +pub static COVALENT: TokenInfo = TokenInfo { + name: "Covalent", + symbol: "CQT", + decimals: 18, + contract: address!("0xD417144312DbF50465b1C641d016962017Ef6240"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14168/thumb/covalent-cqt.png?1624545218"), +}; + +pub static CRONOS: TokenInfo = TokenInfo { + name: "Cronos", + symbol: "CRO", + decimals: 8, + contract: address!("0xA0b73E1Ff0B80914AB6fe0444E65848C4C34450b"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/7310/thumb/oCw2s3GI_400x400.jpeg?1645172042"), +}; + +pub static CRYPTERIUM: TokenInfo = TokenInfo { + name: "Crypterium", + symbol: "CRPT", + decimals: 18, + contract: address!("0x08389495D7456E1951ddF7c3a1314A4bfb646d8B"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1901/thumb/crypt.png?1547036205"), +}; + +pub static CURVE_DAO_TOKEN: TokenInfo = TokenInfo { + name: "Curve DAO Token", + symbol: "CRV", + decimals: 18, + contract: address!("0xD533a949740bb3306d119CC777fa900bA034cd52"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), +}; + +pub static CARTESI: TokenInfo = TokenInfo { + name: "Cartesi", + symbol: "CTSI", + decimals: 18, + contract: address!("0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), +}; + +pub static CRYPTEX_FINANCE: TokenInfo = TokenInfo { + name: "Cryptex Finance", + symbol: "CTX", + decimals: 18, + contract: address!("0x321C2fE4446C7c963dc41Dd58879AF648838f98D"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171"), +}; + +pub static SOMNIUM_SPACE_CUBES: TokenInfo = TokenInfo { + name: "Somnium Space CUBEs", + symbol: "CUBE", + decimals: 8, + contract: address!("0xDf801468a808a32656D2eD2D2d80B72A129739f4"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/10687/thumb/CUBE_icon.png?1617026861"), +}; + +pub static CIVIC: TokenInfo = TokenInfo { + name: "Civic", + symbol: "CVC", + decimals: 8, + contract: address!("0x41e5560054824eA6B0732E656E3Ad64E20e94E45"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556"), +}; + +pub static CONVEX_FINANCE: TokenInfo = TokenInfo { + name: "Convex Finance", + symbol: "CVX", + decimals: 18, + contract: address!("0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/15585/thumb/convex.png?1621256328"), +}; + +pub static COVALENT_X_TOKEN: TokenInfo = TokenInfo { + name: "Covalent X Token", + symbol: "CXT", + decimals: 18, + contract: address!("0x7ABc8A5768E6bE61A6c693a6e4EAcb5B60602C4D"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/39177/large/CXT_Ticker.png?1720829918"), +}; + +pub static DAI_STABLECOIN: TokenInfo = TokenInfo { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + contract: address!("0x6B175474E89094C44Da98b954EedeAC495271d0F"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), +}; + +pub static MINES_OF_DALARNIA: TokenInfo = TokenInfo { + name: "Mines of Dalarnia", + symbol: "DAR", + decimals: 6, + contract: address!("0x081131434f93063751813C619Ecca9C4dC7862a3"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/19837/thumb/dar.png?1636014223"), +}; + +pub static DERIVADAO: TokenInfo = TokenInfo { + name: "DerivaDAO", + symbol: "DDX", + decimals: 18, + contract: address!("0x3A880652F47bFaa771908C07Dd8673A787dAEd3A"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13453/thumb/ddx_logo.png?1608741641"), +}; + +pub static DENT: TokenInfo = TokenInfo { + name: "Dent", + symbol: "DENT", + decimals: 8, + contract: address!("0x3597bfD533a99c9aa083587B074434E61Eb0A258"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1152/thumb/gLCEA2G.png?1604543239"), +}; + +pub static DEXTOOLS: TokenInfo = TokenInfo { + name: "DexTools", + symbol: "DEXT", + decimals: 18, + contract: address!("0xfB7B4564402E5500dB5bB6d63Ae671302777C75a"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188"), +}; + +pub static DIA: TokenInfo = TokenInfo { + name: "DIA", + symbol: "DIA", + decimals: 18, + contract: address!("0x84cA8bc7997272c7CfB4D0Cd3D55cd942B3c9419"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751"), +}; + +pub static DISTRICT0X: TokenInfo = TokenInfo { + name: "district0x", + symbol: "DNT", + decimals: 18, + contract: address!("0x0AbdAce70D3790235af448C88547603b945604ea"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/849/thumb/district0x.png?1547223762"), +}; + +pub static DOLOMITE: TokenInfo = TokenInfo { + name: "Dolomite", + symbol: "DOLO", + decimals: 18, + contract: address!("0x0F81001eF0A83ecCE5ccebf63EB302c70a39a654"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54710/large/DOLO-small.png?1745398535"), +}; + +pub static DOVU: TokenInfo = TokenInfo { + name: "DOVU", + symbol: "DOVU", + decimals: 8, + contract: address!("0x2aeAbde1aB736c59E9A19BeD67681869eEF39526"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/31930/large/Dovu_Icon_Black_%281%29.png?1696530738"), +}; + +pub static DEFI_PULSE_INDEX: TokenInfo = TokenInfo { + name: "DeFi Pulse Index", + symbol: "DPI", + decimals: 18, + contract: address!("0x1494CA1F11D487c2bBe4543E90080AeBa4BA3C2b"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12465/thumb/defi_pulse_index_set.png?1600051053"), +}; + +pub static DREP: TokenInfo = TokenInfo { + name: "Drep", + symbol: "DREP", + decimals: 18, + contract: address!("0x3Ab6Ed69Ef663bd986Ee59205CCaD8A20F98b4c2"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14578/thumb/KotgsCgS_400x400.jpg?1617094445"), +}; + +pub static DERIVE: TokenInfo = TokenInfo { + name: "Derive", + symbol: "DRV", + decimals: 18, + contract: address!("0xB1D1eae60EEA9525032a6DCb4c1CE336a1dE71BE"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695"), +}; + +pub static DYDX: TokenInfo = TokenInfo { + name: "dYdX", + symbol: "DYDX", + decimals: 18, + contract: address!("0x92D6C1e31e14520e676a687F0a93788B716BEff5"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/17500/thumb/hjnIm9bV.jpg?1628009360"), +}; + +pub static DEFI_YIELD_PROTOCOL: TokenInfo = TokenInfo { + name: "DeFi Yield Protocol", + symbol: "DYP", + decimals: 18, + contract: address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066"), +}; + +pub static EIGENLAYER: TokenInfo = TokenInfo { + name: "EigenLayer", + symbol: "EIGEN", + decimals: 18, + contract: address!("0xec53bF9167f50cDEB3Ae105f56099aaaB9061F83"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/37441/large/eigen.jpg?1728023974"), +}; + +pub static ELASTOS: TokenInfo = TokenInfo { + name: "Elastos", + symbol: "ELA", + decimals: 18, + contract: address!("0xe6fd75ff38Adca4B97FBCD938c86b98772431867"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2780/thumb/Elastos.png?1597048112"), +}; + +pub static DOGELON_MARS: TokenInfo = TokenInfo { + name: "Dogelon Mars", + symbol: "ELON", + decimals: 18, + contract: address!("0x761D38e5ddf6ccf6Cf7c55759d5210750B5D60F3"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413"), +}; + +pub static ETHENA: TokenInfo = TokenInfo { + name: "Ethena", + symbol: "ENA", + decimals: 18, + contract: address!("0x57e114B691Db790C35207b2e685D4A43181e6061"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/36530/standard/ethena.png"), +}; + +pub static ENJIN_COIN: TokenInfo = TokenInfo { + name: "Enjin Coin", + symbol: "ENJ", + decimals: 18, + contract: address!("0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1102/thumb/enjin-coin-logo.png?1547035078"), +}; + +pub static ETHEREUM_NAME_SERVICE: TokenInfo = TokenInfo { + name: "Ethereum Name Service", + symbol: "ENS", + decimals: 18, + contract: address!("0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140"), +}; + +pub static CALDERA: TokenInfo = TokenInfo { + name: "Caldera", + symbol: "ERA", + decimals: 18, + contract: address!("0xE2AD0BF751834f2fbdC62A41014f84d67cA1de2A"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54475/large/Token_Logo.png?1749676251"), +}; + +pub static ETHERNITY_CHAIN: TokenInfo = TokenInfo { + name: "Ethernity Chain", + symbol: "ERN", + decimals: 18, + contract: address!("0xBBc2AE13b23d715c30720F079fcd9B4a74093505"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14238/thumb/LOGO_HIGH_QUALITY.png?1647831402"), +}; + +pub static ESPRESSO: TokenInfo = TokenInfo { + name: "Espresso", + symbol: "ESP", + decimals: 18, + contract: address!("0x031De51F3E8016514Bd0963d0B2AB825A591Db9A"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/67626/large/espresso.jpg?1753324525"), +}; + +pub static ETHER_FI: TokenInfo = TokenInfo { + name: "Ether.fi", + symbol: "ETHFI", + decimals: 18, + contract: address!("0xFe0c30065B384F05761f15d0CC899D4F9F9Cc0eB"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/35958/standard/etherfi.jpeg"), +}; + +pub static EULER: TokenInfo = TokenInfo { + name: "Euler", + symbol: "EUL", + decimals: 18, + contract: address!("0xd9Fcd98c322942075A5C3860693e9f4f03AAE07b"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/26149/thumb/YCvKDfl8_400x400.jpeg?1656041509"), +}; + +pub static EURO_COIN: TokenInfo = TokenInfo { + name: "Euro Coin", + symbol: "EURC", + decimals: 6, + contract: address!("0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420"), +}; + +pub static SCHUMAN_EUR_P: TokenInfo = TokenInfo { + name: "Schuman EUR P", + symbol: "EUROP", + decimals: 6, + contract: address!("0x888883b5F5D21fb10Dfeb70e8f9722B9FB0E5E51"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/52132/large/europ-symbol-rgb.jpg?1732634862"), +}; + +pub static QUANTOZ_EURQ: TokenInfo = TokenInfo { + name: "Quantoz EURQ", + symbol: "EURQ", + decimals: 6, + contract: address!("0x8dF723295214Ea6f21026eeEb4382d475f146F9f"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/51853/large/EURQ_1000px_Color.png?1732071269"), +}; + +pub static STABLR_EURO: TokenInfo = TokenInfo { + name: "StablR Euro", + symbol: "EURR", + decimals: 6, + contract: address!("0x50753CfAf86c094925Bf976f218D043f8791e408"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/53720/large/stablreuro-logo.png?1737125898"), +}; + +pub static HARVEST_FINANCE: TokenInfo = TokenInfo { + name: "Harvest Finance", + symbol: "FARM", + decimals: 18, + contract: address!("0xa0246c9032bC3A600820415aE600c6388619A14D"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180"), +}; + +pub static FETCH_AI: TokenInfo = TokenInfo { + name: "Fetch ai", + symbol: "FET", + decimals: 18, + contract: address!("0xaea46A60368A7bD060eec7DF8CBa43b7EF41Ad85"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136"), +}; + +pub static FIDELITY_DIGITAL_DOLLAR: TokenInfo = TokenInfo { + name: "Fidelity Digital Dollar", + symbol: "FIDD", + decimals: 18, + contract: address!("0x7C135549504245B5eAe64fc0E99Fa5ebabb8e35D"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/102171776/large/FIDD-Green_%28792px%29.png?1769612802"), +}; + +pub static STAFI: TokenInfo = TokenInfo { + name: "Stafi", + symbol: "FIS", + decimals: 18, + contract: address!("0xef3A930e1FfFFAcd2fc13434aC81bD278B0ecC8d"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991"), +}; + +pub static FLOKI: TokenInfo = TokenInfo { + name: "FLOKI", + symbol: "FLOKI", + decimals: 9, + contract: address!("0xcf0C122c6b73ff809C693DB761e7BaeBe62b6a2E"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318"), +}; + +pub static FLUX: TokenInfo = TokenInfo { + name: "Flux", + symbol: "FLUX", + decimals: 18, + contract: address!("0x720CD16b011b987Da3518fbf38c3071d4F0D1495"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x720CD16b011b987Da3518fbf38c3071d4F0D1495/logo.png"), +}; + +pub static FORTA: TokenInfo = TokenInfo { + name: "Forta", + symbol: "FORT", + decimals: 18, + contract: address!("0x41545f8b9472D758bB669ed8EaEEEcD7a9C4Ec29"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/25060/thumb/Forta_lgo_%281%29.png?1655353696"), +}; + +pub static AMPLEFORTH_GOVERNANCE_TOKEN: TokenInfo = TokenInfo { + name: "Ampleforth Governance Token", + symbol: "FORTH", + decimals: 18, + contract: address!("0x77FbA179C79De5B7653F68b5039Af940AdA60ce0"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14917/thumb/photo_2021-04-22_00.00.03.jpeg?1619020835"), +}; + +pub static SHAPESHIFT_FOX_TOKEN: TokenInfo = TokenInfo { + name: "ShapeShift FOX Token", + symbol: "FOX", + decimals: 18, + contract: address!("0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622"), +}; + +pub static FRAX: TokenInfo = TokenInfo { + name: "Frax", + symbol: "FRAX", + decimals: 18, + contract: address!("0x853d955aCEf822Db058eb8505911ED77F175b99e"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), +}; + +pub static FANTOM: TokenInfo = TokenInfo { + name: "Fantom", + symbol: "FTM", + decimals: 18, + contract: address!("0x4E15361FD6b4BB609Fa63C81A2be19d873717870"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016"), +}; + +pub static FUNCTION_X: TokenInfo = TokenInfo { + name: "Function X", + symbol: "FX", + decimals: 18, + contract: address!("0x8c15Ef5b4B21951d50E53E4fbdA8298FFAD25057"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/8186/thumb/47271330_590071468072434_707260356350705664_n.jpg?1556096683"), +}; + +pub static FRAX_SHARE: TokenInfo = TokenInfo { + name: "Frax Share", + symbol: "FXS", + decimals: 18, + contract: address!("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), +}; + +pub static GRAVITY: TokenInfo = TokenInfo { + name: "Gravity", + symbol: "G", + decimals: 18, + contract: address!("0x9C7BEBa8F6eF6643aBd725e45a4E8387eF260649"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/39200/large/gravity.jpg?1721020647"), +}; + +pub static GALXE: TokenInfo = TokenInfo { + name: "Galxe", + symbol: "GAL", + decimals: 18, + contract: address!("0x5fAa989Af96Af85384b8a938c2EdE4A7378D9875"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533"), +}; + +pub static GALA: TokenInfo = TokenInfo { + name: "GALA", + symbol: "GALA", + decimals: 8, + contract: address!("0xd1d2Eb1B1e90B638588728b4130137D262C87cae"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12493/standard/GALA-COINGECKO.png?1696512310"), +}; + +pub static GOLDFINCH: TokenInfo = TokenInfo { + name: "Goldfinch", + symbol: "GFI", + decimals: 18, + contract: address!("0xdab396cCF3d84Cf2D07C4454e10C8A6F5b008D2b"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/19081/thumb/GOLDFINCH.png?1634369662"), +}; + +pub static AAVEGOTCHI: TokenInfo = TokenInfo { + name: "Aavegotchi", + symbol: "GHST", + decimals: 18, + contract: address!("0x3F382DbD960E3a9bbCeaE22651E88158d2791550"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12467/thumb/ghst_200.png?1600750321"), +}; + +pub static GOLEM: TokenInfo = TokenInfo { + name: "Golem", + symbol: "GLM", + decimals: 18, + contract: address!("0x7DD9c5Cba05E151C895FDe1CF355C9A1D5DA6429"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/542/thumb/Golem_Submark_Positive_RGB.png?1606392013"), +}; + +pub static GNOSIS_TOKEN: TokenInfo = TokenInfo { + name: "Gnosis Token", + symbol: "GNO", + decimals: 18, + contract: address!("0x6810e776880C02933D47DB1b9fc05908e5386b96"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png"), +}; + +pub static GODS_UNCHAINED: TokenInfo = TokenInfo { + name: "Gods Unchained", + symbol: "GODS", + decimals: 18, + contract: address!("0xccC8cb5229B0ac8069C51fd58367Fd1e622aFD97"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/17139/thumb/10631.png?1635718182"), +}; + +pub static THE_GRAPH: TokenInfo = TokenInfo { + name: "The Graph", + symbol: "GRT", + decimals: 18, + contract: address!("0xc944E90C64B2c07662A292be6244BDf05Cda44a7"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566"), +}; + +pub static GITCOIN: TokenInfo = TokenInfo { + name: "Gitcoin", + symbol: "GTC", + decimals: 18, + contract: address!("0xDe30da39c46104798bB5aA3fe8B9e0e1F348163F"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929"), +}; + +pub static GEMINI_DOLLAR: TokenInfo = TokenInfo { + name: "Gemini Dollar", + symbol: "GUSD", + decimals: 2, + contract: address!("0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/5992/thumb/gemini-dollar-gusd.png?1536745278"), +}; + +pub static ETHGAS: TokenInfo = TokenInfo { + name: "ETHGas", + symbol: "GWEI", + decimals: 18, + contract: address!("0x2798b1cC5A993085E8A9D46e80499F1B63f42204"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/71375/large/ethgas_token_200.png?1769055039"), +}; + +pub static GYEN: TokenInfo = TokenInfo { + name: "GYEN", + symbol: "GYEN", + decimals: 6, + contract: address!("0xC08512927D12348F6620a698105e1BAac6EcD911"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343"), +}; + +pub static HASHFLOW: TokenInfo = TokenInfo { + name: "Hashflow", + symbol: "HFT", + decimals: 18, + contract: address!("0xb3999F658C0391d94A37f7FF328F3feC942BcADC"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/26136/large/hashflow-icon-cmc.png"), +}; + +pub static HIGHSTREET: TokenInfo = TokenInfo { + name: "Highstreet", + symbol: "HIGH", + decimals: 18, + contract: address!("0x71Ab77b7dbB4fa7e017BC15090b2163221420282"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470"), +}; + +pub static HOPR: TokenInfo = TokenInfo { + name: "HOPR", + symbol: "HOPR", + decimals: 18, + contract: address!("0xF5581dFeFD8Fb0e4aeC526bE659CFaB1f8c781dA"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14061/thumb/Shared_HOPR_logo_512px.png?1614073468"), +}; + +pub static IDEX: TokenInfo = TokenInfo { + name: "IDEX", + symbol: "IDEX", + decimals: 18, + contract: address!("0xB705268213D593B8FD88d3FDEFF93AFF5CbDcfAE"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2565/thumb/logomark-purple-286x286.png?1638362736"), +}; + +pub static ILLUVIUM: TokenInfo = TokenInfo { + name: "Illuvium", + symbol: "ILV", + decimals: 18, + contract: address!("0x767FE9EDC9E0dF98E07454847909b5E959D7ca0E"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14468/large/ILV.JPG"), +}; + +pub static IMMUNEFI: TokenInfo = TokenInfo { + name: "ImmuneFi", + symbol: "IMU", + decimals: 18, + contract: address!("0xb48c6B24f36307c7A1f2a9281E978a9ef2902BA5"), + chain: 1, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/39429.png"), +}; + +pub static IMMUTABLE_X: TokenInfo = TokenInfo { + name: "Immutable X", + symbol: "IMX", + decimals: 18, + contract: address!("0xF57e7e7C23978C3cAEC3C3548E3D615c346e79fF"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/17233/thumb/imx.png?1636691817"), +}; + +pub static INDEX_COOPERATIVE: TokenInfo = TokenInfo { + name: "Index Cooperative", + symbol: "INDEX", + decimals: 18, + contract: address!("0x0954906da0Bf32d5479e25f46056d22f08464cab"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12729/thumb/index.png?1634894321"), +}; + +pub static INJECTIVE: TokenInfo = TokenInfo { + name: "Injective", + symbol: "INJ", + decimals: 18, + contract: address!("0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237"), +}; + +pub static INVERSE_FINANCE: TokenInfo = TokenInfo { + name: "Inverse Finance", + symbol: "INV", + decimals: 18, + contract: address!("0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14205/thumb/inverse_finance.jpg?1614921871"), +}; + +pub static INFINEX: TokenInfo = TokenInfo { + name: "Infinex", + symbol: "INX", + decimals: 18, + contract: address!("0xdeF1b2D939EdC0E4d35806c59b3166F790175afe"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/70868/large/infinex.png?1764322875"), +}; + +pub static IOTEX: TokenInfo = TokenInfo { + name: "IoTeX", + symbol: "IOTX", + decimals: 18, + contract: address!("0x6fB3e0A217407EFFf7Ca062D46c26E5d60a14d69"), + chain: 1, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/2777.png"), +}; + +pub static IRYS: TokenInfo = TokenInfo { + name: "Irys", + symbol: "IRYS", + decimals: 18, + contract: address!("0x50f41F589aFACa2EF41FDF590FE7b90cD26DEe64"), + chain: 1, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/38978.png"), +}; + +pub static GEOJAM: TokenInfo = TokenInfo { + name: "Geojam", + symbol: "JAM", + decimals: 18, + contract: address!("0x23894DC9da6c94ECb439911cAF7d337746575A72"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/24648/thumb/ey40AzBN_400x400.jpg?1648507272"), +}; + +pub static JASMYCOIN: TokenInfo = TokenInfo { + name: "JasmyCoin", + symbol: "JASMY", + decimals: 18, + contract: address!("0x7420B4b9a0110cdC71fB720908340C03F9Bc03EC"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13876/thumb/JASMY200x200.jpg?1612473259"), +}; + +pub static JUPITER: TokenInfo = TokenInfo { + name: "Jupiter", + symbol: "JUP", + decimals: 18, + contract: address!("0x4B1E80cAC91e2216EEb63e29B957eB91Ae9C2Be8"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/10351/thumb/logo512.png?1632480932"), +}; + +pub static KEEP_NETWORK: TokenInfo = TokenInfo { + name: "Keep Network", + symbol: "KEEP", + decimals: 18, + contract: address!("0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/3373/thumb/IuNzUb5b_400x400.jpg?1589526336"), +}; + +pub static KERNELDAO: TokenInfo = TokenInfo { + name: "KernelDAO", + symbol: "KERNEL", + decimals: 18, + contract: address!("0x3f80B1c54Ae920Be41a77f8B902259D48cf24cCf"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54326/large/Kernel_token_logo_2x.png?1739827205"), +}; + +pub static SELFKEY: TokenInfo = TokenInfo { + name: "SelfKey", + symbol: "KEY", + decimals: 18, + contract: address!("0x4CC19356f2D37338b9802aa8E8fc58B0373296E7"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2034/thumb/selfkey.png?1548608934"), +}; + +pub static KITE: TokenInfo = TokenInfo { + name: "Kite", + symbol: "KITE", + decimals: 18, + contract: address!("0x904567252D8F48555b7447c67dCA23F0372E16be"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/70426/large/KITE-ICON.png?1762328605"), +}; + +pub static KYBER_NETWORK_CRYSTAL: TokenInfo = TokenInfo { + name: "Kyber Network Crystal", + symbol: "KNC", + decimals: 18, + contract: address!("0xdd974D5C2e2928deA5F71b9825b8b646686BD200"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png"), +}; + +pub static KEEP3RV1: TokenInfo = TokenInfo { + name: "Keep3rV1", + symbol: "KP3R", + decimals: 18, + contract: address!("0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12966/thumb/kp3r_logo.jpg?1607057458"), +}; + +pub static KRYLL: TokenInfo = TokenInfo { + name: "KRYLL", + symbol: "KRL", + decimals: 18, + contract: address!("0x464eBE77c293E473B48cFe96dDCf88fcF7bFDAC0"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979"), +}; + +pub static KUJIRA: TokenInfo = TokenInfo { + name: "Kujira", + symbol: "KUJI", + decimals: 6, + contract: address!("0x96543ef8d2C75C26387c1a319ae69c0BEE6f3fe7"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png"), +}; + +pub static LAYER3: TokenInfo = TokenInfo { + name: "Layer3", + symbol: "L3", + decimals: 18, + contract: address!("0x88909D489678dD17aA6D9609F89B0419Bf78FD9a"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/37768/large/Square.png"), +}; + +pub static LAGRANGE: TokenInfo = TokenInfo { + name: "Lagrange", + symbol: "LA", + decimals: 18, + contract: address!("0x0fc2a55d5BD13033f1ee0cdd11f60F7eFe66f467"), + chain: 1, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/36510.png"), +}; + +pub static LCX: TokenInfo = TokenInfo { + name: "LCX", + symbol: "LCX", + decimals: 18, + contract: address!("0x037A54AaB062628C9Bbae1FDB1583c195585fe41"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/9985/thumb/zRPSu_0o_400x400.jpg?1574327008"), +}; + +pub static LIDO_DAO: TokenInfo = TokenInfo { + name: "Lido DAO", + symbol: "LDO", + decimals: 18, + contract: address!("0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644"), +}; + +pub static LINEA: TokenInfo = TokenInfo { + name: "Linea", + symbol: "LINEA", + decimals: 18, + contract: address!("0x1789e0043623282D5DCc7F213d703C6D8BAfBB04"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/68507/large/linea-logo.jpeg?1756025484"), +}; + +pub static CHAINLINK_TOKEN: TokenInfo = TokenInfo { + name: "ChainLink Token", + symbol: "LINK", + decimals: 18, + contract: address!("0x514910771AF9Ca656af840dff83E8264EcF986CA"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), +}; + +pub static LITENTRY: TokenInfo = TokenInfo { + name: "Litentry", + symbol: "LIT", + decimals: 18, + contract: address!("0xb59490aB09A0f526Cc7305822aC65f2Ab12f9723"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13825/large/logo_200x200.png"), +}; + +pub static LIGHTER: TokenInfo = TokenInfo { + name: "Lighter", + symbol: "LIT", + decimals: 18, + contract: address!("0x232CE3bd40fCd6f80f3d55A522d03f25Df784Ee2"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/71121/large/lighter.png?1765888098"), +}; + +pub static LEAGUE_OF_KINGDOMS: TokenInfo = TokenInfo { + name: "League of Kingdoms", + symbol: "LOKA", + decimals: 18, + contract: address!("0x61E90A50137E1F645c9eF4a0d3A4f01477738406"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/22572/thumb/loka_64pix.png?1642643271"), +}; + +pub static LOOM_NETWORK: TokenInfo = TokenInfo { + name: "Loom Network", + symbol: "LOOM", + decimals: 18, + contract: address!("0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0/logo.png"), +}; + +pub static LIVEPEER: TokenInfo = TokenInfo { + name: "Livepeer", + symbol: "LPT", + decimals: 18, + contract: address!("0x58b6A8A3302369DAEc383334672404Ee733aB239"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/7137/thumb/logo-circle-green.png?1619593365"), +}; + +pub static LIQUITY: TokenInfo = TokenInfo { + name: "Liquity", + symbol: "LQTY", + decimals: 18, + contract: address!("0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180"), +}; + +pub static LOOPRINGCOIN_V2: TokenInfo = TokenInfo { + name: "LoopringCoin V2", + symbol: "LRC", + decimals: 18, + contract: address!("0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png"), +}; + +pub static BLOCKLORDS: TokenInfo = TokenInfo { + name: "BLOCKLORDS", + symbol: "LRDS", + decimals: 18, + contract: address!("0xd0a6053f087E87a25dC60701ba6E663b1a548E85"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/34775/standard/LRDS_PNG.png"), +}; + +pub static LIQUID_STAKED_ETH: TokenInfo = TokenInfo { + name: "Liquid Staked ETH", + symbol: "LSETH", + decimals: 18, + contract: address!("0x8c1BEd5b9a0928467c9B1341Da1D7BD5e10b6549"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/28848/large/LsETH-receipt-token-circle.png?1696527824"), +}; + +pub static LISK: TokenInfo = TokenInfo { + name: "Lisk", + symbol: "LSK", + decimals: 18, + contract: address!("0x6033F7f88332B8db6ad452B7C6D5bB643990aE3f"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/385/large/Lisk_logo.png?1722338450"), +}; + +pub static LIQUITY_USD: TokenInfo = TokenInfo { + name: "Liquity USD", + symbol: "LUSD", + decimals: 18, + contract: address!("0x5f98805A4E8be255a32880FDeC7F6728C6568bA0"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327"), +}; + +pub static DECENTRALAND: TokenInfo = TokenInfo { + name: "Decentraland", + symbol: "MANA", + decimals: 18, + contract: address!("0x0F5D2fB29fb7d3CFeE444a200298f468908cC942"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745"), +}; + +pub static MASK_NETWORK: TokenInfo = TokenInfo { + name: "Mask Network", + symbol: "MASK", + decimals: 18, + contract: address!("0x69af81e73A73B40adF4f3d4223Cd9b1ECE623074"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316"), +}; + +pub static MATH: TokenInfo = TokenInfo { + name: "MATH", + symbol: "MATH", + decimals: 18, + contract: address!("0x08d967bb0134F2d07f7cfb6E246680c53927DD30"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590"), +}; + +pub static POLYGON: TokenInfo = TokenInfo { + name: "Polygon", + symbol: "MATIC", + decimals: 18, + contract: address!("0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), +}; + +pub static MERIT_CIRCLE: TokenInfo = TokenInfo { + name: "Merit Circle", + symbol: "MC", + decimals: 18, + contract: address!("0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/19304/thumb/Db4XqML.png?1634972154"), +}; + +pub static MOSS_CARBON_CREDIT: TokenInfo = TokenInfo { + name: "Moss Carbon Credit", + symbol: "MCO2", + decimals: 18, + contract: address!("0xfC98e825A2264D890F9a1e68ed50E1526abCcacD"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14414/thumb/ENtxnThA_400x400.jpg?1615948522"), +}; + +pub static MEASURABLE_DATA_TOKEN: TokenInfo = TokenInfo { + name: "Measurable Data Token", + symbol: "MDT", + decimals: 18, + contract: address!("0x814e0908b12A99FeCf5BC101bB5d0b8B5cDf7d26"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2441/thumb/mdt_logo.png?1569813574"), +}; + +pub static MEMECOIN: TokenInfo = TokenInfo { + name: "Memecoin", + symbol: "MEME", + decimals: 18, + contract: address!("0xb131f4A55907B10d1F0A50d8ab8FA09EC342cd74"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/32528/large/memecoin_(2).png"), +}; + +pub static METIS: TokenInfo = TokenInfo { + name: "Metis", + symbol: "METIS", + decimals: 18, + contract: address!("0x9E32b13ce7f2E80A01932B42553652E053D6ed8e"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312"), +}; + +pub static MAGIC_INTERNET_MONEY: TokenInfo = TokenInfo { + name: "Magic Internet Money", + symbol: "MIM", + decimals: 18, + contract: address!("0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612"), +}; + +pub static MIRROR_PROTOCOL: TokenInfo = TokenInfo { + name: "Mirror Protocol", + symbol: "MIR", + decimals: 18, + contract: address!("0x09a3EcAFa817268f77BE1283176B946C4ff2E608"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13295/thumb/mirror_logo_transparent.png?1611554658"), +}; + +pub static MAKER: TokenInfo = TokenInfo { + name: "Maker", + symbol: "MKR", + decimals: 18, + contract: address!("0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png"), +}; + +pub static MELON: TokenInfo = TokenInfo { + name: "Melon", + symbol: "MLN", + decimals: 18, + contract: address!("0xec67005c4E498Ec7f55E092bd1d35cbC47C91892"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295"), +}; + +pub static MANTLE: TokenInfo = TokenInfo { + name: "Mantle", + symbol: "MNT", + decimals: 18, + contract: address!("0x3c3a81e81dc49A522A592e7622A7E711c06bf354"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/30980/large/Mantle-Logo-mark.png?1739213200"), +}; + +pub static MOG_COIN: TokenInfo = TokenInfo { + name: "Mog Coin", + symbol: "MOG", + decimals: 18, + contract: address!("0xaaeE1A9723aaDB7afA2810263653A34bA2C21C7a"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/31059/large/MOG_LOGO_200x200.png"), +}; + +pub static MONAVALE: TokenInfo = TokenInfo { + name: "Monavale", + symbol: "MONA", + decimals: 18, + contract: address!("0x275f5Ad03be0Fa221B4C6649B8AeE09a42D9412A"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13298/thumb/monavale_logo.jpg?1607232721"), +}; + +pub static MORPHO_TOKEN: TokenInfo = TokenInfo { + name: "Morpho Token", + symbol: "MORPHO", + decimals: 18, + contract: address!("0x58D97B57BB95320F9a05dC918Aef65434969c2B2"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/29837/large/Morpho-token-icon.png?1726771230"), +}; + +pub static MOVEMENT: TokenInfo = TokenInfo { + name: "Movement", + symbol: "MOVE", + decimals: 8, + contract: address!("0x3073f7aAA4DB83f95e9FFf17424F71D4751a3073"), + chain: 1, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/32452.png"), +}; + +pub static MAPLE: TokenInfo = TokenInfo { + name: "Maple", + symbol: "MPL", + decimals: 18, + contract: address!("0x33349B282065b0284d756F0577FB39c158F935e6"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14097/thumb/photo_2021-05-03_14.20.41.jpeg?1620022863"), +}; + +pub static METAL: TokenInfo = TokenInfo { + name: "Metal", + symbol: "MTL", + decimals: 8, + contract: address!("0xF433089366899D83a9f26A773D59ec7eCF30355e"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/763/thumb/Metal.png?1592195010"), +}; + +pub static MULTICHAIN: TokenInfo = TokenInfo { + name: "Multichain", + symbol: "MULTI", + decimals: 18, + contract: address!("0x65Ef703f5594D2573eb71Aaf55BC0CB548492df4"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238"), +}; + +pub static MSTABLE_USD: TokenInfo = TokenInfo { + name: "mStable USD", + symbol: "MUSD", + decimals: 18, + contract: address!("0xe2f2a5C287993345a840Db3B0845fbC70f5935a5"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11576/thumb/mStable_USD.png?1595591803"), +}; + +pub static MUSE_DAO: TokenInfo = TokenInfo { + name: "Muse DAO", + symbol: "MUSE", + decimals: 18, + contract: address!("0xB6Ca7399B4F9CA56FC27cBfF44F4d2e4Eef1fc81"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13230/thumb/muse_logo.png?1606460453"), +}; + +pub static GENSOKISHI_METAVERSE: TokenInfo = TokenInfo { + name: "GensoKishi Metaverse", + symbol: "MV", + decimals: 18, + contract: address!("0xAE788F80F2756A86aa2F410C651F2aF83639B95b"), + chain: 1, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/17704.png"), +}; + +pub static MXC: TokenInfo = TokenInfo { + name: "MXC", + symbol: "MXC", + decimals: 18, + contract: address!("0x5Ca381bBfb58f0092df149bD3D243b08B9a8386e"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/4604/thumb/mxc.png?1655534336"), +}; + +pub static POLYSWARM: TokenInfo = TokenInfo { + name: "PolySwarm", + symbol: "NCT", + decimals: 18, + contract: address!("0x9E46A38F5DaaBe8683E10793b06749EEF7D733d1"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2843/thumb/ImcYCVfX_400x400.jpg?1628519767"), +}; + +pub static NEIRO: TokenInfo = TokenInfo { + name: "Neiro", + symbol: "Neiro", + decimals: 9, + contract: address!("0x812Ba41e071C7b7fA4EBcFB62dF5F45f6fA853Ee"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/39488/large/neiro.jpg?1731449567"), +}; + +pub static NEWTON: TokenInfo = TokenInfo { + name: "Newton", + symbol: "NEWT", + decimals: 18, + contract: address!("0xD0eC028a3D21533Fdd200838F39c85B03679285D"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/66819/large/newton.jpg?1750642513"), +}; + +pub static NKN: TokenInfo = TokenInfo { + name: "NKN", + symbol: "NKN", + decimals: 18, + contract: address!("0x5Cf04716BA20127F1E2297AdDCf4B5035000c9eb"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/3375/thumb/nkn.png?1548329212"), +}; + +pub static NUMERAIRE: TokenInfo = TokenInfo { + name: "Numeraire", + symbol: "NMR", + decimals: 18, + contract: address!("0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png"), +}; + +pub static NOMINA: TokenInfo = TokenInfo { + name: "Nomina", + symbol: "NOM", + decimals: 18, + contract: address!("0x6e6F6d696e61decd6605bD4a57836c5DB6923340"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/69687/large/nomina_400x400.jpg?1759312531"), +}; + +pub static NUCYPHER: TokenInfo = TokenInfo { + name: "NuCypher", + symbol: "NU", + decimals: 18, + contract: address!("0x4fE83213D56308330EC302a8BD641f1d0113A4Cc"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/3318/thumb/photo1198982838879365035.jpg?1547037916"), +}; + +pub static OCEAN_PROTOCOL: TokenInfo = TokenInfo { + name: "Ocean Protocol", + symbol: "OCEAN", + decimals: 18, + contract: address!("0x967da4048cD07aB37855c090aAF366e4ce1b9F48"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686"), +}; + +pub static ORIGIN_PROTOCOL: TokenInfo = TokenInfo { + name: "Origin Protocol", + symbol: "OGN", + decimals: 18, + contract: address!("0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878"), +}; + +pub static OMG_NETWORK: TokenInfo = TokenInfo { + name: "OMG Network", + symbol: "OMG", + decimals: 18, + contract: address!("0xd26114cd6EE289AccF82350c8d8487fedB8A0C07"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/776/thumb/OMG_Network.jpg?1591167168"), +}; + +pub static OMNI_NETWORK: TokenInfo = TokenInfo { + name: "Omni Network", + symbol: "OMNI", + decimals: 18, + contract: address!("0x36E66fbBce51e4cD5bd3C62B637Eb411b18949D4"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/36465/standard/Symbol-Color.png?1711511095"), +}; + +pub static ONDO_FINANCE: TokenInfo = TokenInfo { + name: "Ondo Finance", + symbol: "ONDO", + decimals: 18, + contract: address!("0xfAbA6f8e4a5E8Ab82F62fe7C39859FA577269BE3"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/26580/standard/ONDO.png?1696525656"), +}; + +pub static ORCA_ALLIANCE: TokenInfo = TokenInfo { + name: "ORCA Alliance", + symbol: "ORCA", + decimals: 18, + contract: address!("0x6F59e0461Ae5E2799F1fB3847f05a63B16d0DbF8"), + chain: 1, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/5183.png"), +}; + +pub static ORION_PROTOCOL: TokenInfo = TokenInfo { + name: "Orion Protocol", + symbol: "ORN", + decimals: 8, + contract: address!("0x0258F474786DdFd37ABCE6df6BBb1Dd5dfC4434a"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11841/thumb/orion_logo.png?1594943318"), +}; + +pub static ORCHID: TokenInfo = TokenInfo { + name: "Orchid", + symbol: "OXT", + decimals: 18, + contract: address!("0x4575f41308EC1483f3d399aa9a2826d74Da13Deb"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4575f41308EC1483f3d399aa9a2826d74Da13Deb/logo.png"), +}; + +pub static PAYPEREX: TokenInfo = TokenInfo { + name: "PayperEx", + symbol: "PAX", + decimals: 18, + contract: address!("0xc1D204d77861dEf49b6E769347a883B15EC397Ff"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1601/thumb/pax.png?1547035800"), +}; + +pub static PAX_GOLD: TokenInfo = TokenInfo { + name: "PAX Gold", + symbol: "PAXG", + decimals: 18, + contract: address!("0x45804880De22913dAFE09f4980848ECE6EcbAf78"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/9519/thumb/paxg.PNG?1568542565"), +}; + +pub static PLAYDAPP: TokenInfo = TokenInfo { + name: "PlayDapp", + symbol: "PDA", + decimals: 18, + contract: address!("0x0D3CbED3f69EE050668ADF3D9Ea57241cBa33A2B"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14316/standard/PDA-symbol.png?1710234068"), +}; + +pub static PENDLE: TokenInfo = TokenInfo { + name: "Pendle", + symbol: "PENDLE", + decimals: 18, + contract: address!("0x808507121B80c02388fAd14726482e061B8da827"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728"), +}; + +pub static PEPE: TokenInfo = TokenInfo { + name: "Pepe", + symbol: "PEPE", + decimals: 18, + contract: address!("0x6982508145454Ce325dDbE47a25d4ec3d2311933"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725"), +}; + +pub static PERPETUAL_PROTOCOL: TokenInfo = TokenInfo { + name: "Perpetual Protocol", + symbol: "PERP", + decimals: 18, + contract: address!("0xbC396689893D065F41bc2C6EcbeE5e0085233447"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), +}; + +pub static PIRATE_NATION: TokenInfo = TokenInfo { + name: "Pirate Nation", + symbol: "PIRATE", + decimals: 18, + contract: address!("0x7613C48E0cd50E42dD9Bf0f6c235063145f6f8DC"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/38524/standard/_Pirate_Transparent_200x200.png"), +}; + +pub static PLUTON: TokenInfo = TokenInfo { + name: "Pluton", + symbol: "PLU", + decimals: 18, + contract: address!("0xD8912C10681D8B21Fd3742244f44658dBA12264E"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1241/thumb/pluton.png?1548331624"), +}; + +pub static PLUME: TokenInfo = TokenInfo { + name: "Plume", + symbol: "PLUME", + decimals: 18, + contract: address!("0x4C1746A800D224393fE2470C70A35717eD4eA5F1"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/53623/large/plume-token.png?1736896935"), +}; + +pub static POLYGON_ECOSYSTEM_TOKEN: TokenInfo = TokenInfo { + name: "Polygon Ecosystem Token", + symbol: "POL", + decimals: 18, + contract: address!("0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/32440/large/polygon.png?1698233684"), +}; + +pub static POLKASTARTER: TokenInfo = TokenInfo { + name: "Polkastarter", + symbol: "POLS", + decimals: 18, + contract: address!("0x83e6f1E41cdd28eAcEB20Cb649155049Fac3D5Aa"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702"), +}; + +pub static POLYMATH: TokenInfo = TokenInfo { + name: "Polymath", + symbol: "POLY", + decimals: 18, + contract: address!("0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034"), +}; + +pub static MARLIN: TokenInfo = TokenInfo { + name: "Marlin", + symbol: "POND", + decimals: 18, + contract: address!("0x57B946008913B82E4dF85f501cbAeD910e58D26C"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/8903/thumb/POND_200x200.png?1622515451"), +}; + +pub static PORTAL: TokenInfo = TokenInfo { + name: "Portal", + symbol: "PORTAL", + decimals: 18, + contract: address!("0x1Bbe973BeF3a977Fc51CbED703E8ffDEfE001Fed"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/35436/standard/portal.jpeg"), +}; + +pub static POWER_LEDGER: TokenInfo = TokenInfo { + name: "Power Ledger", + symbol: "POWR", + decimals: 6, + contract: address!("0x595832F8FC6BF59c85C527fEC3740A1b7a361269"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1104/thumb/power-ledger.png?1547035082"), +}; + +pub static PRIME: TokenInfo = TokenInfo { + name: "Prime", + symbol: "PRIME", + decimals: 18, + contract: address!("0xb23d80f5FefcDDaa212212F028021B41DEd428CF"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222"), +}; + +pub static PROPY: TokenInfo = TokenInfo { + name: "Propy", + symbol: "PRO", + decimals: 8, + contract: address!("0x226bb599a12C826476e3A771454697EA52E9E220"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/869/thumb/propy.png?1548332100"), +}; + +pub static SUCCINCT: TokenInfo = TokenInfo { + name: "Succinct", + symbol: "PROVE", + decimals: 18, + contract: address!("0x6BEF15D938d4E72056AC92Ea4bDD0D76B1C4ad29"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/67905/large/succinct-logo.png?1754228574"), +}; + +pub static PARSIQ: TokenInfo = TokenInfo { + name: "PARSIQ", + symbol: "PRQ", + decimals: 18, + contract: address!("0x362bc847A3a9637d3af6624EeC853618a43ed7D2"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280"), +}; + +pub static PSTAKE_FINANCE: TokenInfo = TokenInfo { + name: "pSTAKE Finance", + symbol: "PSTAKE", + decimals: 18, + contract: address!("0xfB5c6815cA3AC72Ce9F5006869AE67f18bF77006"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/23931/thumb/PSTAKE_Dark.png?1645709930"), +}; + +pub static PUFFER_FINANCE: TokenInfo = TokenInfo { + name: "Puffer Finance", + symbol: "PUFFER", + decimals: 18, + contract: address!("0x4d1C297d39C5c1277964D0E3f8Aa901493664530"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/50630/large/puffer.jpg?1728545297"), +}; + +pub static PAYPAL_USD: TokenInfo = TokenInfo { + name: "PayPal USD", + symbol: "PYUSD", + decimals: 6, + contract: address!("0x6c3ea9036406852006290770BEdFcAbA0e23A0e8"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/31212/large/PYUSD_Logo_%282%29.png?1691458314"), +}; + +pub static QUANT: TokenInfo = TokenInfo { + name: "Quant", + symbol: "QNT", + decimals: 18, + contract: address!("0x4a220E6096B25EADb88358cb44068A3248254675"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/3370/thumb/5ZOu7brX_400x400.jpg?1612437252"), +}; + +pub static QREDO: TokenInfo = TokenInfo { + name: "Qredo", + symbol: "QRDO", + decimals: 8, + contract: address!("0x4123a133ae3c521FD134D7b13A2dEC35b56c2463"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/17541/thumb/qrdo.png?1630637735"), +}; + +pub static QUANTSTAMP: TokenInfo = TokenInfo { + name: "Quantstamp", + symbol: "QSP", + decimals: 18, + contract: address!("0x99ea4dB9EE77ACD40B119BD1dC4E33e1C070b80d"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1219/thumb/0_E0kZjb4dG4hUnoDD_.png?1604815917"), +}; + +pub static QUICKSWAP: TokenInfo = TokenInfo { + name: "Quickswap", + symbol: "QUICK", + decimals: 18, + contract: address!("0x6c28AeF8977c9B773996d0e8376d2EE379446F2f"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13970/thumb/1_pOU6pBMEmiL-ZJVb0CYRjQ.png?1613386659"), +}; + +pub static RADICLE: TokenInfo = TokenInfo { + name: "Radicle", + symbol: "RAD", + decimals: 18, + contract: address!("0x31c8EAcBFFdD875c74b94b077895Bd78CF1E64A3"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14013/thumb/radicle.png?1614402918"), +}; + +pub static RAI_REFLEX_INDEX: TokenInfo = TokenInfo { + name: "Rai Reflex Index", + symbol: "RAI", + decimals: 18, + contract: address!("0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334"), +}; + +pub static SUPERRARE: TokenInfo = TokenInfo { + name: "SuperRare", + symbol: "RARE", + decimals: 18, + contract: address!("0xba5BDe662c17e2aDFF1075610382B9B691296350"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/17753/thumb/RARE.jpg?1629220534"), +}; + +pub static RARIBLE: TokenInfo = TokenInfo { + name: "Rarible", + symbol: "RARI", + decimals: 18, + contract: address!("0xFca59Cd816aB1eaD66534D82bc21E7515cE441CF"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11845/thumb/Rari.png?1594946953"), +}; + +pub static RUBIC: TokenInfo = TokenInfo { + name: "Rubic", + symbol: "RBC", + decimals: 18, + contract: address!("0xA4EED63db85311E22dF4473f87CcfC3DaDCFA3E3"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12629/thumb/200x200.png?1607952509"), +}; + +pub static RIBBON_FINANCE: TokenInfo = TokenInfo { + name: "Ribbon Finance", + symbol: "RBN", + decimals: 18, + contract: address!("0x6123B0049F904d730dB3C36a31167D9d4121fA6B"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/15823/thumb/RBN_64x64.png?1633529723"), +}; + +pub static REDSTONE: TokenInfo = TokenInfo { + name: "Redstone", + symbol: "RED", + decimals: 18, + contract: address!("0xc43C6bfeDA065fE2c4c11765Bf838789bd0BB5dE"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/53640/large/RedStone_Logo_New_White.png?1740640919"), +}; + +pub static REPUBLIC_TOKEN: TokenInfo = TokenInfo { + name: "Republic Token", + symbol: "REN", + decimals: 18, + contract: address!("0x408e41876cCCDC0F92210600ef50372656052a38"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png"), +}; + +pub static REPUTATION_AUGUR_V1: TokenInfo = TokenInfo { + name: "Reputation Augur v1", + symbol: "REP", + decimals: 18, + contract: address!("0x1985365e9f78359a9B6AD760e32412f4a445E862"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1985365e9f78359a9B6AD760e32412f4a445E862/logo.png"), +}; + +pub static REPUTATION_AUGUR_V2: TokenInfo = TokenInfo { + name: "Reputation Augur v2", + symbol: "REPv2", + decimals: 18, + contract: address!("0x221657776846890989a759BA2973e427DfF5C9bB"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x221657776846890989a759BA2973e427DfF5C9bB/logo.png"), +}; + +pub static REQUEST: TokenInfo = TokenInfo { + name: "Request", + symbol: "REQ", + decimals: 18, + contract: address!("0x8f8221aFbB33998d8584A2B05749bA73c37a938a"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1031/thumb/Request_icon_green.png?1643250951"), +}; + +pub static REVV: TokenInfo = TokenInfo { + name: "REVV", + symbol: "REVV", + decimals: 18, + contract: address!("0x557B933a7C2c45672B610F8954A3deB39a51A8Ca"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12373/thumb/REVV_TOKEN_Refined_2021_%281%29.png?1627652390"), +}; + +pub static RENZO: TokenInfo = TokenInfo { + name: "Renzo", + symbol: "REZ", + decimals: 18, + contract: address!("0x3B50805453023a91a8bf641e279401a0b23FA6F9"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/37327/standard/renzo_200x200.png?1714025012"), +}; + +pub static RARI_GOVERNANCE_TOKEN: TokenInfo = TokenInfo { + name: "Rari Governance Token", + symbol: "RGT", + decimals: 18, + contract: address!("0xD291E7a03283640FDc51b121aC401383A46cC623"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014"), +}; + +pub static IEXEC_RLC: TokenInfo = TokenInfo { + name: "iExec RLC", + symbol: "RLC", + decimals: 9, + contract: address!("0x607F4C5BB672230e8672085532f7e901544a7375"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1604543202"), +}; + +pub static RAYLS: TokenInfo = TokenInfo { + name: "Rayls", + symbol: "RLS", + decimals: 18, + contract: address!("0xB5F7b021a78f470d31D762C1DDA05ea549904fbd"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/70091/large/cgrLS.png?1760541265"), +}; + +pub static RLUSD: TokenInfo = TokenInfo { + name: "RLUSD", + symbol: "RLUSD", + decimals: 18, + contract: address!("0x8292Bb45bf1Ee4d140127049757C2E0fF06317eD"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/39651/large/RLUSD_200x200_(1).png?1727376633"), +}; + +pub static RALLY: TokenInfo = TokenInfo { + name: "Rally", + symbol: "RLY", + decimals: 18, + contract: address!("0xf1f955016EcbCd7321c7266BccFB96c68ea5E49b"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12843/thumb/image.png?1611212077"), +}; + +pub static RENDER_TOKEN: TokenInfo = TokenInfo { + name: "Render Token", + symbol: "RNDR", + decimals: 18, + contract: address!("0x6De037ef9aD2725EB40118Bb1702EBb27e4Aeb24"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11636/thumb/rndr.png?1638840934"), +}; + +pub static ROBO_TOKEN: TokenInfo = TokenInfo { + name: "ROBO Token", + symbol: "ROBO", + decimals: 18, + contract: address!("0x32b4d049fE4c888D2b92eEcaf729F44DF6B1F36E"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/102172005/large/ROBO.png?1770925648"), +}; + +pub static ROOK: TokenInfo = TokenInfo { + name: "Rook", + symbol: "ROOK", + decimals: 18, + contract: address!("0xfA5047c9c78B8877af97BDcb85Db743fD7313d4a"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13005/thumb/keeper_dao_logo.jpg?1604316506"), +}; + +pub static ROCKET_POOL_PROTOCOL: TokenInfo = TokenInfo { + name: "Rocket Pool Protocol", + symbol: "RPL", + decimals: 18, + contract: address!("0xD33526068D116cE69F19A9ee46F0bd304F21A51f"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/2090/large/rocket_pool_%28RPL%29.png?1696503058"), +}; + +pub static RESERVE_RIGHTS: TokenInfo = TokenInfo { + name: "Reserve Rights", + symbol: "RSR", + decimals: 18, + contract: address!("0x320623b8E4fF03373931769A31Fc52A4E78B5d70"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856"), +}; + +pub static SAFE: TokenInfo = TokenInfo { + name: "Safe", + symbol: "SAFE", + decimals: 18, + contract: address!("0x5aFE3855358E112B5647B952709E6165e1c1eEEe"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/27032/standard/Artboard_1_copy_8circle-1.png?1696526084"), +}; + +pub static THE_SANDBOX: TokenInfo = TokenInfo { + name: "The Sandbox", + symbol: "SAND", + decimals: 18, + contract: address!("0x3845badAde8e6dFF049820680d1F14bD3903a5d0"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1597397942"), +}; + +pub static STADER: TokenInfo = TokenInfo { + name: "Stader", + symbol: "SD", + decimals: 18, + contract: address!("0x30D20208d987713f46DFD34EF128Bb16C404D10f"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png"), +}; + +pub static SENTIENT: TokenInfo = TokenInfo { + name: "Sentient", + symbol: "SENT", + decimals: 18, + contract: address!("0x56A3BA04E95d34268A19b2a4474DC979baBDaf76"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/70508/large/SENTIENT-Icon-BlushForce-L.png?1762267532"), +}; + +pub static SHIBA_INU: TokenInfo = TokenInfo { + name: "Shiba Inu", + symbol: "SHIB", + decimals: 18, + contract: address!("0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11939/thumb/shiba.png?1622619446"), +}; + +pub static SHPING: TokenInfo = TokenInfo { + name: "Shping", + symbol: "SHPING", + decimals: 18, + contract: address!("0x7C84e62859D0715eb77d1b1C4154Ecd6aBB21BEC"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2588/thumb/r_yabKKi_400x400.jpg?1639470164"), +}; + +pub static SKALE: TokenInfo = TokenInfo { + name: "SKALE", + symbol: "SKL", + decimals: 18, + contract: address!("0x00c83aeCC790e8a4453e5dD3B0B4b3680501a7A7"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13245/thumb/SKALE_token_300x300.png?1606789574"), +}; + +pub static SKY_GOVERNANCE_TOKEN: TokenInfo = TokenInfo { + name: "SKY Governance Token", + symbol: "SKY", + decimals: 18, + contract: address!("0x56072C95FAA701256059aa122697B133aDEd9279"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/39925/large/sky.jpg?1724827980"), +}; + +pub static SMOOTH_LOVE_POTION: TokenInfo = TokenInfo { + name: "Smooth Love Potion", + symbol: "SLP", + decimals: 0, + contract: address!("0xCC8Fa225D80b9c7D42F96e9570156c65D6cAAa25"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/10366/thumb/SLP.png?1578640057"), +}; + +pub static STATUS: TokenInfo = TokenInfo { + name: "Status", + symbol: "SNT", + decimals: 18, + contract: address!("0x744d70FDBE2Ba4CF95131626614a1763DF805B9E"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778"), +}; + +pub static SYNTHETIX_NETWORK_TOKEN: TokenInfo = TokenInfo { + name: "Synthetix Network Token", + symbol: "SNX", + decimals: 18, + contract: address!("0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), +}; + +pub static UNISOCKS: TokenInfo = TokenInfo { + name: "Unisocks", + symbol: "SOCKS", + decimals: 18, + contract: address!("0x23B608675a2B2fB1890d3ABBd85c5775c51691d5"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/10717/thumb/qFrcoiM.png?1582525244"), +}; + +pub static SOL_WORMHOLE: TokenInfo = TokenInfo { + name: "SOL Wormhole ", + symbol: "SOL", + decimals: 9, + contract: address!("0xD31a59c85aE9D8edEFeC411D448f90841571b89c"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), +}; + +pub static SPELL_TOKEN: TokenInfo = TokenInfo { + name: "Spell Token", + symbol: "SPELL", + decimals: 18, + contract: address!("0x090185f2135308BaD17527004364eBcC2D37e5F6"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862"), +}; + +pub static SPARK: TokenInfo = TokenInfo { + name: "Spark", + symbol: "SPK", + decimals: 18, + contract: address!("0xc20059e0317DE91738d13af027DfC4a50781b066"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/38637/large/Spark-Logomark-RGB.png?1744878896"), +}; + +pub static SPX6900: TokenInfo = TokenInfo { + name: "SPX6900", + symbol: "SPX", + decimals: 8, + contract: address!("0xE0f63A424a4439cBE457D80E4f4b51aD25b2c56C"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083"), +}; + +pub static STARGATE_FINANCE: TokenInfo = TokenInfo { + name: "Stargate Finance", + symbol: "STG", + decimals: 18, + contract: address!("0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518"), +}; + +pub static STORJ_TOKEN: TokenInfo = TokenInfo { + name: "Storj Token", + symbol: "STORJ", + decimals: 8, + contract: address!("0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png"), +}; + +pub static STARKNET: TokenInfo = TokenInfo { + name: "Starknet", + symbol: "STRK", + decimals: 18, + contract: address!("0xCa14007Eff0dB1f8135f4C25B34De49AB0d42766"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/26433/standard/starknet.png?1696525507"), +}; + +pub static STOX: TokenInfo = TokenInfo { + name: "Stox", + symbol: "STX", + decimals: 18, + contract: address!("0x006BeA43Baa3f7A6f765F14f10A1a1b08334EF45"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1230/thumb/stox-token.png?1547035256"), +}; + +pub static SUKU: TokenInfo = TokenInfo { + name: "SUKU", + symbol: "SUKU", + decimals: 18, + contract: address!("0x0763fdCCF1aE541A5961815C0872A8c5Bc6DE4d7"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11969/thumb/UmfW5S6f_400x400.jpg?1596602238"), +}; + +pub static SUPERFARM: TokenInfo = TokenInfo { + name: "SuperFarm", + symbol: "SUPER", + decimals: 18, + contract: address!("0xe53EC727dbDEB9E2d5456c3be40cFF031AB40A55"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899"), +}; + +pub static SYNTH_SUSD: TokenInfo = TokenInfo { + name: "Synth sUSD", + symbol: "sUSD", + decimals: 18, + contract: address!("0x57Ab1ec28D129707052df4dF418D58a2D46d5f51"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765"), +}; + +pub static SUSHI: TokenInfo = TokenInfo { + name: "Sushi", + symbol: "SUSHI", + decimals: 18, + contract: address!("0x6B3595068778DD592e39A122f4f5a5cF09C90fE2"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), +}; + +pub static SWELL: TokenInfo = TokenInfo { + name: "Swell", + symbol: "SWELL", + decimals: 18, + contract: address!("0x0a6E7Ba5042B38349e437ec6Db6214AEC7B35676"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/28777/large/swell1.png?1727899715"), +}; + +pub static SWFTCOIN: TokenInfo = TokenInfo { + name: "SWFTCOIN", + symbol: "SWFTC", + decimals: 8, + contract: address!("0x0bb217E40F8a5Cb79Adf04E1aAb60E5abd0dfC1e"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2346/thumb/SWFTCoin.jpg?1618392022"), +}; + +pub static SWIPE: TokenInfo = TokenInfo { + name: "Swipe", + symbol: "SXP", + decimals: 18, + contract: address!("0x8CE9137d39326AD0cD6491fb5CC0CbA0e089b6A9"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/9368/thumb/swipe.png?1566792311"), +}; + +pub static SPACE_AND_TIME: TokenInfo = TokenInfo { + name: "Space and Time", + symbol: "SXT", + decimals: 18, + contract: address!("0xE6Bfd33F52d82Ccb5b37E16D3dD81f9FFDAbB195"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/55424/large/sxt-token_circle.jpg?1745935919"), +}; + +pub static SYLO: TokenInfo = TokenInfo { + name: "Sylo", + symbol: "SYLO", + decimals: 18, + contract: address!("0xf293d23BF2CDc05411Ca0edDD588eb1977e8dcd4"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/6430/thumb/SYLO.svg?1589527756"), +}; + +pub static SYNAPSE: TokenInfo = TokenInfo { + name: "Synapse", + symbol: "SYN", + decimals: 18, + contract: address!("0x0f2D719407FdBeFF09D87557AbB7232601FD9F29"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049"), +}; + +pub static SYRUP_TOKEN: TokenInfo = TokenInfo { + name: "Syrup Token", + symbol: "SYRUP", + decimals: 18, + contract: address!("0x643C4E15d7d62Ad0aBeC4a9BD4b001aA3Ef52d66"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/51232/standard/IMG_7420.png?1730831572"), +}; + +pub static THRESHOLD_NETWORK: TokenInfo = TokenInfo { + name: "Threshold Network", + symbol: "T", + decimals: 18, + contract: address!("0xCdF7028ceAB81fA0C6971208e83fa7872994beE5"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340"), +}; + +pub static TBTC: TokenInfo = TokenInfo { + name: "tBTC", + symbol: "tBTC", + decimals: 18, + contract: address!("0x18084fbA666a33d37592fA2633fD49a74DD93a88"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png"), +}; + +pub static TERM_FINANCE: TokenInfo = TokenInfo { + name: "Term Finance", + symbol: "TERM", + decimals: 18, + contract: address!("0xC3d21f79C3120A4fFda7A535f8005a7c297799bF"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/38142/large/terms.png?1716630303"), +}; + +pub static THEORIQ: TokenInfo = TokenInfo { + name: "Theoriq", + symbol: "THQ", + decimals: 18, + contract: address!("0xafFbe9a60F1F45E057FD9b6DC70004Bb0Ccc8b99"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/67759/large/thq.jpg?1753757049"), +}; + +pub static CHRONOTECH: TokenInfo = TokenInfo { + name: "ChronoTech", + symbol: "TIME", + decimals: 8, + contract: address!("0x485d17A6f1B8780392d53D64751824253011A260"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/604/thumb/time-32x32.png?1627130666"), +}; + +pub static ALIEN_WORLDS: TokenInfo = TokenInfo { + name: "Alien Worlds", + symbol: "TLM", + decimals: 4, + contract: address!("0x888888848B652B3E3a0f34c96E00EEC0F3a23F72"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14676/thumb/kY-C4o7RThfWrDQsLCAG4q4clZhBDDfJQVhWUEKxXAzyQYMj4Jmq1zmFwpRqxhAJFPOa0AsW_PTSshoPuMnXNwq3rU7Imp15QimXTjlXMx0nC088mt1rIwRs75GnLLugWjSllxgzvQ9YrP4tBgclK4_rb17hjnusGj_c0u2fx0AvVokjSNB-v2poTj0xT9BZRCbzRE3-lF1.jpg?1617700061"), +}; + +pub static TOKEMAK: TokenInfo = TokenInfo { + name: "Tokemak", + symbol: "TOKE", + decimals: 18, + contract: address!("0x2e9d63788249371f1DFC918a52f8d799F4a38C94"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/17495/thumb/tokemak-avatar-200px-black.png?1628131614"), +}; + +pub static TOKENFI: TokenInfo = TokenInfo { + name: "TokenFi", + symbol: "TOKEN", + decimals: 9, + contract: address!("0x4507cEf57C46789eF8d1a19EA45f4216bae2B528"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/32507/large/MAIN_TokenFi_logo_icon.png?1698918427"), +}; + +pub static TE_FOOD: TokenInfo = TokenInfo { + name: "TE FOOD", + symbol: "TONE", + decimals: 18, + contract: address!("0x2Ab6Bb8408ca3199B8Fa6C92d5b455F820Af03c4"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/2325/thumb/tec.png?1547036538"), +}; + +pub static ORIGINTRAIL: TokenInfo = TokenInfo { + name: "OriginTrail", + symbol: "TRAC", + decimals: 18, + contract: address!("0xaA7a9CA87d3694B5755f213B5D04094b8d0F0A6F"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/1877/thumb/TRAC.jpg?1635134367"), +}; + +pub static TELLOR: TokenInfo = TokenInfo { + name: "Tellor", + symbol: "TRB", + decimals: 18, + contract: address!("0x88dF592F8eb5D7Bd38bFeF7dEb0fBc02cf3778a0"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686"), +}; + +pub static TREEHOUSE_TOKEN: TokenInfo = TokenInfo { + name: "Treehouse Token", + symbol: "TREE", + decimals: 18, + contract: address!("0x77146784315Ba81904d654466968e3a7c196d1f3"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/67664/large/TREE_logo.png?1753601041"), +}; + +pub static TRIA: TokenInfo = TokenInfo { + name: "Tria", + symbol: "TRIA", + decimals: 18, + contract: address!("0x228bEC415adE4b61D7CaF0adf8C91EAc587BA369"), + chain: 1, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/39382.png"), +}; + +pub static TRIBE: TokenInfo = TokenInfo { + name: "Tribe", + symbol: "TRIBE", + decimals: 18, + contract: address!("0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/14575/thumb/tribe.PNG?1617487954"), +}; + +pub static TRUEFI: TokenInfo = TokenInfo { + name: "TrueFi", + symbol: "TRU", + decimals: 8, + contract: address!("0x4C19596f5aAfF459fA38B0f7eD92F11AE6543784"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13180/thumb/truefi_glyph_color.png?1617610941"), +}; + +pub static TURBO: TokenInfo = TokenInfo { + name: "Turbo", + symbol: "TURBO", + decimals: 18, + contract: address!("0xA35923162C49cF95e6BF26623385eb431ad920D3"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/30117/large/TurboMark-QL_200.png?1708079597"), +}; + +pub static THE_VIRTUA_KOLECT: TokenInfo = TokenInfo { + name: "The Virtua Kolect", + symbol: "TVK", + decimals: 18, + contract: address!("0xd084B83C305daFD76AE3E1b4E1F1fe2eCcCb3988"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13330/thumb/virtua_original.png?1656043619"), +}; + +pub static UMA_VOTING_TOKEN_V1: TokenInfo = TokenInfo { + name: "UMA Voting Token v1", + symbol: "UMA", + decimals: 18, + contract: address!("0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), +}; + +pub static UNIFI_PROTOCOL_DAO: TokenInfo = TokenInfo { + name: "Unifi Protocol DAO", + symbol: "UNFI", + decimals: 18, + contract: address!("0x441761326490cACF7aF299725B6292597EE822c2"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/13152/thumb/logo-2.png?1605748967"), +}; + +pub static UNISWAP: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), + chain: 1, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static PAWTOCOL: TokenInfo = TokenInfo { + name: "Pawtocol", + symbol: "UPI", + decimals: 18, + contract: address!("0x70D2b7C19352bB76e4409858FF5746e500f2B67c"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12186/thumb/pawtocol.jpg?1597962008"), +}; + +pub static WORLD_LIBERTY_FINANCIAL_USD: TokenInfo = TokenInfo { + name: "World Liberty Financial USD", + symbol: "USD1", + decimals: 18, + contract: address!("0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54977/large/USD1_1000x1000_transparent.png?1749297002"), +}; + +pub static USDCOIN: TokenInfo = TokenInfo { + name: "USDCoin", + symbol: "USDC", + decimals: 6, + contract: address!("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), +}; + +pub static GLOBAL_DOLLAR: TokenInfo = TokenInfo { + name: "Global Dollar", + symbol: "USDG", + decimals: 6, + contract: address!("0xe343167631d89B6Ffc58B88d6b7fB0228795491D"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/51281/large/GDN_USDG_Token_200x200.png"), +}; + +pub static PAX_DOLLAR: TokenInfo = TokenInfo { + name: "Pax Dollar", + symbol: "USDP", + decimals: 18, + contract: address!("0x8E870D67F660D95d5be530380D0eC0bd388289E1"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/6013/standard/Pax_Dollar.png?1696506427"), +}; + +pub static QUANTOZ_USDQ: TokenInfo = TokenInfo { + name: "Quantoz USDQ", + symbol: "USDQ", + decimals: 6, + contract: address!("0xc83e27f270cce0A3A3A29521173a83F402c1768b"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/51852/large/USDQ_1000px_Color.png?1732071232"), +}; + +pub static STABLR_USD: TokenInfo = TokenInfo { + name: "StablR USD", + symbol: "USDR", + decimals: 6, + contract: address!("0x7B43E3875440B44613DC3bC08E7763e6Da63C8f8"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/53721/large/stablrusd-logo.png?1737126629"), +}; + +pub static USDS_STABLECOIN: TokenInfo = TokenInfo { + name: "USDS Stablecoin", + symbol: "USDS", + decimals: 18, + contract: address!("0xdC035D45d973E3EC169d2276DDab16f1e407384F"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/39926/large/usds.webp?1726666683"), +}; + +pub static TETHER_USD: TokenInfo = TokenInfo { + name: "Tether USD", + symbol: "USDT", + decimals: 6, + contract: address!("0xdAC17F958D2ee523a2206206994597C13D831ec7"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), +}; + +pub static USUAL: TokenInfo = TokenInfo { + name: "USUAL", + symbol: "USUAL", + decimals: 18, + contract: address!("0xC4441c2BE5d8fA8126822B9929CA0b81Ea0DE38E"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/51091/large/USUAL.jpg?1730035787"), +}; + +pub static VANRY: TokenInfo = TokenInfo { + name: "VANRY", + symbol: "VANRY", + decimals: 18, + contract: address!("0x8DE5B80a0C1B02Fe4976851D030B36122dbb8624"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/33466/large/apple-touch-icon.png?1701942541"), +}; + +pub static VOYAGER_TOKEN: TokenInfo = TokenInfo { + name: "Voyager Token", + symbol: "VGX", + decimals: 8, + contract: address!("0x3C4B6E6e1eA3D4863700D7F76b36B7f3D3f13E3d"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/794/thumb/Voyager-vgx.png?1575693595"), +}; + +pub static WRAPPED_AMPLEFORTH: TokenInfo = TokenInfo { + name: "Wrapped Ampleforth", + symbol: "WAMPL", + decimals: 18, + contract: address!("0xEDB171C18cE90B633DB442f2A6F72874093b49Ef"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/20825/thumb/photo_2021-11-25_02-05-11.jpg?1637811951"), +}; + +pub static WRAPPED_ANALOG_ONE_TOKEN: TokenInfo = TokenInfo { + name: "Wrapped Analog One Token", + symbol: "WANLOG", + decimals: 12, + contract: address!("0xf983da3ca66964C02628189Ea8Ca99fa9E24f66c"), + chain: 1, + logo_uri: Some("https://assets.kraken.com/marketing/web/icons-uni-webp/s_anlog.webp?i=kds"), +}; + +pub static WRAPPED_BTC: TokenInfo = TokenInfo { + name: "Wrapped BTC", + symbol: "WBTC", + decimals: 8, + contract: address!("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), +}; + +pub static WRAPPED_CENTRIFUGE: TokenInfo = TokenInfo { + name: "Wrapped Centrifuge", + symbol: "WCFG", + decimals: 18, + contract: address!("0xc221b7E65FfC80DE234bbB6667aBDd46593D34F0"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/17106/thumb/WCFG.jpg?1626266462"), +}; + +pub static WALLETCONNECT_TOKEN: TokenInfo = TokenInfo { + name: "WalletConnect Token", + symbol: "WCT", + decimals: 18, + contract: address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/50390/large/wc-token1.png?1727569464"), +}; + +pub static WRAPPED_ETHER: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static WORLD_LIBERTY_FINANCIAL: TokenInfo = TokenInfo { + name: "World Liberty Financial", + symbol: "WLFI", + decimals: 18, + contract: address!("0xdA5e1988097297dCdc1f90D4dFE7909e847CBeF6"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/50767/large/wlfi.png?1756438915"), +}; + +pub static WOO_NETWORK: TokenInfo = TokenInfo { + name: "WOO Network", + symbol: "WOO", + decimals: 18, + contract: address!("0x4691937a7508860F876c9c0a2a617E7d9E945D4B"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), +}; + +pub static ANOMA: TokenInfo = TokenInfo { + name: "Anoma", + symbol: "XAN", + decimals: 18, + contract: address!("0xCEDbEA37C8872c4171259Cdfd5255CB8923Cf8e7"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/69380/large/Anoma_Logo_Roundel_RGB_Colour-01.png?1758356672"), +}; + +pub static TETHER_GOLD: TokenInfo = TokenInfo { + name: "Tether Gold", + symbol: "XAUT", + decimals: 6, + contract: address!("0x68749665FF8D2d112Fa859AA293F07A622782F38"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/10481/large/Tether_Gold.png?1696510471"), +}; + +pub static CHAIN: TokenInfo = TokenInfo { + name: "Chain", + symbol: "XCN", + decimals: 18, + contract: address!("0xA2cd3D43c775978A96BdBf12d733D5A1ED94fb18"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054"), +}; + +pub static XSGD: TokenInfo = TokenInfo { + name: "XSGD", + symbol: "XSGD", + decimals: 6, + contract: address!("0x70e8dE73cE538DA2bEEd35d14187F6959a8ecA96"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623"), +}; + +pub static XYO_NETWORK: TokenInfo = TokenInfo { + name: "XYO Network", + symbol: "XYO", + decimals: 18, + contract: address!("0x55296f69f40Ea6d20E478533C15A6B08B654E758"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819"), +}; + +pub static YIELD_BASIS: TokenInfo = TokenInfo { + name: "Yield Basis", + symbol: "YB", + decimals: 18, + contract: address!("0x01791F726B4103694969820be083196cC7c045fF"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54871/large/yieldbasis_400x400.png?1760514173"), +}; + +pub static YEARN_FINANCE: TokenInfo = TokenInfo { + name: "yearn finance", + symbol: "YFI", + decimals: 18, + contract: address!("0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), +}; + +pub static DFI_MONEY: TokenInfo = TokenInfo { + name: "DFI money", + symbol: "YFII", + decimals: 18, + contract: address!("0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/11902/thumb/YFII-logo.78631676.png?1598677348"), +}; + +pub static YIELD_GUILD_GAMES: TokenInfo = TokenInfo { + name: "Yield Guild Games", + symbol: "YGG", + decimals: 18, + contract: address!("0x25f8087EAD173b73D6e8B84329989A8eEA16CF73"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/17358/thumb/le1nzlO6_400x400.jpg?1632465691"), +}; + +pub static ZAMA: TokenInfo = TokenInfo { + name: "Zama", + symbol: "ZAMA", + decimals: 18, + contract: address!("0xA12CC123ba206d4031D1c7f6223D1C2Ec249f4f3"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/70921/large/zama.png?1764591992"), +}; + +pub static ZETACHAIN: TokenInfo = TokenInfo { + name: "Zetachain", + symbol: "Zeta", + decimals: 18, + contract: address!("0xf091867EC603A6628eD83D274E835539D82e9cc8"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/26718/standard/Twitter_icon.png?1696525788"), +}; + +pub static BOUNDLESS: TokenInfo = TokenInfo { + name: "Boundless", + symbol: "ZKC", + decimals: 18, + contract: address!("0x000006c2A22ff4A44ff1f5d0F2ed65F781F55555"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/68462/large/boundless.png?1755826792"), +}; + +pub static ZKPASS: TokenInfo = TokenInfo { + name: "zkPass", + symbol: "ZKP", + decimals: 18, + contract: address!("0xe1Be424F442D0687129128C6c38aAce44F8c8Dbc"), + chain: 1, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/70273/large/zkpass.png?1761379373"), +}; + +pub static LAYERZERO: TokenInfo = TokenInfo { + name: "LayerZero", + symbol: "ZRO", + decimals: 18, + contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), + chain: 1, + logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), +}; + +pub static TOKEN_0X_PROTOCOL_TOKEN: TokenInfo = TokenInfo { + name: "0x Protocol Token", + symbol: "ZRX", + decimals: 18, + contract: address!("0xE41d2489571d322189246DaFA5ebDe1F4699F498"), + chain: 1, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), +}; + +pub static DAI_STABLECOIN_3_CE07538D: TokenInfo = TokenInfo { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + contract: address!("0xaD6D458402F60fD3Bd25163575031ACDce07538D"), + chain: 3, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xaD6D458402F60fD3Bd25163575031ACDce07538D/logo.png"), +}; + +pub static UNISWAP_3_4201F984: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), + chain: 3, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static WRAPPED_ETHER_3_AA0CD5AB: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0xc778417E063141139Fce010982780140Aa0cD5Ab"), + chain: 3, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc778417E063141139Fce010982780140Aa0cD5Ab/logo.png"), +}; + +pub static DAI_STABLECOIN_4_A8FC4735: TokenInfo = TokenInfo { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + contract: address!("0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735"), + chain: 4, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735/logo.png"), +}; + +pub static MAKER_4_359AAD85: TokenInfo = TokenInfo { + name: "Maker", + symbol: "MKR", + decimals: 18, + contract: address!("0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85"), + chain: 4, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85/logo.png"), +}; + +pub static UNISWAP_4_4201F984: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), + chain: 4, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static WRAPPED_ETHER_4_AA0CD5AB: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0xc778417E063141139Fce010982780140Aa0cD5Ab"), + chain: 4, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc778417E063141139Fce010982780140Aa0cD5Ab/logo.png"), +}; + +pub static UNISWAP_5_4201F984: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), + chain: 5, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static WRAPPED_ETHER_5_2B2208D6: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"), + chain: 5, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6/logo.png"), +}; + +pub static TOKEN_1INCH_10_94736426: TokenInfo = TokenInfo { + name: "1inch", + symbol: "1INCH", + decimals: 18, + contract: address!("0xAd42D013ac31486B73b6b059e748172994736426"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), +}; + +pub static AAVE_10_950C9278: TokenInfo = TokenInfo { + name: "Aave", + symbol: "AAVE", + decimals: 18, + contract: address!("0x76FB31fb4af56892A25e32cFC43De717950c9278"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), +}; + +pub static ACROSS_PROTOCOL_TOKEN_10_FDD1B76B: TokenInfo = TokenInfo { + name: "Across Protocol Token", + symbol: "ACX", + decimals: 18, + contract: address!("0xFf733b2A3557a7ed6697007ab5D11B79FdD1b76B"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165"), +}; + +pub static ARPA_CHAIN_10_C9BFA31E: TokenInfo = TokenInfo { + name: "ARPA Chain", + symbol: "ARPA", + decimals: 18, + contract: address!("0x334cc734866E97D8452Ae6261d68Fd9bc9BFa31E"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357"), +}; + +pub static BALANCER_10_E9379921: TokenInfo = TokenInfo { + name: "Balancer", + symbol: "BAL", + decimals: 18, + contract: address!("0xFE8B128bA8C78aabC59d4c64cEE7fF28e9379921"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png"), +}; + +pub static BICONOMY_10_C0FB1C9D: TokenInfo = TokenInfo { + name: "Biconomy", + symbol: "BICO", + decimals: 18, + contract: address!("0xd6909e9e702024eb93312B989ee46794c0fB1C9D"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749"), +}; + +pub static BOBA_NETWORK_10_CB88854D: TokenInfo = TokenInfo { + name: "Boba Network", + symbol: "BOBA", + decimals: 18, + contract: address!("0x07ad578FF86B135bE19A12759064b802Cb88854D"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/20285/thumb/BOBA.png?1636811576"), +}; + +pub static BARNBRIDGE_10_3F276747: TokenInfo = TokenInfo { + name: "BarnBridge", + symbol: "BOND", + decimals: 18, + contract: address!("0x3e7eF8f50246f725885102E8238CBba33F276747"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853"), +}; + +pub static BRAINTRUST_10_E141254E: TokenInfo = TokenInfo { + name: "Braintrust", + symbol: "BTRST", + decimals: 18, + contract: address!("0xEd50aCE88bd42B45cB0F49be15395021E141254e"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/18100/thumb/braintrust.PNG?1630475394"), +}; + +pub static BINANCE_USD_10_39D2DB39: TokenInfo = TokenInfo { + name: "Binance USD", + symbol: "BUSD", + decimals: 18, + contract: address!("0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), +}; + +pub static COINBASE_WRAPPED_STAKED_ETH_10_78DCF3B2: TokenInfo = TokenInfo { + name: "Coinbase Wrapped Staked ETH", + symbol: "cbETH", + decimals: 18, + contract: address!("0xadDb6A0412DE1BA0F936DCaeb8Aaa24578dcF3B2"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/27008/large/cbeth.png"), +}; + +pub static CELO_NATIVE_ASSET_WORMHOLE_10_B9B5C349: TokenInfo = TokenInfo { + name: "Celo native asset (Wormhole)", + symbol: "CELO", + decimals: 18, + contract: address!("0x9b88D293b7a791E40d36A39765FFd5A1B9b5c349"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png"), +}; + +pub static CURVE_DAO_TOKEN_10_0605FB53: TokenInfo = TokenInfo { + name: "Curve DAO Token", + symbol: "CRV", + decimals: 18, + contract: address!("0x0994206dfE8De6Ec6920FF4D779B0d950605Fb53"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), +}; + +pub static CARTESI_10_071295BF: TokenInfo = TokenInfo { + name: "Cartesi", + symbol: "CTSI", + decimals: 18, + contract: address!("0xEc6adef5E1006bb305bB1975333e8fc4071295bf"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), +}; + +pub static CYBER: TokenInfo = TokenInfo { + name: "CYBER", + symbol: "CYBER", + decimals: 18, + contract: address!("0x14778860E937f509e651192a90589dE711Fb88a9"), + chain: 10, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/31274/large/token.png?1715826754"), +}; + +pub static DAI_STABLECOIN_10_C9000DA1: TokenInfo = TokenInfo { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + contract: address!("0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), +}; + +pub static DERIVE_10_72BBA100: TokenInfo = TokenInfo { + name: "Derive", + symbol: "DRV", + decimals: 18, + contract: address!("0x33800De7E817A70A694F31476313A7c572BBa100"), + chain: 10, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695"), +}; + +pub static ETHEREUM_NAME_SERVICE_10_5E890A00: TokenInfo = TokenInfo { + name: "Ethereum Name Service", + symbol: "ENS", + decimals: 18, + contract: address!("0x65559aA14915a70190438eF90104769e5E890A00"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140"), +}; + +pub static STAFI_10_911BAD41: TokenInfo = TokenInfo { + name: "Stafi", + symbol: "FIS", + decimals: 18, + contract: address!("0xD8737CA46aa6285dE7B8777a8e3db232911baD41"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991"), +}; + +pub static SHAPESHIFT_FOX_TOKEN_10_37CED174: TokenInfo = TokenInfo { + name: "ShapeShift FOX Token", + symbol: "FOX", + decimals: 18, + contract: address!("0xF1a0DA3367BC7aa04F8D94BA57B862ff37CeD174"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622"), +}; + +pub static FRAX_10_9A53F475: TokenInfo = TokenInfo { + name: "Frax", + symbol: "FRAX", + decimals: 18, + contract: address!("0x2E3D870790dC77A83DD1d18184Acc7439A53f475"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), +}; + +pub static FRAX_SHARE_10_1C2205BE: TokenInfo = TokenInfo { + name: "Frax Share", + symbol: "FXS", + decimals: 18, + contract: address!("0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), +}; + +pub static GITCOIN_10_46445B08: TokenInfo = TokenInfo { + name: "Gitcoin", + symbol: "GTC", + decimals: 18, + contract: address!("0x1EBA7a6a72c894026Cd654AC5CDCF83A46445B08"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929"), +}; + +pub static GYEN_10_D9B6D5F7: TokenInfo = TokenInfo { + name: "GYEN", + symbol: "GYEN", + decimals: 6, + contract: address!("0x589d35656641d6aB57A545F08cf473eCD9B6D5F7"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343"), +}; + +pub static KRYLL_10_C9022021: TokenInfo = TokenInfo { + name: "KRYLL", + symbol: "KRL", + decimals: 18, + contract: address!("0x2ed6222CB75E353b8789bec7Bb443b7eC9022021"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979"), +}; + +pub static KUJIRA_10_5671E7CA: TokenInfo = TokenInfo { + name: "Kujira", + symbol: "KUJI", + decimals: 6, + contract: address!("0x3A18dcC9745eDcD1Ef33ecB93b0b6eBA5671e7Ca"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png"), +}; + +pub static LIDO_DAO_10_2596735F: TokenInfo = TokenInfo { + name: "Lido DAO", + symbol: "LDO", + decimals: 18, + contract: address!("0xFdb794692724153d1488CcdBE0C56c252596735F"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644"), +}; + +pub static CHAINLINK_TOKEN_10_38FFA7F6: TokenInfo = TokenInfo { + name: "ChainLink Token", + symbol: "LINK", + decimals: 18, + contract: address!("0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), +}; + +pub static LOOPRINGCOIN_V2_10_1464907E: TokenInfo = TokenInfo { + name: "LoopringCoin V2", + symbol: "LRC", + decimals: 18, + contract: address!("0xFEaA9194F9F8c1B65429E31341a103071464907E"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png"), +}; + +pub static LIQUITY_USD_10_9B7B2819: TokenInfo = TokenInfo { + name: "Liquity USD", + symbol: "LUSD", + decimals: 18, + contract: address!("0xc40F949F8a4e094D1b49a23ea9241D289B7b2819"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327"), +}; + +pub static MASK_NETWORK_10_BDF63798: TokenInfo = TokenInfo { + name: "Mask Network", + symbol: "MASK", + decimals: 18, + contract: address!("0x3390108E913824B8eaD638444cc52B9aBdF63798"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316"), +}; + +pub static MAKER_10_27F2FCB5: TokenInfo = TokenInfo { + name: "Maker", + symbol: "MKR", + decimals: 18, + contract: address!("0xab7bAdEF82E9Fe11f6f33f87BC9bC2AA27F2fCB5"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png"), +}; + +pub static OCEAN_PROTOCOL_10_B8B49F9E: TokenInfo = TokenInfo { + name: "Ocean Protocol", + symbol: "OCEAN", + decimals: 18, + contract: address!("0x2561aa2bB1d2Eb6629EDd7b0938d7679B8b49f9E"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686"), +}; + +pub static OPTIMISM: TokenInfo = TokenInfo { + name: "Optimism", + symbol: "OP", + decimals: 18, + contract: address!("0x4200000000000000000000000000000000000042"), + chain: 10, + logo_uri: Some("https://ethereum-optimism.github.io/data/OP/logo.png"), +}; + +pub static PENDLE_10_796E66E1: TokenInfo = TokenInfo { + name: "Pendle", + symbol: "PENDLE", + decimals: 18, + contract: address!("0xBC7B1Ff1c6989f006a1185318eD4E7b5796e66E1"), + chain: 10, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728"), +}; + +pub static PEPE_10_9DDB16F5: TokenInfo = TokenInfo { + name: "Pepe", + symbol: "PEPE", + decimals: 18, + contract: address!("0xC1c167CC44f7923cd0062c4370Df962f9DDB16f5"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725"), +}; + +pub static PERPETUAL_PROTOCOL_10_976840E0: TokenInfo = TokenInfo { + name: "Perpetual Protocol", + symbol: "PERP", + decimals: 18, + contract: address!("0x9e1028F5F1D5eDE59748FFceE5532509976840E0"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), +}; + +pub static RAI_REFLEX_INDEX_10_7705448B: TokenInfo = TokenInfo { + name: "Rai Reflex Index", + symbol: "RAI", + decimals: 18, + contract: address!("0x7FB688CCf682d58f86D7e38e03f9D22e7705448B"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334"), +}; + +pub static RARI_GOVERNANCE_TOKEN_10_DCEC711A: TokenInfo = TokenInfo { + name: "Rari Governance Token", + symbol: "RGT", + decimals: 18, + contract: address!("0xB548f63D4405466B36C0c0aC3318a22fDcec711a"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014"), +}; + +pub static ROCKET_POOL_PROTOCOL_10_C14D1401: TokenInfo = TokenInfo { + name: "Rocket Pool Protocol", + symbol: "RPL", + decimals: 18, + contract: address!("0xC81D1F0EB955B0c020E5d5b264E1FF72c14d1401"), + chain: 10, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/2090/large/rocket_pool_%28RPL%29.png?1696503058"), +}; + +pub static STATUS_10_64CFB6B2: TokenInfo = TokenInfo { + name: "Status", + symbol: "SNT", + decimals: 18, + contract: address!("0x650AF3C15AF43dcB218406d30784416D64Cfb6B2"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778"), +}; + +pub static SYNTHETIX_NETWORK_TOKEN_10_3D7599B4: TokenInfo = TokenInfo { + name: "Synthetix Network Token", + symbol: "SNX", + decimals: 18, + contract: address!("0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), +}; + +pub static SOL_WORMHOLE_10_7FA664F1: TokenInfo = TokenInfo { + name: "SOL Wormhole ", + symbol: "SOL", + decimals: 9, + contract: address!("0xba1Cf949c382A32a09A17B2AdF3587fc7fA664f1"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), +}; + +pub static SUKU_10_0B9E50A4: TokenInfo = TokenInfo { + name: "SUKU", + symbol: "SUKU", + decimals: 18, + contract: address!("0xEf6301DA234fC7b0545c6E877D3359FE0B9E50a4"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/11969/thumb/UmfW5S6f_400x400.jpg?1596602238"), +}; + +pub static SYNTH_SUSD_10_751EC8D9: TokenInfo = TokenInfo { + name: "Synth sUSD", + symbol: "sUSD", + decimals: 18, + contract: address!("0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765"), +}; + +pub static SUSHI_10_0F60112B: TokenInfo = TokenInfo { + name: "Sushi", + symbol: "SUSHI", + decimals: 18, + contract: address!("0x3eaEb77b03dBc0F6321AE1b72b2E9aDb0F60112B"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), +}; + +pub static THRESHOLD_NETWORK_10_8C734EA7: TokenInfo = TokenInfo { + name: "Threshold Network", + symbol: "T", + decimals: 18, + contract: address!("0x747e42Eb0591547a0ab429B3627816208c734EA7"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340"), +}; + +pub static TELLOR_10_E3CEB888: TokenInfo = TokenInfo { + name: "Tellor", + symbol: "TRB", + decimals: 18, + contract: address!("0xaf8cA653Fa2772d58f4368B0a71980e9E3cEB888"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686"), +}; + +pub static UMA_VOTING_TOKEN_V1_10_855A77EA: TokenInfo = TokenInfo { + name: "UMA Voting Token v1", + symbol: "UMA", + decimals: 18, + contract: address!("0xE7798f023fC62146e8Aa1b36Da45fb70855a77Ea"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), +}; + +pub static UNISWAP_10_0E816691: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0x6fd9d7AD17242c41f7131d257212c54A0e816691"), + chain: 10, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static USDCOIN_10_D097FF85: TokenInfo = TokenInfo { + name: "USDCoin", + symbol: "USDC", + decimals: 6, + contract: address!("0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"), + chain: 10, + logo_uri: Some("https://ethereum-optimism.github.io/data/USDC/logo.png"), +}; + +pub static USDCOIN_BRIDGED_FROM_ETHEREUM: TokenInfo = TokenInfo { + name: "USDCoin (Bridged from Ethereum)", + symbol: "USDC.e", + decimals: 6, + contract: address!("0x7F5c764cBc14f9669B88837ca1490cCa17c31607"), + chain: 10, + logo_uri: Some("https://ethereum-optimism.github.io/data/USDC/logo.png"), +}; + +pub static TETHER_USD_10_8CE58E58: TokenInfo = TokenInfo { + name: "Tether USD", + symbol: "USDT", + decimals: 6, + contract: address!("0x94b008aA00579c1307B0EF2c499aD98a8ce58e58"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), +}; + +pub static VELODROME_FINANCE: TokenInfo = TokenInfo { + name: "Velodrome Finance", + symbol: "VELO", + decimals: 18, + contract: address!("0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/12538/standard/Logo_200x_200.png?1696512350"), +}; + +pub static WRAPPED_BTC_10_BF0A2095: TokenInfo = TokenInfo { + name: "Wrapped BTC", + symbol: "WBTC", + decimals: 8, + contract: address!("0x68f180fcCe6836688e9084f035309E29Bf0A2095"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), +}; + +pub static WALLETCONNECT_TOKEN_10_DD927945: TokenInfo = TokenInfo { + name: "WalletConnect Token", + symbol: "WCT", + decimals: 18, + contract: address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945"), + chain: 10, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/50390/large/wc-token1.png?1727569464"), +}; + +pub static WRAPPED_ETHER_10_00000006: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0x4200000000000000000000000000000000000006"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static WORLDCOIN: TokenInfo = TokenInfo { + name: "Worldcoin", + symbol: "WLD", + decimals: 18, + contract: address!("0xdC6fF44d5d932Cbd77B52E5612Ba0529DC6226F1"), + chain: 10, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/31069/large/worldcoin.jpeg?1696529903"), +}; + +pub static WOO_NETWORK_10_51A5E527: TokenInfo = TokenInfo { + name: "WOO Network", + symbol: "WOO", + decimals: 18, + contract: address!("0x871f2F2ff935FD1eD867842FF2a7bfD051A5E527"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), +}; + +pub static XYO_NETWORK_10_DBD81FC8: TokenInfo = TokenInfo { + name: "XYO Network", + symbol: "XYO", + decimals: 18, + contract: address!("0x9db118D43069B73B8a252bF0be49d50Edbd81fc8"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819"), +}; + +pub static YEARN_FINANCE_10_FEE9107B: TokenInfo = TokenInfo { + name: "yearn finance", + symbol: "YFI", + decimals: 18, + contract: address!("0x9046D36440290FfDE54FE0DD84Db8b1CfEE9107B"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), +}; + +pub static LAYERZERO_10_F13271CD: TokenInfo = TokenInfo { + name: "LayerZero", + symbol: "ZRO", + decimals: 18, + contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), + chain: 10, + logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), +}; + +pub static TOKEN_0X_PROTOCOL_TOKEN_10_FA3C2F33: TokenInfo = TokenInfo { + name: "0x Protocol Token", + symbol: "ZRX", + decimals: 18, + contract: address!("0xD1917629B3E6A72E6772Aab5dBe58Eb7FA3C2F33"), + chain: 10, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), +}; + +pub static DAI_STABLECOIN_42_B64CA6AA: TokenInfo = TokenInfo { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + contract: address!("0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa"), + chain: 42, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa/logo.png"), +}; + +pub static MAKER_42_71A4FFCD: TokenInfo = TokenInfo { + name: "Maker", + symbol: "MKR", + decimals: 18, + contract: address!("0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD"), + chain: 42, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD/logo.png"), +}; + +pub static UNISWAP_42_4201F984: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), + chain: 42, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static WRAPPED_ETHER_42_C2CF029C: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0xd0A1E359811322d97991E03f863a0C30C2cF029C"), + chain: 42, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xd0A1E359811322d97991E03f863a0C30C2cF029C/logo.png"), +}; + +pub static TOKEN_1INCH_56_4120C302: TokenInfo = TokenInfo { + name: "1inch", + symbol: "1INCH", + decimals: 18, + contract: address!("0x111111111117dC0aa78b770fA6A738034120C302"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), +}; + +pub static AAVE_56_7E58F802: TokenInfo = TokenInfo { + name: "Aave", + symbol: "AAVE", + decimals: 18, + contract: address!("0xfb6115445Bff7b52FeB98650C87f44907E58f802"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), +}; + +pub static ALCHEMY_PAY_56_7003056D: TokenInfo = TokenInfo { + name: "Alchemy Pay", + symbol: "ACH", + decimals: 8, + contract: address!("0xBc7d6B50616989655AfD682fb42743507003056D"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12390/thumb/ACH_%281%29.png?1599691266"), +}; + +pub static AMBIRE_ADEX_56_A7077819: TokenInfo = TokenInfo { + name: "Ambire AdEx", + symbol: "ADX", + decimals: 18, + contract: address!("0x6bfF4Fb161347ad7de4A625AE5aa3A1CA7077819"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540"), +}; + +pub static AGEUR_56_D5FE5F89: TokenInfo = TokenInfo { + name: "agEur", + symbol: "agEUR", + decimals: 18, + contract: address!("0x12f31B73D812C6Bb0d735a218c086d44D5fe5f89"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), +}; + +pub static AIOZ_NETWORK_56_9FC3741D: TokenInfo = TokenInfo { + name: "AIOZ Network", + symbol: "AIOZ", + decimals: 18, + contract: address!("0x33d08D8C7a168333a85285a68C0042b39fC3741D"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126"), +}; + +pub static ALEPH_IM_56_DE9038C4: TokenInfo = TokenInfo { + name: "Aleph im", + symbol: "ALEPH", + decimals: 18, + contract: address!("0x82D2f8E02Afb160Dd5A480a617692e62de9038C4"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725"), +}; + +pub static MY_NEIGHBOR_ALICE_56_745D63E8: TokenInfo = TokenInfo { + name: "My Neighbor Alice", + symbol: "ALICE", + decimals: 6, + contract: address!("0xAC51066d7bEC65Dc4589368da368b212745d63E8"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/14375/thumb/alice_logo.jpg?1615782968"), +}; + +pub static ALPHA_VENTURE_DAO_56_13B40975: TokenInfo = TokenInfo { + name: "Alpha Venture DAO", + symbol: "ALPHA", + decimals: 18, + contract: address!("0xa1faa113cbE53436Df28FF0aEe54275c13B40975"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876"), +}; + +pub static ANKR_56_531B08E3: TokenInfo = TokenInfo { + name: "Ankr", + symbol: "ANKR", + decimals: 18, + contract: address!("0xf307910A4c7bbc79691fD374889b36d8531B08e3"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978"), +}; + +pub static ARPA_CHAIN_56_FA2D6F7E: TokenInfo = TokenInfo { + name: "ARPA Chain", + symbol: "ARPA", + decimals: 18, + contract: address!("0x6F769E65c14Ebd1f68817F5f1DcDb61Cfa2D6f7e"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357"), +}; + +pub static ASTER: TokenInfo = TokenInfo { + name: "Aster", + symbol: "ASTER", + decimals: 18, + contract: address!("0x000Ae314E2A2172a039B26378814C252734f556A"), + chain: 56, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/69040/large/_ASTER.png?1757326782"), +}; + +pub static AUTOMATA_56_2F141225: TokenInfo = TokenInfo { + name: "Automata", + symbol: "ATA", + decimals: 18, + contract: address!("0xA2120b9e674d3fC3875f415A7DF52e382F141225"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745"), +}; + +pub static AXELAR_56_C96F1F65: TokenInfo = TokenInfo { + name: "Axelar", + symbol: "AXL", + decimals: 6, + contract: address!("0x8b1f4432F943c465A973FeDC6d7aa50Fc96f1f65"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg"), +}; + +pub static AXIE_INFINITY_56_D4D2F8A0: TokenInfo = TokenInfo { + name: "Axie Infinity", + symbol: "AXS", + decimals: 18, + contract: address!("0x715D400F88C167884bbCc41C5FeA407ed4D2f8A0"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082"), +}; + +pub static BLUZELLE_56_DA0ACDA2: TokenInfo = TokenInfo { + name: "Bluzelle", + symbol: "BLZ", + decimals: 18, + contract: address!("0x935a544Bf5816E3A7C13DB2EFe3009Ffda0aCdA2"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/2848/thumb/ColorIcon_3x.png?1622516510"), +}; + +pub static BINANCE_USD_56_DD087D56: TokenInfo = TokenInfo { + name: "Binance USD", + symbol: "BUSD", + decimals: 18, + contract: address!("0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), +}; + +pub static COIN98_56_90F1C3A6: TokenInfo = TokenInfo { + name: "Coin98", + symbol: "C98", + decimals: 18, + contract: address!("0xaEC945e04baF28b135Fa7c640f624f8D90F1C3a6"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/17117/thumb/logo.png?1626412904"), +}; + +pub static CHROMIA_56_32B224FE: TokenInfo = TokenInfo { + name: "Chromia", + symbol: "CHR", + decimals: 6, + contract: address!("0xf9CeC8d50f6c8ad3Fb6dcCEC577e05aA32B224FE"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/5000/thumb/Chromia.png?1559038018"), +}; + +pub static CLOVER_FINANCE_56_367A4E4D: TokenInfo = TokenInfo { + name: "Clover Finance", + symbol: "CLV", + decimals: 18, + contract: address!("0x09E889BB4D5b474f561db0491C38702F367A4e4d"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/15278/thumb/clover.png?1645084454"), +}; + +pub static COMPOUND_56_8CAD67E8: TokenInfo = TokenInfo { + name: "Compound", + symbol: "COMP", + decimals: 18, + contract: address!("0x52CE071Bd9b1C4B00A0b92D298c512478CaD67e8"), + chain: 56, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), +}; + +pub static CIRCUITS_OF_VALUE_56_2B141464: TokenInfo = TokenInfo { + name: "Circuits of Value", + symbol: "COVAL", + decimals: 8, + contract: address!("0xd15CeE1DEaFBad6C0B3Fd7489677Cc102B141464"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/588/thumb/coval-logo.png?1599493950"), +}; + +pub static CARTESI_56_2D033EF2: TokenInfo = TokenInfo { + name: "Cartesi", + symbol: "CTSI", + decimals: 18, + contract: address!("0x8dA443F84fEA710266C8eB6bC34B71702d033EF2"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), +}; + +pub static DAI_STABLECOIN_56_58B1DBC3: TokenInfo = TokenInfo { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + contract: address!("0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3"), + chain: 56, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), +}; + +pub static MINES_OF_DALARNIA_56_D45CD978: TokenInfo = TokenInfo { + name: "Mines of Dalarnia", + symbol: "DAR", + decimals: 6, + contract: address!("0x23CE9e926048273eF83be0A3A8Ba9Cb6D45cd978"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/19837/thumb/dar.png?1636014223"), +}; + +pub static DEXTOOLS_56_C29896E3: TokenInfo = TokenInfo { + name: "DexTools", + symbol: "DEXT", + decimals: 18, + contract: address!("0xe91a8D2c584Ca93C7405F15c22CdFE53C29896E3"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188"), +}; + +pub static DIA_56_7E0901DD: TokenInfo = TokenInfo { + name: "DIA", + symbol: "DIA", + decimals: 18, + contract: address!("0x99956D38059cf7bEDA96Ec91Aa7BB2477E0901DD"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751"), +}; + +pub static DREP_56_01A705FF: TokenInfo = TokenInfo { + name: "Drep", + symbol: "DREP", + decimals: 18, + contract: address!("0xEC583f25A049CC145dA9A256CDbE9B6201a705Ff"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/14578/thumb/KotgsCgS_400x400.jpg?1617094445"), +}; + +pub static DEFI_YIELD_PROTOCOL_56_91BCEF17: TokenInfo = TokenInfo { + name: "DeFi Yield Protocol", + symbol: "DYP", + decimals: 18, + contract: address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066"), +}; + +pub static DOGELON_MARS_56_D9BE2540: TokenInfo = TokenInfo { + name: "Dogelon Mars", + symbol: "ELON", + decimals: 18, + contract: address!("0x7bd6FaBD64813c48545C9c0e312A0099d9be2540"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413"), +}; + +pub static HARVEST_FINANCE_56_A5D33743: TokenInfo = TokenInfo { + name: "Harvest Finance", + symbol: "FARM", + decimals: 18, + contract: address!("0x4B5C23cac08a567ecf0c1fFcA8372A45a5D33743"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180"), +}; + +pub static FETCH_AI_56_8691FA7F: TokenInfo = TokenInfo { + name: "Fetch ai", + symbol: "FET", + decimals: 18, + contract: address!("0x031b41e504677879370e9DBcF937283A8691Fa7f"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136"), +}; + +pub static FLOKI_56_5363D37E: TokenInfo = TokenInfo { + name: "FLOKI", + symbol: "FLOKI", + decimals: 9, + contract: address!("0xfb5B838b6cfEEdC2873aB27866079AC55363D37E"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318"), +}; + +pub static FRAX_56_53E89F40: TokenInfo = TokenInfo { + name: "Frax", + symbol: "FRAX", + decimals: 18, + contract: address!("0x90C97F71E18723b0Cf0dfa30ee176Ab653E89F40"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), +}; + +pub static FANTOM_56_AF29DCFE: TokenInfo = TokenInfo { + name: "Fantom", + symbol: "FTM", + decimals: 18, + contract: address!("0xAD29AbB318791D579433D831ed122aFeAf29dcfe"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016"), +}; + +pub static FRAX_SHARE_56_5EADB9EE: TokenInfo = TokenInfo { + name: "Frax Share", + symbol: "FXS", + decimals: 18, + contract: address!("0xe48A3d7d0Bc88d552f730B62c006bC925eadB9eE"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), +}; + +pub static GALXE_56_40497AA5: TokenInfo = TokenInfo { + name: "Galxe", + symbol: "GAL", + decimals: 18, + contract: address!("0xe4Cc45Bb5DBDA06dB6183E8bf016569f40497Aa5"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533"), +}; + +pub static ETHGAS_56_B72F7D49: TokenInfo = TokenInfo { + name: "ETHGas", + symbol: "GWEI", + decimals: 18, + contract: address!("0x30117E4bC17d7B044194b76A38365C53b72F7D49"), + chain: 56, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/71375/large/ethgas_token_200.png?1769055039"), +}; + +pub static HASHFLOW_56_35883E47: TokenInfo = TokenInfo { + name: "Hashflow", + symbol: "HFT", + decimals: 18, + contract: address!("0x44Ec807ce2F4a6F2737A92e985f318d035883e47"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/26136/large/hashflow-icon-cmc.png"), +}; + +pub static HIGHSTREET_56_1FFEED63: TokenInfo = TokenInfo { + name: "Highstreet", + symbol: "HIGH", + decimals: 18, + contract: address!("0x5f4Bde007Dc06b867f86EBFE4802e34A1fFEEd63"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470"), +}; + +pub static INJECTIVE_56_EBE4D495: TokenInfo = TokenInfo { + name: "Injective", + symbol: "INJ", + decimals: 18, + contract: address!("0xa2B726B1145A4773F68593CF171187d8EBe4d495"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237"), +}; + +pub static JUPITER_56_8E140CE7: TokenInfo = TokenInfo { + name: "Jupiter", + symbol: "JUP", + decimals: 18, + contract: address!("0x0231f91e02DebD20345Ae8AB7D71A41f8E140cE7"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/10351/thumb/logo512.png?1632480932"), +}; + +pub static KUJIRA_56_7C9FB5CC: TokenInfo = TokenInfo { + name: "Kujira", + symbol: "KUJI", + decimals: 6, + contract: address!("0x073690e6CE25bE816E68F32dCA3e11067c9FB5Cc"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png"), +}; + +pub static CHAINLINK_TOKEN_56_111A51BD: TokenInfo = TokenInfo { + name: "ChainLink Token", + symbol: "LINK", + decimals: 18, + contract: address!("0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD"), + chain: 56, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), +}; + +pub static MASK_NETWORK_56_F4D568A3: TokenInfo = TokenInfo { + name: "Mask Network", + symbol: "MASK", + decimals: 18, + contract: address!("0x2eD9a5C8C13b93955103B9a7C167B67Ef4d568a3"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316"), +}; + +pub static MATH_56_98A36983: TokenInfo = TokenInfo { + name: "MATH", + symbol: "MATH", + decimals: 18, + contract: address!("0xF218184Af829Cf2b0019F8E6F0b2423498a36983"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590"), +}; + +pub static POLYGON_56_5ED682BD: TokenInfo = TokenInfo { + name: "Polygon", + symbol: "MATIC", + decimals: 18, + contract: address!("0xCC42724C6683B7E57334c4E856f4c9965ED682bD"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), +}; + +pub static MERIT_CIRCLE_56_4EF9E5D6: TokenInfo = TokenInfo { + name: "Merit Circle", + symbol: "MC", + decimals: 18, + contract: address!("0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/19304/thumb/Db4XqML.png?1634972154"), +}; + +pub static METIS_56_B0820639: TokenInfo = TokenInfo { + name: "Metis", + symbol: "METIS", + decimals: 18, + contract: address!("0xe552Fb52a4F19e44ef5A967632DBc320B0820639"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312"), +}; + +pub static MAGIC_INTERNET_MONEY_56_19F433BA: TokenInfo = TokenInfo { + name: "Magic Internet Money", + symbol: "MIM", + decimals: 18, + contract: address!("0xfE19F0B51438fd612f6FD59C1dbB3eA319f433Ba"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612"), +}; + +pub static MIRROR_PROTOCOL_56_10D8C2C9: TokenInfo = TokenInfo { + name: "Mirror Protocol", + symbol: "MIR", + decimals: 18, + contract: address!("0x5B6DcF557E2aBE2323c48445E8CC948910d8c2c9"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/13295/thumb/mirror_logo_transparent.png?1611554658"), +}; + +pub static MULTICHAIN_56_3C8764E3: TokenInfo = TokenInfo { + name: "Multichain", + symbol: "MULTI", + decimals: 18, + contract: address!("0x9Fb9a33956351cf4fa040f65A13b835A3C8764E3"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238"), +}; + +pub static PERPETUAL_PROTOCOL_56_84C7C6F5: TokenInfo = TokenInfo { + name: "Perpetual Protocol", + symbol: "PERP", + decimals: 18, + contract: address!("0x4e7f408be2d4E9D60F49A64B89Bb619c84C7c6F5"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), +}; + +pub static POLKASTARTER_56_0887F570: TokenInfo = TokenInfo { + name: "Polkastarter", + symbol: "POLS", + decimals: 18, + contract: address!("0x7e624FA0E1c4AbFD309cC15719b7E2580887f570"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702"), +}; + +pub static PARSIQ_56_93D2A577: TokenInfo = TokenInfo { + name: "PARSIQ", + symbol: "PRQ", + decimals: 18, + contract: address!("0xd21d29B38374528675C34936bf7d5Dd693D2a577"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280"), +}; + +pub static PSTAKE_FINANCE_56_F58A7C0C: TokenInfo = TokenInfo { + name: "pSTAKE Finance", + symbol: "PSTAKE", + decimals: 18, + contract: address!("0x4C882ec256823eE773B25b414d36F92ef58a7c0C"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/23931/thumb/PSTAKE_Dark.png?1645709930"), +}; + +pub static REVV_56_8D702A93: TokenInfo = TokenInfo { + name: "REVV", + symbol: "REVV", + decimals: 18, + contract: address!("0x833F307aC507D47309fD8CDD1F835BeF8D702a93"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12373/thumb/REVV_TOKEN_Refined_2021_%281%29.png?1627652390"), +}; + +pub static STADER_56_0B5481E8: TokenInfo = TokenInfo { + name: "Stader", + symbol: "SD", + decimals: 18, + contract: address!("0x3BC5AC0dFdC871B365d159f728dd1B9A0B5481E8"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png"), +}; + +pub static SOL_WORMHOLE_56_D3AEA76E: TokenInfo = TokenInfo { + name: "SOL Wormhole ", + symbol: "SOL", + decimals: 9, + contract: address!("0xfA54fF1a158B5189Ebba6ae130CEd6bbd3aEA76e"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), +}; + +pub static STARGATE_FINANCE_56_9631D62B: TokenInfo = TokenInfo { + name: "Stargate Finance", + symbol: "STG", + decimals: 18, + contract: address!("0xB0D502E938ed5f4df2E681fE6E419ff29631d62b"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518"), +}; + +pub static SUPERFARM_56_CC4F0D4D: TokenInfo = TokenInfo { + name: "SuperFarm", + symbol: "SUPER", + decimals: 18, + contract: address!("0x51BA0b044d96C3aBfcA52B64D733603CCC4F0d4D"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899"), +}; + +pub static SUSHI_56_FC9124C4: TokenInfo = TokenInfo { + name: "Sushi", + symbol: "SUSHI", + decimals: 18, + contract: address!("0x947950BcC74888a40Ffa2593C5798F11Fc9124C4"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), +}; + +pub static SWFTCOIN_56_55DFBAD3: TokenInfo = TokenInfo { + name: "SWFTCOIN", + symbol: "SWFTC", + decimals: 18, + contract: address!("0xE64E30276C2F826FEbd3784958d6Da7B55DfbaD3"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/2346/thumb/SWFTCoin.jpg?1618392022"), +}; + +pub static SWIPE_56_FABA485A: TokenInfo = TokenInfo { + name: "Swipe", + symbol: "SXP", + decimals: 18, + contract: address!("0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/9368/thumb/swipe.png?1566792311"), +}; + +pub static SYNAPSE_56_1F9E9484: TokenInfo = TokenInfo { + name: "Synapse", + symbol: "SYN", + decimals: 18, + contract: address!("0xa4080f1778e69467E905B8d6F72f6e441f9e9484"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049"), +}; + +pub static CHRONOTECH_56_DE5D7F68: TokenInfo = TokenInfo { + name: "ChronoTech", + symbol: "TIME", + decimals: 8, + contract: address!("0x3b198e26E473b8faB2085b37978e36c9DE5D7f68"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/604/thumb/time-32x32.png?1627130666"), +}; + +pub static ALIEN_WORLDS_56_EBD57C95: TokenInfo = TokenInfo { + name: "Alien Worlds", + symbol: "TLM", + decimals: 4, + contract: address!("0x2222227E22102Fe3322098e4CBfE18cFebD57c95"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/14676/thumb/kY-C4o7RThfWrDQsLCAG4q4clZhBDDfJQVhWUEKxXAzyQYMj4Jmq1zmFwpRqxhAJFPOa0AsW_PTSshoPuMnXNwq3rU7Imp15QimXTjlXMx0nC088mt1rIwRs75GnLLugWjSllxgzvQ9YrP4tBgclK4_rb17hjnusGj_c0u2fx0AvVokjSNB-v2poTj0xT9BZRCbzRE3-lF1.jpg?1617700061"), +}; + +pub static UNIFI_PROTOCOL_DAO_56_6B814D8B: TokenInfo = TokenInfo { + name: "Unifi Protocol DAO", + symbol: "UNFI", + decimals: 18, + contract: address!("0x728C5baC3C3e370E372Fc4671f9ef6916b814d8B"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/13152/thumb/logo-2.png?1605748967"), +}; + +pub static UNISWAP_56_A02CE9B1: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0xBf5140A22578168FD562DCcF235E5D43A02ce9B1"), + chain: 56, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static PAWTOCOL_56_94334EE4: TokenInfo = TokenInfo { + name: "Pawtocol", + symbol: "UPI", + decimals: 18, + contract: address!("0x0D35A2B85c5A63188d566D104bEbf7C694334Ee4"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12186/thumb/pawtocol.jpg?1597962008"), +}; + +pub static USDCOIN_56_32CD580D: TokenInfo = TokenInfo { + name: "USDCoin", + symbol: "USDC", + decimals: 18, + contract: address!("0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d"), + chain: 56, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), +}; + +pub static TETHER_USD_56_B3197955: TokenInfo = TokenInfo { + name: "Tether USD", + symbol: "USDT", + decimals: 18, + contract: address!("0x55d398326f99059fF775485246999027B3197955"), + chain: 56, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), +}; + +pub static WRAPPED_BNB: TokenInfo = TokenInfo { + name: "Wrapped BNB", + symbol: "WBNB", + decimals: 18, + contract: address!("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"), + chain: 56, + logo_uri: Some("https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/smartchain/assets/0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c/logo.png"), +}; + +pub static WRAPPED_ETHER_56_59F933F8: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0x2170Ed0880ac9A755fd29B2688956BD959F933F8"), + chain: 56, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static WOO_NETWORK_56_9E945D4B: TokenInfo = TokenInfo { + name: "WOO Network", + symbol: "WOO", + decimals: 18, + contract: address!("0x4691937a7508860F876c9c0a2a617E7d9E945D4B"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), +}; + +pub static CHAIN_56_DF88A05B: TokenInfo = TokenInfo { + name: "Chain", + symbol: "XCN", + decimals: 18, + contract: address!("0x7324c7C0d95CEBC73eEa7E85CbAac0dBdf88a05b"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054"), +}; + +pub static LAYERZERO_56_F13271CD: TokenInfo = TokenInfo { + name: "LayerZero", + symbol: "ZRO", + decimals: 18, + contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), + chain: 56, + logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), +}; + +pub static TOKEN_1INCH_130_A9ACD06E: TokenInfo = TokenInfo { + name: "1inch", + symbol: "1INCH", + decimals: 18, + contract: address!("0xbe41cde1C5e75a7b6c2c70466629878aa9ACd06E"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), +}; + +pub static ANCIENT8_130_FEF7759A: TokenInfo = TokenInfo { + name: "Ancient8", + symbol: "A8", + decimals: 18, + contract: address!("0x44D618C366D7bC85945Bfc922ACad5B1feF7759A"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/39170/standard/A8_Token-04_200x200.png?1720798300"), +}; + +pub static AAVE_130_BEEAAE1E: TokenInfo = TokenInfo { + name: "Aave", + symbol: "AAVE", + decimals: 18, + contract: address!("0x02a24C380dA560E4032Dc6671d8164cfbEEAAE1e"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), +}; + +pub static ARCBLOCK_130_FE5675BC: TokenInfo = TokenInfo { + name: "Arcblock", + symbol: "ABT", + decimals: 18, + contract: address!("0xDDCe42b89215548beCaA160048460747Fe5675bC"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2341/thumb/arcblock.png?1547036543"), +}; + +pub static ALCHEMY_PAY_130_E66ECF77: TokenInfo = TokenInfo { + name: "Alchemy Pay", + symbol: "ACH", + decimals: 8, + contract: address!("0xb8A8e137A2dAa25EF1B3577b6598fE8Be66Ecf77"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12390/thumb/ACH_%281%29.png?1599691266"), +}; + +pub static ACROSS_PROTOCOL_TOKEN_130_62BBB32C: TokenInfo = TokenInfo { + name: "Across Protocol Token", + symbol: "ACX", + decimals: 18, + contract: address!("0x34424B3352af905e41078a4029b61EDe62BbB32C"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165"), +}; + +pub static AMBIRE_ADEX_130_A299A500: TokenInfo = TokenInfo { + name: "Ambire AdEx", + symbol: "ADX", + decimals: 18, + contract: address!("0x3e1C572d8b069fc2f14ac4f8bdCE6e8eA299A500"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540"), +}; + +pub static AERGO_130_F15873B5: TokenInfo = TokenInfo { + name: "Aergo", + symbol: "AERGO", + decimals: 18, + contract: address!("0xfd38ac2316f6d3631a86065aDb3292f6f15873B5"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/4490/thumb/aergo.png?1647696770"), +}; + +pub static AEVO_130_60D60F8B: TokenInfo = TokenInfo { + name: "Aevo", + symbol: "AEVO", + decimals: 18, + contract: address!("0x54FA9210cCB765639b7Fd532f25bCb1060D60F8B"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/35893/standard/aevo.png"), +}; + +pub static AGEUR_130_C681A118: TokenInfo = TokenInfo { + name: "agEur", + symbol: "agEUR", + decimals: 18, + contract: address!("0xA4eeF95995F40aD0b3D63a474293Fc7CC681A118"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), +}; + +pub static ADVENTURE_GOLD_130_412721CF: TokenInfo = TokenInfo { + name: "Adventure Gold", + symbol: "AGLD", + decimals: 18, + contract: address!("0x14421614587A2A3e9C3Aa3131Fc396aF412721CF"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/18125/thumb/lpgblc4h_400x400.jpg?1630570955"), +}; + +pub static AIOZ_NETWORK_130_6CF99B1A: TokenInfo = TokenInfo { + name: "AIOZ Network", + symbol: "AIOZ", + decimals: 18, + contract: address!("0x5F891E74947b0FC400128E5E85333d7a6cF99b1A"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126"), +}; + +pub static ALCHEMIX_130_5AEBDCD6: TokenInfo = TokenInfo { + name: "Alchemix", + symbol: "ALCX", + decimals: 18, + contract: address!("0xbf194C82A5Bb9180f9280c1832f886a65Aebdcd6"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14113/thumb/Alchemix.png?1614409874"), +}; + +pub static ALEPH_IM_130_4C15BB5C: TokenInfo = TokenInfo { + name: "Aleph im", + symbol: "ALEPH", + decimals: 18, + contract: address!("0xa3E646211a456e08829C33fcE21cC3DC4c15Bb5c"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725"), +}; + +pub static ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_130_EEC73780: TokenInfo = TokenInfo { + name: "Alethea Artificial Liquid Intelligence", + symbol: "ALI", + decimals: 18, + contract: address!("0x2a87dd1e1F849ed88C18565AFDa98e2EEEc73780"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848"), +}; + +pub static MY_NEIGHBOR_ALICE_130_8860960A: TokenInfo = TokenInfo { + name: "My Neighbor Alice", + symbol: "ALICE", + decimals: 6, + contract: address!("0xBb72B8031F590748d8910Aad7e25F8B18860960a"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14375/thumb/alice_logo.jpg?1615782968"), +}; + +pub static ALPHA_VENTURE_DAO_130_CEBD78D3: TokenInfo = TokenInfo { + name: "Alpha Venture DAO", + symbol: "ALPHA", + decimals: 18, + contract: address!("0x44c3E7c49C4Bb6f4f5eCD87E035176dFceBD78d3"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876"), +}; + +pub static ALTLAYER_130_B3589153: TokenInfo = TokenInfo { + name: "AltLayer", + symbol: "ALT", + decimals: 18, + contract: address!("0x6D5De04F1a3E0e554B9A15059d03e20cb3589153"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/34608/standard/Logomark_200x200.png"), +}; + +pub static AMP_130_2BBC967F: TokenInfo = TokenInfo { + name: "Amp", + symbol: "AMP", + decimals: 18, + contract: address!("0x4D6B8ecb576dF9BB4bF6E6764A469a762bBc967F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12409/thumb/amp-200x200.png?1599625397"), +}; + +pub static ANKR_130_EFF97622: TokenInfo = TokenInfo { + name: "Ankr", + symbol: "ANKR", + decimals: 18, + contract: address!("0xf081Fc8E0878D7eBe6ec381E5d7279d6EFf97622"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978"), +}; + +pub static ARAGON_130_D4A31308: TokenInfo = TokenInfo { + name: "Aragon", + symbol: "ANT", + decimals: 18, + contract: address!("0x865d184885200B8e86eb2a3Da8b3B4a7d4A31308"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/681/thumb/JelZ58cv_400x400.png?1601449653"), +}; + +pub static APECOIN_130_314046CF: TokenInfo = TokenInfo { + name: "ApeCoin", + symbol: "APE", + decimals: 18, + contract: address!("0xD1b8423FdE5F37464FadE603f80903cB314046cf"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/24383/small/apecoin.jpg?1647476455"), +}; + +pub static API3_130_F678961B: TokenInfo = TokenInfo { + name: "API3", + symbol: "API3", + decimals: 18, + contract: address!("0xA63122b27308EED0C1D83DD355ADdaA7f678961b"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13256/thumb/api3.jpg?1606751424"), +}; + +pub static APU_APUSTAJA_130_63B9E379: TokenInfo = TokenInfo { + name: "Apu Apustaja", + symbol: "APU", + decimals: 18, + contract: address!("0xcDfcE5eb357E8976A80Be84E94a03BA963b9e379"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/35986/large/200x200.png?1710308147"), +}; + +pub static ARBITRUM_130_18A4B40D: TokenInfo = TokenInfo { + name: "Arbitrum", + symbol: "ARB", + decimals: 18, + contract: address!("0x5cC70a9DF8E293aFFb14DFCa1e7F851418a4b40d"), + chain: 130, + logo_uri: Some("https://arbitrum.foundation/logo.png"), +}; + +pub static ARKHAM_130_442EF089: TokenInfo = TokenInfo { + name: "Arkham", + symbol: "ARKM", + decimals: 18, + contract: address!("0x59F16BaA7A22f49c32680661e0041A53442Ef089"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/30929/standard/Arkham_Logo_CG.png?1696529771"), +}; + +pub static ARPA_CHAIN_130_88E30B45: TokenInfo = TokenInfo { + name: "ARPA Chain", + symbol: "ARPA", + decimals: 18, + contract: address!("0xE911A809F87490406AB34fad701aabCA88e30b45"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/8506/thumb/9u0a23XY_400x400.jpg?1559027357"), +}; + +pub static ASH_130_5A30D7FB: TokenInfo = TokenInfo { + name: "ASH", + symbol: "ASH", + decimals: 18, + contract: address!("0x4b355De6Ea44711f0353Ed89545705395a30d7Fb"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/15714/thumb/omnPqaTY.png?1622820503"), +}; + +pub static ASSEMBLE_PROTOCOL_130_5BA0ADA7: TokenInfo = TokenInfo { + name: "Assemble Protocol", + symbol: "ASM", + decimals: 18, + contract: address!("0x1e196D83e2c562de0b1f270Eb72220335bA0ADa7"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11605/thumb/gpvrlkSq_400x400_%281%29.jpg?1591775789"), +}; + +pub static AIRSWAP_130_8C09AE56: TokenInfo = TokenInfo { + name: "AirSwap", + symbol: "AST", + decimals: 4, + contract: address!("0x7F3F14A49FE5D5009E4e0a09e76cB8468C09Ae56"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1019/thumb/Airswap.png?1630903484"), +}; + +pub static AUTOMATA_130_D890C4B2: TokenInfo = TokenInfo { + name: "Automata", + symbol: "ATA", + decimals: 18, + contract: address!("0xBAAa314d2f5Af29B00867a612F24F816d890C4B2"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745"), +}; + +pub static AETHIR_TOKEN_130_FEE183AB: TokenInfo = TokenInfo { + name: "Aethir Token", + symbol: "ATH", + decimals: 18, + contract: address!("0xa249732271cbA6E06Be4ac8B20f0D465FeE183Ab"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/36179/large/logogram_circle_dark_green_vb_green_(1).png?1718232706"), +}; + +pub static BOUNCE_130_91BEF68E: TokenInfo = TokenInfo { + name: "Bounce", + symbol: "AUCTION", + decimals: 18, + contract: address!("0x82F90996a4F67Eb388116B3C6F35B6Ea91BeF68E"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13860/thumb/1_KtgpRIJzuwfHe0Rl0avP_g.jpeg?1612412025"), +}; + +pub static AUDIUS_130_3C81684B: TokenInfo = TokenInfo { + name: "Audius", + symbol: "AUDIO", + decimals: 18, + contract: address!("0x48b8441dE79cEE3604b805093B41028d3c81684B"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12913/thumb/AudiusCoinLogo_2x.png?1603425727"), +}; + +pub static ARTVERSE_TOKEN_130_00939999: TokenInfo = TokenInfo { + name: "Artverse Token", + symbol: "AVT", + decimals: 18, + contract: address!("0x38DBf47e2a012a4b83823f15E3F3352A00939999"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/19727/thumb/ewnektoB_400x400.png?1635767094"), +}; + +pub static AXELAR_130_A4CBF2C9: TokenInfo = TokenInfo { + name: "Axelar", + symbol: "AXL", + decimals: 6, + contract: address!("0xbF678793522638F7439aFE3B94d2D2A3a4cBF2C9"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg"), +}; + +pub static AXIE_INFINITY_130_D188F927: TokenInfo = TokenInfo { + name: "Axie Infinity", + symbol: "AXS", + decimals: 18, + contract: address!("0xDA63AdA216d2079B54F2047B2FdC2576D188f927"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082"), +}; + +pub static BADGER_DAO_130_17388406: TokenInfo = TokenInfo { + name: "Badger DAO", + symbol: "BADGER", + decimals: 18, + contract: address!("0xc2a564b44b441D03f09f5B6B2b358B4a17388406"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13287/thumb/badger_dao_logo.jpg?1607054976"), +}; + +pub static BALANCER_130_34A8ADDF: TokenInfo = TokenInfo { + name: "Balancer", + symbol: "BAL", + decimals: 18, + contract: address!("0x01625E26274Ed828Ac1d47694c97221b34a8ADdF"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png"), +}; + +pub static BAND_PROTOCOL_130_6A8857D5: TokenInfo = TokenInfo { + name: "Band Protocol", + symbol: "BAND", + decimals: 18, + contract: address!("0xa264F2b88C630f260AbDcAb577eAB7266A8857d5"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/9545/thumb/band-protocol.png?1568730326"), +}; + +pub static BASIC_ATTENTION_TOKEN_130_508EA589: TokenInfo = TokenInfo { + name: "Basic Attention Token", + symbol: "BAT", + decimals: 18, + contract: address!("0x4e373C99199773f9D92d32B8c8Bc0C81508ea589"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427"), +}; + +pub static BEAM_130_F9500824: TokenInfo = TokenInfo { + name: "Beam", + symbol: "BEAM", + decimals: 18, + contract: address!("0xe5ECB192f1aE5839eD49886F36dFA670f9500824"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/32417/standard/chain-logo.png?1698114384"), +}; + +pub static BICONOMY_130_1D0588E7: TokenInfo = TokenInfo { + name: "Biconomy", + symbol: "BICO", + decimals: 18, + contract: address!("0x604Ff88ADC02325EFb7f93DB3E442dc81D0588E7"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749"), +}; + +pub static BIG_TIME_130_D2FA7CDC: TokenInfo = TokenInfo { + name: "Big Time", + symbol: "BIGTIME", + decimals: 18, + contract: address!("0x17f3AfE72cAa6b9090801b60607918b6D2Fa7cdc"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/32251/standard/-6136155493475923781_121.jpg?1696998691"), +}; + +pub static BITDAO_130_FB523A5C: TokenInfo = TokenInfo { + name: "BitDAO", + symbol: "BIT", + decimals: 18, + contract: address!("0xA4Cb2aaf7503641B441e80fC353e6748fb523A5C"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/17627/thumb/rI_YptK8.png?1653983088"), +}; + +pub static HARRYPOTTEROBAMASONIC10INU_130_9B3D706F: TokenInfo = TokenInfo { + name: "HarryPotterObamaSonic10Inu", + symbol: "BITCOIN", + decimals: 8, + contract: address!("0x41f6e69166e81A9583DBc96604B01D2E9B3D706f"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224"), +}; + +pub static BLUR_130_2B9255EA: TokenInfo = TokenInfo { + name: "Blur", + symbol: "BLUR", + decimals: 18, + contract: address!("0x942fC6b61686e06fB411cB1bCf5d16DC2b9255eA"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/28453/large/blur.png?1670745921"), +}; + +pub static BLUZELLE_130_8EF471EE: TokenInfo = TokenInfo { + name: "Bluzelle", + symbol: "BLZ", + decimals: 18, + contract: address!("0xe7b3Ca9d9Db06E1867781fd1C5F02E6c8eF471ee"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2848/thumb/ColorIcon_3x.png?1622516510"), +}; + +pub static BANCOR_NETWORK_TOKEN_130_472C5A62: TokenInfo = TokenInfo { + name: "Bancor Network Token", + symbol: "BNT", + decimals: 18, + contract: address!("0xf2Cc2D274dA528AB64DA86bE3f8416E5472c5a62"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png"), +}; + +pub static BOBA_NETWORK_130_BBB41B05: TokenInfo = TokenInfo { + name: "Boba Network", + symbol: "BOBA", + decimals: 18, + contract: address!("0xBE8E46422fB7F9Ca9D639B3109492D64BbB41b05"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/20285/thumb/BOBA.png?1636811576"), +}; + +pub static BARNBRIDGE_130_61DF8972: TokenInfo = TokenInfo { + name: "BarnBridge", + symbol: "BOND", + decimals: 18, + contract: address!("0x4d5b7e9CCE3Ab81298dA7E1F52b48c9a61Df8972"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853"), +}; + +pub static BONK: TokenInfo = TokenInfo { + name: "BONK", + symbol: "BONK", + decimals: 5, + contract: address!("0xBbE97f3522101e5B6976cBf77376047097BA837F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/28600/standard/bonk.jpg?1696527587"), +}; + +pub static BRAINTRUST_130_00986B71: TokenInfo = TokenInfo { + name: "Braintrust", + symbol: "BTRST", + decimals: 18, + contract: address!("0x6A4a359C7453F5892392FCb8eAB7A9A100986B71"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/18100/thumb/braintrust.PNG?1630475394"), +}; + +pub static BINANCE_USD_130_BDA9F9C6: TokenInfo = TokenInfo { + name: "Binance USD", + symbol: "BUSD", + decimals: 18, + contract: address!("0xa4da5c92F44422dFA3E2E309b53d93bbbDa9f9c6"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), +}; + +pub static COIN98_130_F8E4F8E1: TokenInfo = TokenInfo { + name: "Coin98", + symbol: "C98", + decimals: 18, + contract: address!("0x29129fa2e0F35594ca7b362fFA8c80f5f8e4f8E1"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/17117/thumb/logo.png?1626412904"), +}; + +pub static COINBASE_WRAPPED_BTC_130_AB6A1EF1: TokenInfo = TokenInfo { + name: "Coinbase Wrapped BTC", + symbol: "cbBTC", + decimals: 8, + contract: address!("0xb6A3E8e5715fd4c99EcEDaaAe121bDe4Ab6a1Ef1"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/40143/standard/cbbtc.webp"), +}; + +pub static COINBASE_WRAPPED_STAKED_ETH_130_8211DB59: TokenInfo = TokenInfo { + name: "Coinbase Wrapped Staked ETH", + symbol: "cbETH", + decimals: 18, + contract: address!("0xEb64b50FeF2A363940369285F86Ae9a68211db59"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/27008/large/cbeth.png"), +}; + +pub static CELO_NATIVE_ASSET_WORMHOLE_130_5A8A8D9C: TokenInfo = TokenInfo { + name: "Celo native asset (Wormhole)", + symbol: "CELO", + decimals: 18, + contract: address!("0x6008F5BaD83742fDbFf5AAc55e3c51b65A8A8D9C"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png"), +}; + +pub static CELER_NETWORK_130_48035703: TokenInfo = TokenInfo { + name: "Celer Network", + symbol: "CELR", + decimals: 18, + contract: address!("0x5AD5d6B1AE6761Aab12066b51D21729248035703"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/4379/thumb/Celr.png?1554705437"), +}; + +pub static CHROMIA_130_210A4E5B: TokenInfo = TokenInfo { + name: "Chromia", + symbol: "CHR", + decimals: 6, + contract: address!("0xAC930Be88cFAc775A937E9291c4234Bf210a4e5b"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/5000/thumb/Chromia.png?1559038018"), +}; + +pub static CHILIZ_130_8B2396B0: TokenInfo = TokenInfo { + name: "Chiliz", + symbol: "CHZ", + decimals: 18, + contract: address!("0xb0C69e24450e29afa8008962052007E08b2396b0"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/8834/thumb/Chiliz.png?1561970540"), +}; + +pub static CLOVER_FINANCE_130_FA41404C: TokenInfo = TokenInfo { + name: "Clover Finance", + symbol: "CLV", + decimals: 18, + contract: address!("0xD7212097f6d6B195a9Bc350b8dCE28a7fA41404C"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/15278/thumb/clover.png?1645084454"), +}; + +pub static COMPOUND_130_F2288656: TokenInfo = TokenInfo { + name: "Compound", + symbol: "COMP", + decimals: 18, + contract: address!("0xdf78e4F0A8279942ca68046476919A90f2288656"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), +}; + +pub static COTI_130_32F499C3: TokenInfo = TokenInfo { + name: "COTI", + symbol: "COTI", + decimals: 18, + contract: address!("0xc63612B3e697AEeC61C3Ce9baEc0f9Db32F499C3"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2962/thumb/Coti.png?1559653863"), +}; + +pub static CIRCUITS_OF_VALUE_130_CC295BEC: TokenInfo = TokenInfo { + name: "Circuits of Value", + symbol: "COVAL", + decimals: 8, + contract: address!("0x2562DC34c21371613CEF236b321EE63fCC295beC"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/588/thumb/coval-logo.png?1599493950"), +}; + +pub static COW_PROTOCOL_130_B26D3996: TokenInfo = TokenInfo { + name: "CoW Protocol", + symbol: "COW", + decimals: 18, + contract: address!("0xC3a97c76AA194711E05Ff1d181534090B26D3996"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/24384/large/CoW-token_logo.png?1719524382"), +}; + +pub static CLEARPOOL_130_423DFB57: TokenInfo = TokenInfo { + name: "Clearpool", + symbol: "CPOOL", + decimals: 18, + contract: address!("0xF8E7B485CE10D3C7Ac30B8444B98a0cC423dFb57"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/19252/large/photo_2022-08-31_12.45.02.jpeg?1696518697"), +}; + +pub static COVALENT_130_621F90C1: TokenInfo = TokenInfo { + name: "Covalent", + symbol: "CQT", + decimals: 18, + contract: address!("0x6C28eeB9E018011d3841f42c5b458713621F90C1"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14168/thumb/covalent-cqt.png?1624545218"), +}; + +pub static CRONOS_130_A30DE818: TokenInfo = TokenInfo { + name: "Cronos", + symbol: "CRO", + decimals: 8, + contract: address!("0x73c63A80Ec77BFe31eEc6663828C4beaA30dE818"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/7310/thumb/oCw2s3GI_400x400.jpeg?1645172042"), +}; + +pub static CRYPTERIUM_130_18B0D066: TokenInfo = TokenInfo { + name: "Crypterium", + symbol: "CRPT", + decimals: 18, + contract: address!("0x7e7784f13029c7C4BF4746112B1A503818B0D066"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1901/thumb/crypt.png?1547036205"), +}; + +pub static CURVE_DAO_TOKEN_130_D1C2CCB3: TokenInfo = TokenInfo { + name: "Curve DAO Token", + symbol: "CRV", + decimals: 18, + contract: address!("0xAC73671a1762FE835208Fb93b7aE7490d1c2cCb3"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), +}; + +pub static CARTESI_130_BAAED2C5: TokenInfo = TokenInfo { + name: "Cartesi", + symbol: "CTSI", + decimals: 18, + contract: address!("0xa7073F530856cD32c2037150dd9763B9BAaED2C5"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), +}; + +pub static CRYPTEX_FINANCE_130_62FCB619: TokenInfo = TokenInfo { + name: "Cryptex Finance", + symbol: "CTX", + decimals: 18, + contract: address!("0x36fA435F6def83cbB7a0706d035C9eA062fCb619"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171"), +}; + +pub static SOMNIUM_SPACE_CUBES_130_92C2F8AF: TokenInfo = TokenInfo { + name: "Somnium Space CUBEs", + symbol: "CUBE", + decimals: 8, + contract: address!("0xE60e9b2E68297d5DF6B383fEe787B7fB92c2F8aF"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/10687/thumb/CUBE_icon.png?1617026861"), +}; + +pub static CIVIC_130_E85A01ED: TokenInfo = TokenInfo { + name: "Civic", + symbol: "CVC", + decimals: 8, + contract: address!("0x35C458aD1e3e68d2717C8349b985384Be85a01Ed"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556"), +}; + +pub static CONVEX_FINANCE_130_F0087EA5: TokenInfo = TokenInfo { + name: "Convex Finance", + symbol: "CVX", + decimals: 18, + contract: address!("0x1C6789F30e7E335c2Eca2c75EC193aDBF0087Ea5"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/15585/thumb/convex.png?1621256328"), +}; + +pub static COVALENT_X_TOKEN_130_F14E5A09: TokenInfo = TokenInfo { + name: "Covalent X Token", + symbol: "CXT", + decimals: 18, + contract: address!("0x8E29E12B46FeE20E034fE1e812bc12EFf14E5A09"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/39177/large/CXT_Ticker.png?1720829918"), +}; + +pub static DAI_STABLECOIN_130_19573F81: TokenInfo = TokenInfo { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + contract: address!("0x20CAb320A855b39F724131C69424240519573f81"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), +}; + +pub static MINES_OF_DALARNIA_130_90288086: TokenInfo = TokenInfo { + name: "Mines of Dalarnia", + symbol: "DAR", + decimals: 6, + contract: address!("0x2ef0775A19d1bc2258653fc5529F8f8490288086"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/19837/thumb/dar.png?1636014223"), +}; + +pub static DERIVADAO_130_3A270265: TokenInfo = TokenInfo { + name: "DerivaDAO", + symbol: "DDX", + decimals: 18, + contract: address!("0x91ED4bb192e3461E45575730508525083A270265"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13453/thumb/ddx_logo.png?1608741641"), +}; + +pub static DENT_130_328E874C: TokenInfo = TokenInfo { + name: "Dent", + symbol: "DENT", + decimals: 8, + contract: address!("0x45a4f750d806498A4c7f7B5267815aaC328e874C"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1152/thumb/gLCEA2G.png?1604543239"), +}; + +pub static DEXTOOLS_130_1723CDDD: TokenInfo = TokenInfo { + name: "DexTools", + symbol: "DEXT", + decimals: 18, + contract: address!("0x17C38207334011a131b0Acf200E35Cd81723cddd"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188"), +}; + +pub static DIA_130_3F9543C2: TokenInfo = TokenInfo { + name: "DIA", + symbol: "DIA", + decimals: 18, + contract: address!("0x4bdc8553cf14EEBCD489cD1d75b7FF463f9543c2"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751"), +}; + +pub static DISTRICT0X_130_C1B9E545: TokenInfo = TokenInfo { + name: "district0x", + symbol: "DNT", + decimals: 18, + contract: address!("0x0eb07cE7a28FF84DF132fb5ee5F56Aabc1b9E545"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/849/thumb/district0x.png?1547223762"), +}; + +pub static DOGECOIN: TokenInfo = TokenInfo { + name: "Dogecoin", + symbol: "DOGE", + decimals: 18, + contract: address!("0x12E96C2BFEA6E835CF8Dd38a5834fa61Cf723736"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/5/standard/dogecoin.png?1696501409"), +}; + +pub static DEFI_PULSE_INDEX_130_CD2F84F1: TokenInfo = TokenInfo { + name: "DeFi Pulse Index", + symbol: "DPI", + decimals: 18, + contract: address!("0xE274f564c37aE15fd2570D544102eD4ACd2f84f1"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12465/thumb/defi_pulse_index_set.png?1600051053"), +}; + +pub static DREP_130_38EA9EE7: TokenInfo = TokenInfo { + name: "Drep", + symbol: "DREP", + decimals: 18, + contract: address!("0x56aF109D597eb0a0F79ebCD0786Dd88C38EA9Ee7"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14578/thumb/KotgsCgS_400x400.jpg?1617094445"), +}; + +pub static DYDX_130_5FAEB82C: TokenInfo = TokenInfo { + name: "dYdX", + symbol: "DYDX", + decimals: 18, + contract: address!("0x601b11907EAa8d3785C0b10b41C3a7315faeB82c"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/17500/thumb/hjnIm9bV.jpg?1628009360"), +}; + +pub static DEFI_YIELD_PROTOCOL_130_9D598610: TokenInfo = TokenInfo { + name: "DeFi Yield Protocol", + symbol: "DYP", + decimals: 18, + contract: address!("0xBdaD8E37a9600F0A35976fE61608a4C89D598610"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066"), +}; + +pub static EIGENLAYER_130_D016C47D: TokenInfo = TokenInfo { + name: "EigenLayer", + symbol: "EIGEN", + decimals: 18, + contract: address!("0xc89ab9B82610BB9b748F6757b8F3ac59d016C47D"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/37441/large/eigen.jpg?1728023974"), +}; + +pub static ELASTOS_130_D8E8C1AB: TokenInfo = TokenInfo { + name: "Elastos", + symbol: "ELA", + decimals: 18, + contract: address!("0x24aBc32215354Ba3eD224bfa6312E31dD8E8c1ab"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2780/thumb/Elastos.png?1597048112"), +}; + +pub static DOGELON_MARS_130_26C1DE05: TokenInfo = TokenInfo { + name: "Dogelon Mars", + symbol: "ELON", + decimals: 18, + contract: address!("0x91441fE1415B00bEA8930A4354Fe00c426C1DE05"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413"), +}; + +pub static ETHENA_130_A6CBD2DD: TokenInfo = TokenInfo { + name: "Ethena", + symbol: "ENA", + decimals: 18, + contract: address!("0x9116E70d613860D349495d9Ef8e2AE1cA6cBD2dd"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/36530/standard/ethena.png"), +}; + +pub static ENJIN_COIN_130_84A6D0A6: TokenInfo = TokenInfo { + name: "Enjin Coin", + symbol: "ENJ", + decimals: 18, + contract: address!("0x9A0D1b7594CAAF0A9e4687cAc9fF4E0B84a6d0A6"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1102/thumb/enjin-coin-logo.png?1547035078"), +}; + +pub static ETHEREUM_NAME_SERVICE_130_B5F0383A: TokenInfo = TokenInfo { + name: "Ethereum Name Service", + symbol: "ENS", + decimals: 18, + contract: address!("0x80756FAf1e7Fec5678bf505670eF176AB5F0383a"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140"), +}; + +pub static ETHERNITY_CHAIN_130_A93CDB03: TokenInfo = TokenInfo { + name: "Ethernity Chain", + symbol: "ERN", + decimals: 18, + contract: address!("0x5E5903C236E6873EB8400C3d1979271Fa93cdB03"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14238/thumb/LOGO_HIGH_QUALITY.png?1647831402"), +}; + +pub static ETHER_FI_130_58880821: TokenInfo = TokenInfo { + name: "Ether.fi", + symbol: "ETHFI", + decimals: 18, + contract: address!("0xF8740269F121327D03ff77BeD03a9A3258880821"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/35958/standard/etherfi.jpeg"), +}; + +pub static EULER_130_5B5D03FE: TokenInfo = TokenInfo { + name: "Euler", + symbol: "EUL", + decimals: 18, + contract: address!("0x6319F47719b6713b1624C1b3A8e2DBf15b5D03FE"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/26149/thumb/YCvKDfl8_400x400.jpeg?1656041509"), +}; + +pub static EURO_COIN_130_2813B0A8: TokenInfo = TokenInfo { + name: "Euro Coin", + symbol: "EURC", + decimals: 6, + contract: address!("0x72f34BC403a005A9Be390762EAa46ED42813B0a8"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420"), +}; + +pub static QUANTOZ_EURQ_130_24D7D72D: TokenInfo = TokenInfo { + name: "Quantoz EURQ", + symbol: "EURQ", + decimals: 6, + contract: address!("0xEc42461D9BbDF4eFB6481099253bBB7324D7d72d"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/51853/large/EURQ_1000px_Color.png?1732071269"), +}; + +pub static STABLR_EURO_130_9C36FB5F: TokenInfo = TokenInfo { + name: "StablR Euro", + symbol: "EURR", + decimals: 6, + contract: address!("0x7A1ef7fD6E0d708295D8FD0C30Fd437d9C36FB5f"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/53720/large/stablreuro-logo.png?1737125898"), +}; + +pub static HARVEST_FINANCE_130_31EE825F: TokenInfo = TokenInfo { + name: "Harvest Finance", + symbol: "FARM", + decimals: 18, + contract: address!("0x472E8be16Cc9823b9f6a73A34EA55c0c31ee825F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180"), +}; + +pub static FETCH_AI_130_DDD7DFE7: TokenInfo = TokenInfo { + name: "Fetch ai", + symbol: "FET", + decimals: 18, + contract: address!("0x45343279DefDAd803d81C06fBCf87936DDD7DFE7"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136"), +}; + +pub static STAFI_130_A10764A6: TokenInfo = TokenInfo { + name: "Stafi", + symbol: "FIS", + decimals: 18, + contract: address!("0xec9Be303f204864145CCC193aEb21B5fa10764A6"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991"), +}; + +pub static FLOKI_130_6C51FA81: TokenInfo = TokenInfo { + name: "FLOKI", + symbol: "FLOKI", + decimals: 9, + contract: address!("0x1b3EC249dc44a64bF5Cb8Afdd70e30c26c51fA81"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318"), +}; + +pub static FORTA_130_D87D94E5: TokenInfo = TokenInfo { + name: "Forta", + symbol: "FORT", + decimals: 18, + contract: address!("0xB20fD6fD28e1430f98a8C1e9A83C88E5D87D94e5"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/25060/thumb/Forta_lgo_%281%29.png?1655353696"), +}; + +pub static AMPLEFORTH_GOVERNANCE_TOKEN_130_2220F12E: TokenInfo = TokenInfo { + name: "Ampleforth Governance Token", + symbol: "FORTH", + decimals: 18, + contract: address!("0xFa004fa2ad8Ef993C2B0412baB776b182220F12e"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14917/thumb/photo_2021-04-22_00.00.03.jpeg?1619020835"), +}; + +pub static SHAPESHIFT_FOX_TOKEN_130_3B7A318E: TokenInfo = TokenInfo { + name: "ShapeShift FOX Token", + symbol: "FOX", + decimals: 18, + contract: address!("0xe0BB1924C17b39B71758F49a00D7c0363B7a318E"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622"), +}; + +pub static FRAX_130_D74132B9: TokenInfo = TokenInfo { + name: "Frax", + symbol: "FRAX", + decimals: 18, + contract: address!("0x8c7879bf25D678D9949F305857bD4437d74132B9"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), +}; + +pub static FANTOM_130_90DC7F0E: TokenInfo = TokenInfo { + name: "Fantom", + symbol: "FTM", + decimals: 18, + contract: address!("0xe99235A02958637a5e01575297fBBa3790dC7F0e"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016"), +}; + +pub static FUNCTION_X_130_1D7AF1AF: TokenInfo = TokenInfo { + name: "Function X", + symbol: "FX", + decimals: 18, + contract: address!("0x6F32725F82Bbb06FFdC04974db437fec1d7af1Af"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/8186/thumb/47271330_590071468072434_707260356350705664_n.jpg?1556096683"), +}; + +pub static FRAX_SHARE_130_062021D6: TokenInfo = TokenInfo { + name: "Frax Share", + symbol: "FXS", + decimals: 18, + contract: address!("0x79301DF2117C7F56859fD01b28bBAA61062021D6"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), +}; + +pub static GRAVITY_130_6FD8803C: TokenInfo = TokenInfo { + name: "Gravity", + symbol: "G", + decimals: 18, + contract: address!("0x481cB2C560fc3351833b582b92b965626fd8803C"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/39200/large/gravity.jpg?1721020647"), +}; + +pub static GALXE_130_443D8675: TokenInfo = TokenInfo { + name: "Galxe", + symbol: "GAL", + decimals: 18, + contract: address!("0x70b2b785061d4c91C76CF87692f85B5c443d8675"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533"), +}; + +pub static GALA_130_B560FAC9: TokenInfo = TokenInfo { + name: "GALA", + symbol: "GALA", + decimals: 8, + contract: address!("0x31A71801291774d267615f74b3a44FCEB560FAc9"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12493/standard/GALA-COINGECKO.png?1696512310"), +}; + +pub static GOLDFINCH_130_B157D3D0: TokenInfo = TokenInfo { + name: "Goldfinch", + symbol: "GFI", + decimals: 18, + contract: address!("0x0328A0255866706547B79072DEE54976b157d3D0"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/19081/thumb/GOLDFINCH.png?1634369662"), +}; + +pub static AAVEGOTCHI_130_840AD24B: TokenInfo = TokenInfo { + name: "Aavegotchi", + symbol: "GHST", + decimals: 18, + contract: address!("0x4aE5712A153fDfDE81C305fF7f2E4e59840aD24B"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12467/thumb/ghst_200.png?1600750321"), +}; + +pub static GOLEM_130_E2C9F2B9: TokenInfo = TokenInfo { + name: "Golem", + symbol: "GLM", + decimals: 18, + contract: address!("0x04b747f478AE09AC797d026C8402f409E2C9f2b9"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/542/thumb/Golem_Submark_Positive_RGB.png?1606392013"), +}; + +pub static GNOSIS_TOKEN_130_E125A938: TokenInfo = TokenInfo { + name: "Gnosis Token", + symbol: "GNO", + decimals: 18, + contract: address!("0xC4c6c3A3043Ad5ECe5c91290630A7735e125a938"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png"), +}; + +pub static GODS_UNCHAINED_130_D3683F48: TokenInfo = TokenInfo { + name: "Gods Unchained", + symbol: "GODS", + decimals: 18, + contract: address!("0x6E74EA6546e1f21Abf581b59114f2Bf5d3683f48"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/17139/thumb/10631.png?1635718182"), +}; + +pub static THE_GRAPH_130_B3204D71: TokenInfo = TokenInfo { + name: "The Graph", + symbol: "GRT", + decimals: 18, + contract: address!("0xBb2272Ffc0Ef8F439373aDffD45c3591B3204D71"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566"), +}; + +pub static GITCOIN_130_8FE5CF48: TokenInfo = TokenInfo { + name: "Gitcoin", + symbol: "GTC", + decimals: 18, + contract: address!("0x592620d454a10c47274dBfe3BD922b9a8fE5cf48"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929"), +}; + +pub static GEMINI_DOLLAR_130_5C0920A9: TokenInfo = TokenInfo { + name: "Gemini Dollar", + symbol: "GUSD", + decimals: 2, + contract: address!("0xEbA12eC786Cdc21b4bd5ba601B595b6A5C0920a9"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/5992/thumb/gemini-dollar-gusd.png?1536745278"), +}; + +pub static GYEN_130_A574C36F: TokenInfo = TokenInfo { + name: "GYEN", + symbol: "GYEN", + decimals: 6, + contract: address!("0xad173F5B5FE39DD1183a0d3C49C57629A574c36F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343"), +}; + +pub static HASHFLOW_130_8C34A28B: TokenInfo = TokenInfo { + name: "Hashflow", + symbol: "HFT", + decimals: 18, + contract: address!("0x656104f2028BbFD7144C8f71Fa15daaA8c34A28b"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/26136/large/hashflow-icon-cmc.png"), +}; + +pub static HIGHSTREET_130_B1374879: TokenInfo = TokenInfo { + name: "Highstreet", + symbol: "HIGH", + decimals: 18, + contract: address!("0x99F64C3Db98a4870eFf637315d5C86dcb1374879"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470"), +}; + +pub static HOPR_130_AF385B36: TokenInfo = TokenInfo { + name: "HOPR", + symbol: "HOPR", + decimals: 18, + contract: address!("0xc32C0c5a52F36D244C552E45C485cBceaf385B36"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14061/thumb/Shared_HOPR_logo_512px.png?1614073468"), +}; + +pub static HYPERLIQUID: TokenInfo = TokenInfo { + name: "Hyperliquid", + symbol: "HYPE", + decimals: 18, + contract: address!("0x15D0e0c55a3E7eE67152aD7E89acf164253Ff68d"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/50882/large/hyperliquid.jpg?1729431300"), +}; + +pub static IDEX_130_60EABE8E: TokenInfo = TokenInfo { + name: "IDEX", + symbol: "IDEX", + decimals: 18, + contract: address!("0x4eA052BcAeE7d7ef2E3D61D601e878A560eaBe8e"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2565/thumb/logomark-purple-286x286.png?1638362736"), +}; + +pub static ILLUVIUM_130_42F3E51F: TokenInfo = TokenInfo { + name: "Illuvium", + symbol: "ILV", + decimals: 18, + contract: address!("0xa76195FA77304Bba4cD8946198f5a90E42F3E51F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14468/large/ILV.JPG"), +}; + +pub static IMMUTABLE_X_130_F5AA8053: TokenInfo = TokenInfo { + name: "Immutable X", + symbol: "IMX", + decimals: 18, + contract: address!("0xc4Fc8cF76883094404DDb875d2AF15D1F5AA8053"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/17233/thumb/imx.png?1636691817"), +}; + +pub static INDEX_COOPERATIVE_130_121E39B7: TokenInfo = TokenInfo { + name: "Index Cooperative", + symbol: "INDEX", + decimals: 18, + contract: address!("0xa5Afe7646f07d2C41AA82Bb6AE09e99E121e39B7"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12729/thumb/index.png?1634894321"), +}; + +pub static INJECTIVE_130_9A89F9F8: TokenInfo = TokenInfo { + name: "Injective", + symbol: "INJ", + decimals: 18, + contract: address!("0x9361cA28625E12C7f088523B274A25059A89f9F8"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237"), +}; + +pub static INVERSE_FINANCE_130_9F7B54FB: TokenInfo = TokenInfo { + name: "Inverse Finance", + symbol: "INV", + decimals: 18, + contract: address!("0xD326ACaB8799fb44C3A5B7f7eFbAaB5f9F7b54fb"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14205/thumb/inverse_finance.jpg?1614921871"), +}; + +pub static IOTEX_130_E2B6843F: TokenInfo = TokenInfo { + name: "IoTeX", + symbol: "IOTX", + decimals: 18, + contract: address!("0xD749094Bc62615f0c8645467e241b71Ae2B6843F"), + chain: 130, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/2777.png"), +}; + +pub static GEOJAM_130_1D5C61A8: TokenInfo = TokenInfo { + name: "Geojam", + symbol: "JAM", + decimals: 18, + contract: address!("0x428c2B7Fa7a7821891fb529BAE4d80a71d5c61A8"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/24648/thumb/ey40AzBN_400x400.jpg?1648507272"), +}; + +pub static JASMYCOIN_130_22720708: TokenInfo = TokenInfo { + name: "JasmyCoin", + symbol: "JASMY", + decimals: 18, + contract: address!("0x8EF0686F380dD07f3e2121831839371922720708"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13876/thumb/JASMY200x200.jpg?1612473259"), +}; + +pub static JUPITER_130_E5CAB8B2: TokenInfo = TokenInfo { + name: "Jupiter", + symbol: "JUP", + decimals: 18, + contract: address!("0x781CC305fCBFe7cde376C9Ef5469d5a7E5CaB8b2"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/10351/thumb/logo512.png?1632480932"), +}; + +pub static JUPITER_130_2381AFAD: TokenInfo = TokenInfo { + name: "Jupiter", + symbol: "JUP", + decimals: 6, + contract: address!("0xbe51A5e8FA434F09663e8fB4CCe79d0B2381Afad"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/34188/standard/jup.png?1704266489"), +}; + +pub static KEEP_NETWORK_130_EA6AFE80: TokenInfo = TokenInfo { + name: "Keep Network", + symbol: "KEEP", + decimals: 18, + contract: address!("0x05DBd720fc26F732c8d42Ea89BD7F442EA6AFE80"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/3373/thumb/IuNzUb5b_400x400.jpg?1589526336"), +}; + +pub static SELFKEY_130_3F1BBFDC: TokenInfo = TokenInfo { + name: "SelfKey", + symbol: "KEY", + decimals: 18, + contract: address!("0x68Cea24F675e4F25584607F6c9feFb353f1bBfDc"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2034/thumb/selfkey.png?1548608934"), +}; + +pub static KYBER_NETWORK_CRYSTAL_130_B7CD2284: TokenInfo = TokenInfo { + name: "Kyber Network Crystal", + symbol: "KNC", + decimals: 18, + contract: address!("0xB0E4Ad2dFe3754e4a2443A7a828Eda5bB7Cd2284"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png"), +}; + +pub static KEEP3RV1_130_5FAD6A74: TokenInfo = TokenInfo { + name: "Keep3rV1", + symbol: "KP3R", + decimals: 18, + contract: address!("0x9C41547e404942C173E28bB2B6abE4cf5fad6A74"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12966/thumb/kp3r_logo.jpg?1607057458"), +}; + +pub static KRYLL_130_4F002943: TokenInfo = TokenInfo { + name: "KRYLL", + symbol: "KRL", + decimals: 18, + contract: address!("0x14CFFAD448AeB0876c56B7aa28999C9a4f002943"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979"), +}; + +pub static KUJIRA_130_30258681: TokenInfo = TokenInfo { + name: "Kujira", + symbol: "KUJI", + decimals: 6, + contract: address!("0x2206cdcC9B94fF7dB7A9eAbeC77b5cE430258681"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png"), +}; + +pub static LAYER3_130_1B7B482C: TokenInfo = TokenInfo { + name: "Layer3", + symbol: "L3", + decimals: 18, + contract: address!("0x1201209f55634bdDb67034efE4e8aA4D1B7B482C"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/37768/large/Square.png"), +}; + +pub static LCX_130_46687782: TokenInfo = TokenInfo { + name: "LCX", + symbol: "LCX", + decimals: 18, + contract: address!("0xb34b3DE63D22ffC90419c1a439de6C7d46687782"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/9985/thumb/zRPSu_0o_400x400.jpg?1574327008"), +}; + +pub static LIDO_DAO_130_814E8829: TokenInfo = TokenInfo { + name: "Lido DAO", + symbol: "LDO", + decimals: 18, + contract: address!("0x68A6dbc7214a0F2b0d875963663F1613814E8829"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644"), +}; + +pub static CHAINLINK_TOKEN_130_9BBEEFB7: TokenInfo = TokenInfo { + name: "ChainLink Token", + symbol: "LINK", + decimals: 18, + contract: address!("0x5a53B6D19D8EDCb7923F0D840EeBB3f09BBeEfB7"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), +}; + +pub static LITENTRY_130_91BE0FDF: TokenInfo = TokenInfo { + name: "Litentry", + symbol: "LIT", + decimals: 18, + contract: address!("0x68648F52B85407806bC1d349B745D13C91be0fDf"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13825/large/logo_200x200.png"), +}; + +pub static LEAGUE_OF_KINGDOMS_130_AAC89733: TokenInfo = TokenInfo { + name: "League of Kingdoms", + symbol: "LOKA", + decimals: 18, + contract: address!("0x1D1BFCFC6ae6FE045f151C7e589fB241AAC89733"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/22572/thumb/loka_64pix.png?1642643271"), +}; + +pub static LOOM_NETWORK_130_009F523C: TokenInfo = TokenInfo { + name: "Loom Network", + symbol: "LOOM", + decimals: 18, + contract: address!("0xc68992e0514968BfbA3Dad201fef91f6009f523c"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0/logo.png"), +}; + +pub static LIVEPEER_130_F35B73E3: TokenInfo = TokenInfo { + name: "Livepeer", + symbol: "LPT", + decimals: 18, + contract: address!("0x11c6B34caDC550B65A9666497d7FCb39f35B73E3"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/7137/thumb/logo-circle-green.png?1619593365"), +}; + +pub static LIQUITY_130_53C71A60: TokenInfo = TokenInfo { + name: "Liquity", + symbol: "LQTY", + decimals: 18, + contract: address!("0x0176B38b7767451b1B682236eCe2fae853C71a60"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180"), +}; + +pub static LOOPRINGCOIN_V2_130_A8AB158A: TokenInfo = TokenInfo { + name: "LoopringCoin V2", + symbol: "LRC", + decimals: 18, + contract: address!("0xA2af802b95D7e20167e5aeaC7Fe8fDf4a8aB158A"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png"), +}; + +pub static BLOCKLORDS_130_0C7BEE3F: TokenInfo = TokenInfo { + name: "BLOCKLORDS", + symbol: "LRDS", + decimals: 18, + contract: address!("0xD7eb7348Ba44c5A2f9f1D1d3534623230c7bee3F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/34775/standard/LRDS_PNG.png"), +}; + +pub static LIQUITY_USD_130_D72577FB: TokenInfo = TokenInfo { + name: "Liquity USD", + symbol: "LUSD", + decimals: 18, + contract: address!("0xf81B7485B4cB59645F74528D702c7f8CD72577FB"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327"), +}; + +pub static DECENTRALAND_130_00FE358B: TokenInfo = TokenInfo { + name: "Decentraland", + symbol: "MANA", + decimals: 18, + contract: address!("0x276361c863903751771e9DabA6dDfaAf00FE358b"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745"), +}; + +pub static MASK_NETWORK_130_1B9512C4: TokenInfo = TokenInfo { + name: "Mask Network", + symbol: "MASK", + decimals: 18, + contract: address!("0xC42B642F5010a2A3bD3CA2396Fe6f2e21B9512C4"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316"), +}; + +pub static MATH_130_99ED2C97: TokenInfo = TokenInfo { + name: "MATH", + symbol: "MATH", + decimals: 18, + contract: address!("0xB999b66186d7a48BF0Eb5d22f4E7053A99eD2C97"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590"), +}; + +pub static POLYGON_130_6507176B: TokenInfo = TokenInfo { + name: "Polygon", + symbol: "MATIC", + decimals: 18, + contract: address!("0xF6AC97B05B3bC92f829c7584b25839906507176b"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), +}; + +pub static MERIT_CIRCLE_130_2D657399: TokenInfo = TokenInfo { + name: "Merit Circle", + symbol: "MC", + decimals: 18, + contract: address!("0x460ec1C67e1614Bf1feAb84b98795BAE2d657399"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/19304/thumb/Db4XqML.png?1634972154"), +}; + +pub static MOSS_CARBON_CREDIT_130_7E6ACC40: TokenInfo = TokenInfo { + name: "Moss Carbon Credit", + symbol: "MCO2", + decimals: 18, + contract: address!("0x68619Bc0C709FB63555Fe988ed14e78f7E6ACc40"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14414/thumb/ENtxnThA_400x400.jpg?1615948522"), +}; + +pub static MEASURABLE_DATA_TOKEN_130_31BFEFF4: TokenInfo = TokenInfo { + name: "Measurable Data Token", + symbol: "MDT", + decimals: 18, + contract: address!("0xB29FddC20D5e4bacE9F54c1d9237953331BFeFF4"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2441/thumb/mdt_logo.png?1569813574"), +}; + +pub static MEMECOIN_130_8E3E7D06: TokenInfo = TokenInfo { + name: "Memecoin", + symbol: "MEME", + decimals: 18, + contract: address!("0x397E34AFF8bFc8Ec14aa78F378074F6d8E3E7d06"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/32528/large/memecoin_(2).png"), +}; + +pub static METIS_130_B3A8F102: TokenInfo = TokenInfo { + name: "Metis", + symbol: "METIS", + decimals: 18, + contract: address!("0xBfBa2A8745e5C85544DB7C8824C6962aB3A8f102"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312"), +}; + +pub static MAGIC_INTERNET_MONEY_130_3E3602AB: TokenInfo = TokenInfo { + name: "Magic Internet Money", + symbol: "MIM", + decimals: 18, + contract: address!("0x397C1f55FefF63C8947624b0d457a2CA3e3602ab"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612"), +}; + +pub static MIRROR_PROTOCOL_130_4A72D717: TokenInfo = TokenInfo { + name: "Mirror Protocol", + symbol: "MIR", + decimals: 18, + contract: address!("0x5FE989EaB3021d7e742099d05a7937bA4A72D717"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13295/thumb/mirror_logo_transparent.png?1611554658"), +}; + +pub static MELON_130_4DC3C117: TokenInfo = TokenInfo { + name: "Melon", + symbol: "MLN", + decimals: 18, + contract: address!("0xf7A581f6e26EEa790225d76Af8821EA34Dc3c117"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295"), +}; + +pub static MOG_COIN_130_78921EBD: TokenInfo = TokenInfo { + name: "Mog Coin", + symbol: "MOG", + decimals: 18, + contract: address!("0x58d68e179864605fEA06EAADF1185c6e78921Ebd"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/31059/large/MOG_LOGO_200x200.png"), +}; + +pub static MONAVALE_130_1C7A1087: TokenInfo = TokenInfo { + name: "Monavale", + symbol: "MONA", + decimals: 18, + contract: address!("0xAe6065FB0244A68036C82deC9a8dE5501c7A1087"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13298/thumb/monavale_logo.jpg?1607232721"), +}; + +pub static MOVEMENT_130_0FF19949: TokenInfo = TokenInfo { + name: "Movement", + symbol: "MOVE", + decimals: 8, + contract: address!("0xaa2109f14Bb155766cBA9E7fa8B8D4bF0ff19949"), + chain: 130, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/32452.png"), +}; + +pub static MAPLE_130_D752A219: TokenInfo = TokenInfo { + name: "Maple", + symbol: "MPL", + decimals: 18, + contract: address!("0x587e0E022b074015F4e81eCa489c0C41d752A219"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14097/thumb/photo_2021-05-03_14.20.41.jpeg?1620022863"), +}; + +pub static METAL_130_6CFAD9EA: TokenInfo = TokenInfo { + name: "Metal", + symbol: "MTL", + decimals: 8, + contract: address!("0x71d69d07914d087f1C3536F7A5006a256CfAd9Ea"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/763/thumb/Metal.png?1592195010"), +}; + +pub static MULTICHAIN_130_D82B4701: TokenInfo = TokenInfo { + name: "Multichain", + symbol: "MULTI", + decimals: 18, + contract: address!("0x1C3a8fB65Ab82D73e26B6403bf505B99d82b4701"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238"), +}; + +pub static MSTABLE_USD_130_B40A8DD1: TokenInfo = TokenInfo { + name: "mStable USD", + symbol: "MUSD", + decimals: 18, + contract: address!("0x10F109379E231d5c294ee6A5f9Abb2F8b40A8Dd1"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11576/thumb/mStable_USD.png?1595591803"), +}; + +pub static MUSE_DAO_130_81D5F345: TokenInfo = TokenInfo { + name: "Muse DAO", + symbol: "MUSE", + decimals: 18, + contract: address!("0xe3d92FB06a4EEbaC5879D3C1073e0eAB81D5f345"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13230/thumb/muse_logo.png?1606460453"), +}; + +pub static GENSOKISHI_METAVERSE_130_FF182974: TokenInfo = TokenInfo { + name: "GensoKishi Metaverse", + symbol: "MV", + decimals: 18, + contract: address!("0xD6ec6A24d5365A1811B05099f8D353c0Ff182974"), + chain: 130, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/17704.png"), +}; + +pub static MXC_130_02727794: TokenInfo = TokenInfo { + name: "MXC", + symbol: "MXC", + decimals: 18, + contract: address!("0xCF7c45Ccc1327ac1E9Cb9E098898c59402727794"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/4604/thumb/mxc.png?1655534336"), +}; + +pub static POLYSWARM_130_795032DF: TokenInfo = TokenInfo { + name: "PolySwarm", + symbol: "NCT", + decimals: 18, + contract: address!("0x328Ed7736871F863C8216Ca6CbB6f29B795032Df"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2843/thumb/ImcYCVfX_400x400.jpg?1628519767"), +}; + +pub static NEIRO_130_87696276: TokenInfo = TokenInfo { + name: "Neiro", + symbol: "Neiro", + decimals: 9, + contract: address!("0xc1C06527E810C4A198D8C5d35e1dDBc987696276"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/39488/large/neiro.jpg?1731449567"), +}; + +pub static NKN_130_336BAF62: TokenInfo = TokenInfo { + name: "NKN", + symbol: "NKN", + decimals: 18, + contract: address!("0x75b93cED9627Cd172912304Fb79Cd3e7336BaF62"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/3375/thumb/nkn.png?1548329212"), +}; + +pub static NUMERAIRE_130_DBDA20FC: TokenInfo = TokenInfo { + name: "Numeraire", + symbol: "NMR", + decimals: 18, + contract: address!("0x931e587542b8603EA3C6420dD8d3b22eDbdA20FC"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png"), +}; + +pub static NUCYPHER_130_AACEA6B9: TokenInfo = TokenInfo { + name: "NuCypher", + symbol: "NU", + decimals: 18, + contract: address!("0x2AEB5256de25ECed47797b82d2F5C404AACEA6b9"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/3318/thumb/photo1198982838879365035.jpg?1547037916"), +}; + +pub static OCEAN_PROTOCOL_130_3CD79208: TokenInfo = TokenInfo { + name: "Ocean Protocol", + symbol: "OCEAN", + decimals: 18, + contract: address!("0x652293F4e9b0ef61C52a78D6615D9f5f3cD79208"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686"), +}; + +pub static ORIGIN_PROTOCOL_130_EE18C880: TokenInfo = TokenInfo { + name: "Origin Protocol", + symbol: "OGN", + decimals: 18, + contract: address!("0xa60CE8f7ec6A091535b4708569B39DF5eE18c880"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878"), +}; + +pub static OMG_NETWORK_130_8EE37383: TokenInfo = TokenInfo { + name: "OMG Network", + symbol: "OMG", + decimals: 18, + contract: address!("0x5949b9200dF1e77878dB3D061e43cF878Ee37383"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/776/thumb/OMG_Network.jpg?1591167168"), +}; + +pub static OMNI_NETWORK_130_959EB0E3: TokenInfo = TokenInfo { + name: "Omni Network", + symbol: "OMNI", + decimals: 18, + contract: address!("0xf5614D20c13D5BF2F9e640f00B7B2B76959Eb0E3"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/36465/standard/Symbol-Color.png?1711511095"), +}; + +pub static ONDO_FINANCE_130_85321557: TokenInfo = TokenInfo { + name: "Ondo Finance", + symbol: "ONDO", + decimals: 18, + contract: address!("0xaD0bae21db0b471dFfC6f8F9EEacFe9A85321557"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/26580/standard/ONDO.png?1696525656"), +}; + +pub static ORCA_ALLIANCE_130_1BE3E8C0: TokenInfo = TokenInfo { + name: "ORCA Alliance", + symbol: "ORCA", + decimals: 18, + contract: address!("0xCF2050ebC80B74370C1C2B71bDB635d11be3E8c0"), + chain: 130, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/5183.png"), +}; + +pub static ORION_PROTOCOL_130_B6EAF396: TokenInfo = TokenInfo { + name: "Orion Protocol", + symbol: "ORN", + decimals: 8, + contract: address!("0x3C5319013FD75976F0f13b0bc0852537B6eaF396"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11841/thumb/orion_logo.png?1594943318"), +}; + +pub static ORCHID_130_52B98042: TokenInfo = TokenInfo { + name: "Orchid", + symbol: "OXT", + decimals: 18, + contract: address!("0x9775C2b4f245248dE5596252Ac69311152B98042"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4575f41308EC1483f3d399aa9a2826d74Da13Deb/logo.png"), +}; + +pub static PAYPEREX_130_0D292327: TokenInfo = TokenInfo { + name: "PayperEx", + symbol: "PAX", + decimals: 18, + contract: address!("0x3614c8d98Bf905AbE075BfA289231bbc0D292327"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1601/thumb/pax.png?1547035800"), +}; + +pub static PLAYDAPP_130_1E75D6AC: TokenInfo = TokenInfo { + name: "PlayDapp", + symbol: "PDA", + decimals: 18, + contract: address!("0xeC37cdfC9a692b3cCd5c85696D14aaA31E75d6aC"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14316/standard/PDA-symbol.png?1710234068"), +}; + +pub static PEPE_130_9074952B: TokenInfo = TokenInfo { + name: "Pepe", + symbol: "PEPE", + decimals: 18, + contract: address!("0xD9b5DA95B3D97c3E9872102fDb47d4c09074952B"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725"), +}; + +pub static PERPETUAL_PROTOCOL_130_CCFEC7D5: TokenInfo = TokenInfo { + name: "Perpetual Protocol", + symbol: "PERP", + decimals: 18, + contract: address!("0x5944D2728d5fea7D1F4AA4958E3aEbb3CCFEc7D5"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), +}; + +pub static PIRATE_NATION_130_18D064C6: TokenInfo = TokenInfo { + name: "Pirate Nation", + symbol: "PIRATE", + decimals: 18, + contract: address!("0xd0F77df9a8f0e855F910361f5f59958118d064c6"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/38524/standard/_Pirate_Transparent_200x200.png"), +}; + +pub static PLUTON_130_ABB6F6C7: TokenInfo = TokenInfo { + name: "Pluton", + symbol: "PLU", + decimals: 18, + contract: address!("0x5441619a9754Aee0665c939743cf7611abB6F6C7"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1241/thumb/pluton.png?1548331624"), +}; + +pub static POLYGON_ECOSYSTEM_TOKEN_130_E5682E95: TokenInfo = TokenInfo { + name: "Polygon Ecosystem Token", + symbol: "POL", + decimals: 18, + contract: address!("0xF6A49aEdbD7861DeD0DA2BE1f21C6954E5682E95"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/32440/large/polygon.png?1698233684"), +}; + +pub static POLKASTARTER_130_DC306503: TokenInfo = TokenInfo { + name: "Polkastarter", + symbol: "POLS", + decimals: 18, + contract: address!("0x82a98121eaf30b0E135b08d4208c837Cdc306503"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702"), +}; + +pub static POLYMATH_130_D538D863: TokenInfo = TokenInfo { + name: "Polymath", + symbol: "POLY", + decimals: 18, + contract: address!("0x2f5cfdC89fb96f2cf6c0FB1Ca6e3501Dd538D863"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034"), +}; + +pub static MARLIN_130_4D4782D5: TokenInfo = TokenInfo { + name: "Marlin", + symbol: "POND", + decimals: 18, + contract: address!("0xA2a36541c5a54bd2815985418105091B4D4782d5"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/8903/thumb/POND_200x200.png?1622515451"), +}; + +pub static PORTAL_130_0F2A5642: TokenInfo = TokenInfo { + name: "Portal", + symbol: "PORTAL", + decimals: 18, + contract: address!("0x562E588471cA0e710b2b1217867FFb2E0F2a5642"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/35436/standard/portal.jpeg"), +}; + +pub static POWER_LEDGER_130_DFFA6BFF: TokenInfo = TokenInfo { + name: "Power Ledger", + symbol: "POWR", + decimals: 6, + contract: address!("0xf265af514762286A63d015FeE382B90edfFa6bff"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1104/thumb/power-ledger.png?1547035082"), +}; + +pub static PRIME_130_CBF9FEE0: TokenInfo = TokenInfo { + name: "Prime", + symbol: "PRIME", + decimals: 18, + contract: address!("0xD17D5f0DA4200bBfd3D6626AC6aEA2eccbf9fEE0"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222"), +}; + +pub static PROPY_130_1F41A7C9: TokenInfo = TokenInfo { + name: "Propy", + symbol: "PRO", + decimals: 8, + contract: address!("0xC6Fbf362a12804FEca22000f37DB5EFC1F41A7c9"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/869/thumb/propy.png?1548332100"), +}; + +pub static PARSIQ_130_0ABF3DEF: TokenInfo = TokenInfo { + name: "PARSIQ", + symbol: "PRQ", + decimals: 18, + contract: address!("0xc7B7dcF3c6CAcAAc13F92c9173f9A0060ABf3def"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280"), +}; + +pub static PSTAKE_FINANCE_130_E7D7CAA2: TokenInfo = TokenInfo { + name: "pSTAKE Finance", + symbol: "PSTAKE", + decimals: 18, + contract: address!("0x13FE2c4504f3AA18708561250e2F20E4E7D7CAa2"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/23931/thumb/PSTAKE_Dark.png?1645709930"), +}; + +pub static PUFFER_FINANCE_130_38B560D2: TokenInfo = TokenInfo { + name: "Puffer Finance", + symbol: "PUFFER", + decimals: 18, + contract: address!("0xAdf70dc4AaeFbC6D1E7A6cF0B02b0F2138b560d2"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/50630/large/puffer.jpg?1728545297"), +}; + +pub static PAYPAL_USD_130_8E6207C5: TokenInfo = TokenInfo { + name: "PayPal USD", + symbol: "PYUSD", + decimals: 6, + contract: address!("0x0D2f98904D88909072eA6e61105CBBf78e6207c5"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/31212/large/PYUSD_Logo_%282%29.png?1691458314"), +}; + +pub static QUANT_130_98C360D4: TokenInfo = TokenInfo { + name: "Quant", + symbol: "QNT", + decimals: 18, + contract: address!("0x3a8723f2929F370c61EaC583d6652e5C98C360d4"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/3370/thumb/5ZOu7brX_400x400.jpg?1612437252"), +}; + +pub static QREDO_130_8C1068B8: TokenInfo = TokenInfo { + name: "Qredo", + symbol: "QRDO", + decimals: 8, + contract: address!("0x006254C4664C678e64c3265da28304cc8c1068b8"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/17541/thumb/qrdo.png?1630637735"), +}; + +pub static QUANTSTAMP_130_6BB5EABB: TokenInfo = TokenInfo { + name: "Quantstamp", + symbol: "QSP", + decimals: 18, + contract: address!("0xb019a038eaDCB2F96321D236F6633C8d6Bb5eAbB"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1219/thumb/0_E0kZjb4dG4hUnoDD_.png?1604815917"), +}; + +pub static QUICKSWAP_130_F8E6CAC2: TokenInfo = TokenInfo { + name: "Quickswap", + symbol: "QUICK", + decimals: 18, + contract: address!("0xD815958F92E6aBe63437BCe166E97027f8E6caC2"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13970/thumb/1_pOU6pBMEmiL-ZJVb0CYRjQ.png?1613386659"), +}; + +pub static RADICLE_130_F08A1A45: TokenInfo = TokenInfo { + name: "Radicle", + symbol: "RAD", + decimals: 18, + contract: address!("0x3F9A30c86DC7F0c657eA17d52Efe09Eff08a1a45"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14013/thumb/radicle.png?1614402918"), +}; + +pub static RAI_REFLEX_INDEX_130_89F34A66: TokenInfo = TokenInfo { + name: "Rai Reflex Index", + symbol: "RAI", + decimals: 18, + contract: address!("0x6164A78F7B2aC49cf9b76c49e5B6909e89f34a66"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334"), +}; + +pub static SUPERRARE_130_E025BB6F: TokenInfo = TokenInfo { + name: "SuperRare", + symbol: "RARE", + decimals: 18, + contract: address!("0xe8a0078aA52ac7e93aE43818DdD64591E025BB6F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/17753/thumb/RARE.jpg?1629220534"), +}; + +pub static RARIBLE_130_03C8561C: TokenInfo = TokenInfo { + name: "Rarible", + symbol: "RARI", + decimals: 18, + contract: address!("0x16F01392Ed7fC6F3C345CF544cf1172103C8561C"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11845/thumb/Rari.png?1594946953"), +}; + +pub static RUBIC_130_66B403E3: TokenInfo = TokenInfo { + name: "Rubic", + symbol: "RBC", + decimals: 18, + contract: address!("0x29EA5682024c8C62Cd8BDf691C4f0c5D66B403E3"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12629/thumb/200x200.png?1607952509"), +}; + +pub static RIBBON_FINANCE_130_C841CD3E: TokenInfo = TokenInfo { + name: "Ribbon Finance", + symbol: "RBN", + decimals: 18, + contract: address!("0x75B2dBb2a7C70073133E42F64366a986c841cd3e"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/15823/thumb/RBN_64x64.png?1633529723"), +}; + +pub static REPUBLIC_TOKEN_130_8261617E: TokenInfo = TokenInfo { + name: "Republic Token", + symbol: "REN", + decimals: 18, + contract: address!("0x560603E0bFC941063D1375Ec4E3f9FE38261617E"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png"), +}; + +pub static REPUTATION_AUGUR_V1_130_B2816FC4: TokenInfo = TokenInfo { + name: "Reputation Augur v1", + symbol: "REP", + decimals: 18, + contract: address!("0x097ca3FC389697080C84148C455Ca839b2816Fc4"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1985365e9f78359a9B6AD760e32412f4a445E862/logo.png"), +}; + +pub static REPUTATION_AUGUR_V2_130_1E72A8C4: TokenInfo = TokenInfo { + name: "Reputation Augur v2", + symbol: "REPv2", + decimals: 18, + contract: address!("0xE86B1E5613a5761D005a2D00D8a1B4ad1e72A8c4"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x221657776846890989a759BA2973e427DfF5C9bB/logo.png"), +}; + +pub static REQUEST_130_9D8663CD: TokenInfo = TokenInfo { + name: "Request", + symbol: "REQ", + decimals: 18, + contract: address!("0x9FcC3133779F2039c29908c915b6EFaE9d8663Cd"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1031/thumb/Request_icon_green.png?1643250951"), +}; + +pub static REVV_130_0F9CA657: TokenInfo = TokenInfo { + name: "REVV", + symbol: "REVV", + decimals: 18, + contract: address!("0xc14a68015fA6396eF97B57839da544910f9Ca657"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12373/thumb/REVV_TOKEN_Refined_2021_%281%29.png?1627652390"), +}; + +pub static RENZO_130_AAD6C9AB: TokenInfo = TokenInfo { + name: "Renzo", + symbol: "REZ", + decimals: 18, + contract: address!("0x2178f07c1d585C39272CAf69A72beF08aAD6c9AB"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/37327/standard/renzo_200x200.png?1714025012"), +}; + +pub static RARI_GOVERNANCE_TOKEN_130_946CF284: TokenInfo = TokenInfo { + name: "Rari Governance Token", + symbol: "RGT", + decimals: 18, + contract: address!("0x8c9606001CF1787CEb80E03DEF3F9BaF946CF284"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014"), +}; + +pub static IEXEC_RLC_130_B3347ACB: TokenInfo = TokenInfo { + name: "iExec RLC", + symbol: "RLC", + decimals: 9, + contract: address!("0x538fB2719135740b8877607217Dc391FB3347ACb"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1604543202"), +}; + +pub static RALLY_130_3F88C889: TokenInfo = TokenInfo { + name: "Rally", + symbol: "RLY", + decimals: 18, + contract: address!("0x7Ad899b7C793743fDE692d982F190f443F88c889"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12843/thumb/image.png?1611212077"), +}; + +pub static RENDER_TOKEN_130_8D649868: TokenInfo = TokenInfo { + name: "Render Token", + symbol: "RNDR", + decimals: 18, + contract: address!("0x965C6DeBFa700F53a38d42DbaeD922c58d649868"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11636/thumb/rndr.png?1638840934"), +}; + +pub static ROOK_130_9DE41D99: TokenInfo = TokenInfo { + name: "Rook", + symbol: "ROOK", + decimals: 18, + contract: address!("0x682B2f07e61022A80Ac2753448f7D95E9de41D99"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13005/thumb/keeper_dao_logo.jpg?1604316506"), +}; + +pub static RESERVE_RIGHTS_130_B1889066: TokenInfo = TokenInfo { + name: "Reserve Rights", + symbol: "RSR", + decimals: 18, + contract: address!("0x993A565A1E6219951323cA3c34Cee0A3b1889066"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856"), +}; + +pub static SAFE_130_10EFD888: TokenInfo = TokenInfo { + name: "Safe", + symbol: "SAFE", + decimals: 18, + contract: address!("0x47B72717E48Da346C3F1ED1311c8DCDe10EfD888"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/27032/standard/Artboard_1_copy_8circle-1.png?1696526084"), +}; + +pub static THE_SANDBOX_130_2CAF25CA: TokenInfo = TokenInfo { + name: "The Sandbox", + symbol: "SAND", + decimals: 18, + contract: address!("0x6A654A2ec95fB988Ea37746dBCca10772CAf25CA"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1597397942"), +}; + +pub static STADER_130_B32D72E5: TokenInfo = TokenInfo { + name: "Stader", + symbol: "SD", + decimals: 18, + contract: address!("0x7ccc67C7b232aa6417d9422e90D91ec4b32d72E5"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png"), +}; + +pub static SHIBA_INU_130_5664158E: TokenInfo = TokenInfo { + name: "Shiba Inu", + symbol: "SHIB", + decimals: 18, + contract: address!("0xaa571d01057cdF477D73433D36D86fCb5664158e"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11939/thumb/shiba.png?1622619446"), +}; + +pub static SHPING_130_66024F2F: TokenInfo = TokenInfo { + name: "Shping", + symbol: "SHPING", + decimals: 18, + contract: address!("0x45Bda7bA10DaC525a86DBEaB3135701A66024F2F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2588/thumb/r_yabKKi_400x400.jpg?1639470164"), +}; + +pub static SKALE_130_8AD20C01: TokenInfo = TokenInfo { + name: "SKALE", + symbol: "SKL", + decimals: 18, + contract: address!("0x486Bbb6f250343AdB4782F50Dd09766f8aD20c01"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13245/thumb/SKALE_token_300x300.png?1606789574"), +}; + +pub static SKY_GOVERNANCE_TOKEN_130_D07074E4: TokenInfo = TokenInfo { + name: "SKY Governance Token", + symbol: "SKY", + decimals: 18, + contract: address!("0x5A6058002d0d336e5E8860652e7054a6d07074E4"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/39925/large/sky.jpg?1724827980"), +}; + +pub static SMOOTH_LOVE_POTION_130_96CB03B3: TokenInfo = TokenInfo { + name: "Smooth Love Potion", + symbol: "SLP", + decimals: 0, + contract: address!("0xbD2DD310FECBFb1111fC3262F3a97bA696cb03B3"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/10366/thumb/SLP.png?1578640057"), +}; + +pub static STATUS_130_265ABF5F: TokenInfo = TokenInfo { + name: "Status", + symbol: "SNT", + decimals: 18, + contract: address!("0x914f7CE2B080B2186159C2213B1e193E265aBF5F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778"), +}; + +pub static SYNTHETIX_NETWORK_TOKEN_130_59E6BC88: TokenInfo = TokenInfo { + name: "Synthetix Network Token", + symbol: "SNX", + decimals: 18, + contract: address!("0x022D952aBCc6C8271F26e59e37A65dC359E6bc88"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), +}; + +pub static UNISOCKS_130_DC4627AB: TokenInfo = TokenInfo { + name: "Unisocks", + symbol: "SOCKS", + decimals: 18, + contract: address!("0x5e03C123D829505F4DEa87cf679F77c9dC4627ab"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/10717/thumb/qFrcoiM.png?1582525244"), +}; + +pub static SOL_WORMHOLE_130_C3D054FE: TokenInfo = TokenInfo { + name: "SOL Wormhole ", + symbol: "SOL", + decimals: 9, + contract: address!("0x4Ff3E944D5Cb54f6f4A1dd035782BE59c3d054FE"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), +}; + +pub static SOLANA: TokenInfo = TokenInfo { + name: "Solana", + symbol: "SOL", + decimals: 9, + contract: address!("0xbdE8A5331E8Ac4831cf8ea9e42e229219EafaB97"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54680/large/base.png?1749023388"), +}; + +pub static SPELL_TOKEN_130_C17FEF7F: TokenInfo = TokenInfo { + name: "Spell Token", + symbol: "SPELL", + decimals: 18, + contract: address!("0x739316C7bc4A39Eb39dcFa1b181b64abc17fEF7F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862"), +}; + +pub static SPX6900_130_036DD629: TokenInfo = TokenInfo { + name: "SPX6900", + symbol: "SPX", + decimals: 8, + contract: address!("0x51A7b9a11f10D04C16306D90dc4EC22b036DD629"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083"), +}; + +pub static STARGATE_FINANCE_130_19373135: TokenInfo = TokenInfo { + name: "Stargate Finance", + symbol: "STG", + decimals: 18, + contract: address!("0x77c8A8E1dd3b5270d3Ab589543e9A83319373135"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518"), +}; + +pub static STORJ_TOKEN_130_C9951835: TokenInfo = TokenInfo { + name: "Storj Token", + symbol: "STORJ", + decimals: 8, + contract: address!("0xf13B5B21555092882e69b22282DAf891c9951835"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png"), +}; + +pub static STARKNET_130_2332C72E: TokenInfo = TokenInfo { + name: "Starknet", + symbol: "STRK", + decimals: 18, + contract: address!("0x09f705405677970E509d606348D4635D2332c72e"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/26433/standard/starknet.png?1696525507"), +}; + +pub static STOX_130_CACCEA22: TokenInfo = TokenInfo { + name: "Stox", + symbol: "STX", + decimals: 18, + contract: address!("0xEf86E70E534E02AADEAE95b843973d4AcacCeA22"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1230/thumb/stox-token.png?1547035256"), +}; + +pub static SUKU_130_82176525: TokenInfo = TokenInfo { + name: "SUKU", + symbol: "SUKU", + decimals: 18, + contract: address!("0xc05B416738DDEBd14D5A9B790a6e1ce782176525"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11969/thumb/UmfW5S6f_400x400.jpg?1596602238"), +}; + +pub static SUPERFARM_130_2BD86D3D: TokenInfo = TokenInfo { + name: "SuperFarm", + symbol: "SUPER", + decimals: 18, + contract: address!("0x0c288302629Fc22504D59Ddf8fbf8AA92bD86D3D"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899"), +}; + +pub static SYNTH_SUSD_130_9B3A6A0F: TokenInfo = TokenInfo { + name: "Synth sUSD", + symbol: "sUSD", + decimals: 18, + contract: address!("0x7251d204c2e867b31096D5c7091298239B3A6a0F"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765"), +}; + +pub static SUSHI_130_BDFB3CE5: TokenInfo = TokenInfo { + name: "Sushi", + symbol: "SUSHI", + decimals: 18, + contract: address!("0x2982Be2D0c6ae4A7D5BC1c8fe7B630E3BDfb3ce5"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), +}; + +pub static SWELL_130_028A5870: TokenInfo = TokenInfo { + name: "Swell", + symbol: "SWELL", + decimals: 18, + contract: address!("0xa8015cbc9f7c58788BA00854c330F027028A5870"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/28777/large/swell1.png?1727899715"), +}; + +pub static SWFTCOIN_130_45AF1616: TokenInfo = TokenInfo { + name: "SWFTCOIN", + symbol: "SWFTC", + decimals: 8, + contract: address!("0x0610cDF9856b8825213672981056CD4945Af1616"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2346/thumb/SWFTCoin.jpg?1618392022"), +}; + +pub static SWIPE_130_9785C2E1: TokenInfo = TokenInfo { + name: "Swipe", + symbol: "SXP", + decimals: 18, + contract: address!("0xDcA295E850666753c6332D6B0E0445B09785c2E1"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/9368/thumb/swipe.png?1566792311"), +}; + +pub static SYLO_130_CFFCF85E: TokenInfo = TokenInfo { + name: "Sylo", + symbol: "SYLO", + decimals: 18, + contract: address!("0x1BAAc1979527A38F367c6f89bE081aBfcFFCF85E"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/6430/thumb/SYLO.svg?1589527756"), +}; + +pub static SYNAPSE_130_81888A48: TokenInfo = TokenInfo { + name: "Synapse", + symbol: "SYN", + decimals: 18, + contract: address!("0xCeb1F5671C47cee096C3B40353863b6781888A48"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049"), +}; + +pub static SYRUP_TOKEN_130_8CD6FA96: TokenInfo = TokenInfo { + name: "Syrup Token", + symbol: "SYRUP", + decimals: 18, + contract: address!("0x8f7F997ba304f426E3138999919c23f68cD6FA96"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/51232/standard/IMG_7420.png?1730831572"), +}; + +pub static THRESHOLD_NETWORK_130_48F2AD54: TokenInfo = TokenInfo { + name: "Threshold Network", + symbol: "T", + decimals: 18, + contract: address!("0x8F43Ab8648F1a3BAEea3782Ba5f562a148f2Ad54"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340"), +}; + +pub static BITTENSOR: TokenInfo = TokenInfo { + name: "Bittensor", + symbol: "TAO", + decimals: 18, + contract: address!("0xFdCa15bd55F350a36E63C47661914d80411d2C22"), + chain: 130, + logo_uri: Some("https://app.uniswap.org/assets/unichain-logo-B-lwXybJ.png"), +}; + +pub static TBTC_130_20BC7814: TokenInfo = TokenInfo { + name: "tBTC", + symbol: "tBTC", + decimals: 18, + contract: address!("0xAd497996Dc33DC8E8e552824CcEe199420BC7814"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png"), +}; + +pub static CHRONOTECH_130_1EDA749C: TokenInfo = TokenInfo { + name: "ChronoTech", + symbol: "TIME", + decimals: 8, + contract: address!("0xD9Cbd701bbEA8e9Aaee7d82aa60748451eDa749c"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/604/thumb/time-32x32.png?1627130666"), +}; + +pub static ALIEN_WORLDS_130_A9A46C68: TokenInfo = TokenInfo { + name: "Alien Worlds", + symbol: "TLM", + decimals: 4, + contract: address!("0xd649b9AD2104418B5b032a5899fBcd54a9a46c68"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14676/thumb/kY-C4o7RThfWrDQsLCAG4q4clZhBDDfJQVhWUEKxXAzyQYMj4Jmq1zmFwpRqxhAJFPOa0AsW_PTSshoPuMnXNwq3rU7Imp15QimXTjlXMx0nC088mt1rIwRs75GnLLugWjSllxgzvQ9YrP4tBgclK4_rb17hjnusGj_c0u2fx0AvVokjSNB-v2poTj0xT9BZRCbzRE3-lF1.jpg?1617700061"), +}; + +pub static TOKEMAK_130_36213E0B: TokenInfo = TokenInfo { + name: "Tokemak", + symbol: "TOKE", + decimals: 18, + contract: address!("0x5eD5DA180bB125f229AB7b825E34D2b936213e0B"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/17495/thumb/tokemak-avatar-200px-black.png?1628131614"), +}; + +pub static TE_FOOD_130_A7BD5AC6: TokenInfo = TokenInfo { + name: "TE FOOD", + symbol: "TONE", + decimals: 18, + contract: address!("0x502865ECDd2a2929Aa9418297bE7d3C4a7BD5Ac6"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/2325/thumb/tec.png?1547036538"), +}; + +pub static ORIGINTRAIL_130_DBAE6F2E: TokenInfo = TokenInfo { + name: "OriginTrail", + symbol: "TRAC", + decimals: 18, + contract: address!("0x1ac70C9e29bC19640E64D938DD8D6A46dbAe6f2e"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/1877/thumb/TRAC.jpg?1635134367"), +}; + +pub static TELLOR_130_6D8EC63B: TokenInfo = TokenInfo { + name: "Tellor", + symbol: "TRB", + decimals: 18, + contract: address!("0x8e902FDeA73e5CF9621D2Bee82cD79196d8ec63b"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686"), +}; + +pub static TRIBE_130_33DACDBD: TokenInfo = TokenInfo { + name: "Tribe", + symbol: "TRIBE", + decimals: 18, + contract: address!("0x437dD6360Bd17FB353c67376371133Cd33dacdBD"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/14575/thumb/tribe.PNG?1617487954"), +}; + +pub static TRUEFI_130_F30CFE0E: TokenInfo = TokenInfo { + name: "TrueFi", + symbol: "TRU", + decimals: 8, + contract: address!("0x55C65102C26b173696e935B1325e5AaeF30cFE0e"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13180/thumb/truefi_glyph_color.png?1617610941"), +}; + +pub static TURBO_130_F2D202A1: TokenInfo = TokenInfo { + name: "Turbo", + symbol: "TURBO", + decimals: 18, + contract: address!("0x1E4339318EcE1d6D9d2Fb129b31C06b9F2d202A1"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/30117/large/TurboMark-QL_200.png?1708079597"), +}; + +pub static THE_VIRTUA_KOLECT_130_13BD9D5D: TokenInfo = TokenInfo { + name: "The Virtua Kolect", + symbol: "TVK", + decimals: 18, + contract: address!("0x756fb781389DCaF9D3BC5468927F06A913bD9D5D"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13330/thumb/virtua_original.png?1656043619"), +}; + +pub static UMA_VOTING_TOKEN_V1_130_72435F8C: TokenInfo = TokenInfo { + name: "UMA Voting Token v1", + symbol: "UMA", + decimals: 18, + contract: address!("0x478923278640a10A60951E379aFFb60772435f8C"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), +}; + +pub static UNIFI_PROTOCOL_DAO_130_0408A30B: TokenInfo = TokenInfo { + name: "Unifi Protocol DAO", + symbol: "UNFI", + decimals: 18, + contract: address!("0xe9225a870b54f8FBA42c8188D211271f0408a30B"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/13152/thumb/logo-2.png?1605748967"), +}; + +pub static UNISWAP_130_7CE9EA21: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0x8f187aA05619a017077f5308904739877ce9eA21"), + chain: 130, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static PAWTOCOL_130_3E264D36: TokenInfo = TokenInfo { + name: "Pawtocol", + symbol: "UPI", + decimals: 18, + contract: address!("0x5EAFF8Fa6f3831Bb86FeEB701E6f98293E264D36"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12186/thumb/pawtocol.jpg?1597962008"), +}; + +pub static USDCOIN_130_0EF57AD6: TokenInfo = TokenInfo { + name: "USDCoin", + symbol: "USDC", + decimals: 6, + contract: address!("0x078D782b760474a361dDA0AF3839290b0EF57AD6"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), +}; + +pub static GLOBAL_DOLLAR_130_A9F86F1E: TokenInfo = TokenInfo { + name: "Global Dollar", + symbol: "USDG", + decimals: 6, + contract: address!("0x2A22868610610199D43fE93A16661473A9f86f1E"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/51281/large/GDN_USDG_Token_200x200.png"), +}; + +pub static PAX_DOLLAR_130_6DE0FEFF: TokenInfo = TokenInfo { + name: "Pax Dollar", + symbol: "USDP", + decimals: 18, + contract: address!("0xF7E6430137eF8087E0D472343f358e986De0FEFF"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/6013/standard/Pax_Dollar.png?1696506427"), +}; + +pub static QUANTOZ_USDQ_130_7B2F3A5F: TokenInfo = TokenInfo { + name: "Quantoz USDQ", + symbol: "USDQ", + decimals: 6, + contract: address!("0xf37748D2Cc6E6d5D05945Ce130C03c147b2F3a5F"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/51852/large/USDQ_1000px_Color.png?1732071232"), +}; + +pub static STABLR_USD_130_004C06A7: TokenInfo = TokenInfo { + name: "StablR USD", + symbol: "USDR", + decimals: 6, + contract: address!("0xaC025d055a6B633992dE1F796b97B97F004c06a7"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/53721/large/stablrusd-logo.png?1737126629"), +}; + +pub static USDS_STABLECOIN_130_3B2F7BB4: TokenInfo = TokenInfo { + name: "USDS Stablecoin", + symbol: "USDS", + decimals: 18, + contract: address!("0x116EE4d63847fb295dD919aE57B768EA3B2f7Bb4"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/39926/large/usds.webp?1726666683"), +}; + +pub static TETHER_USD_130_54C75518: TokenInfo = TokenInfo { + name: "Tether USD", + symbol: "USDT", + decimals: 6, + contract: address!("0x588CE4F028D8e7B53B687865d6A67b3A54C75518"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), +}; + +pub static USUAL_130_98BC5950: TokenInfo = TokenInfo { + name: "USUAL", + symbol: "USUAL", + decimals: 18, + contract: address!("0xc7bA59c95ba747a7c374DC7208a0513798BC5950"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/51091/large/USUAL.jpg?1730035787"), +}; + +pub static VANRY_130_01564A0B: TokenInfo = TokenInfo { + name: "VANRY", + symbol: "VANRY", + decimals: 18, + contract: address!("0x286b5Ecea3749c7c7047104aa3C5749901564A0b"), + chain: 130, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/33466/large/apple-touch-icon.png?1701942541"), +}; + +pub static VOYAGER_TOKEN_130_8FFE537F: TokenInfo = TokenInfo { + name: "Voyager Token", + symbol: "VGX", + decimals: 8, + contract: address!("0x4afd08AC2416450d9c8b84D287dbfFb68FFe537f"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/794/thumb/Voyager-vgx.png?1575693595"), +}; + +pub static WRAPPED_AMPLEFORTH_130_06364A49: TokenInfo = TokenInfo { + name: "Wrapped Ampleforth", + symbol: "WAMPL", + decimals: 18, + contract: address!("0xb86a08ec917EeF9f835aC2B26c3a506c06364A49"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/20825/thumb/photo_2021-11-25_02-05-11.jpg?1637811951"), +}; + +pub static WRAPPED_BTC_130_4EC4AFB8: TokenInfo = TokenInfo { + name: "Wrapped BTC", + symbol: "WBTC", + decimals: 8, + contract: address!("0x927B51f251480a681271180DA4de28D44EC4AfB8"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), +}; + +pub static WRAPPED_CENTRIFUGE_130_D72E82C4: TokenInfo = TokenInfo { + name: "Wrapped Centrifuge", + symbol: "WCFG", + decimals: 18, + contract: address!("0xaE87B8eb5E313AC72B306CbA7c1E3f23D72e82C4"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/17106/thumb/WCFG.jpg?1626266462"), +}; + +pub static WRAPPED_ETHER_130_00000006: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0x4200000000000000000000000000000000000006"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static DOGWIFHAT: TokenInfo = TokenInfo { + name: "dogwifhat", + symbol: "WIF", + decimals: 6, + contract: address!("0x97Fadb3D000b953360FD011e173F12cDDB5d70Fa"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/33566/standard/dogwifhat.jpg?1702499428"), +}; + +pub static WOO_NETWORK_130_EFD89E62: TokenInfo = TokenInfo { + name: "WOO Network", + symbol: "WOO", + decimals: 18, + contract: address!("0xef22b9df2dDf4246A827575C4Aa46BDaeFd89E62"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), +}; + +pub static CHAIN_130_DC06A12F: TokenInfo = TokenInfo { + name: "Chain", + symbol: "XCN", + decimals: 18, + contract: address!("0x15261eEb999eD3C3ae3c5319E0035940dc06a12f"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054"), +}; + +pub static PLASMA: TokenInfo = TokenInfo { + name: "Plasma", + symbol: "XPL", + decimals: 18, + contract: address!("0x139451953Ef1865c096F89C5e522C081DC3b5f11"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/plasma/info/logo.png"), +}; + +pub static XRP: TokenInfo = TokenInfo { + name: "XRP", + symbol: "XRP", + decimals: 18, + contract: address!("0x2615a94df961278DcbC41Fb0a54fEc5f10a693aE"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ripple/info/logo.png"), +}; + +pub static XSGD_130_021265C3: TokenInfo = TokenInfo { + name: "XSGD", + symbol: "XSGD", + decimals: 6, + contract: address!("0xb1A9385B500Fe81B58c4d0e3AaCC39d8021265c3"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623"), +}; + +pub static XYO_NETWORK_130_2AEBE4EA: TokenInfo = TokenInfo { + name: "XYO Network", + symbol: "XYO", + decimals: 18, + contract: address!("0x43D5EA0f30Bce3907aAD6783e61D56592AEbE4eA"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819"), +}; + +pub static YEARN_FINANCE_130_F84A3201: TokenInfo = TokenInfo { + name: "yearn finance", + symbol: "YFI", + decimals: 18, + contract: address!("0x52Bf54Eb4210F588320f3e4c151Bca81f84a3201"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), +}; + +pub static DFI_MONEY_130_6C18A07E: TokenInfo = TokenInfo { + name: "DFI money", + symbol: "YFII", + decimals: 18, + contract: address!("0x62ffD4229bb9a327412D1BE518A1dbAe6c18A07E"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/11902/thumb/YFII-logo.78631676.png?1598677348"), +}; + +pub static YIELD_GUILD_GAMES_130_76E36F4B: TokenInfo = TokenInfo { + name: "Yield Guild Games", + symbol: "YGG", + decimals: 18, + contract: address!("0xeA20C2Cf22acBbF3d8311D15bC73FD7076E36f4B"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/17358/thumb/le1nzlO6_400x400.jpg?1632465691"), +}; + +pub static ZCASH: TokenInfo = TokenInfo { + name: "Zcash", + symbol: "ZEC", + decimals: 18, + contract: address!("0x83f31af747189c2FA9E5DeB253200c505eff6ed2"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/zcash/info/logo.png"), +}; + +pub static ZETACHAIN_130_B3CB3CA4: TokenInfo = TokenInfo { + name: "Zetachain", + symbol: "Zeta", + decimals: 18, + contract: address!("0x757dCF360f2FE999FAEEBcc6E80f5Eceb3cb3CA4"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/26718/standard/Twitter_icon.png?1696525788"), +}; + +pub static LAYERZERO_130_7ED29CFB: TokenInfo = TokenInfo { + name: "LayerZero", + symbol: "ZRO", + decimals: 18, + contract: address!("0x00ad3704d1e101DF76f87738bEfE67737eD29cFb"), + chain: 130, + logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), +}; + +pub static TOKEN_0X_PROTOCOL_TOKEN_130_A6E7EDF5: TokenInfo = TokenInfo { + name: "0x Protocol Token", + symbol: "ZRX", + decimals: 18, + contract: address!("0x7e7e8e5f0eDd7ca2ed3D9609cea1FF37a6E7Edf5"), + chain: 130, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), +}; + +pub static AAVE_137_2B21C90B: TokenInfo = TokenInfo { + name: "Aave", + symbol: "AAVE", + decimals: 18, + contract: address!("0xD6DF932A45C0f255f85145f286eA0b292B21C90B"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), +}; + +pub static AGEUR_137_C0057DB4: TokenInfo = TokenInfo { + name: "agEur", + symbol: "agEUR", + decimals: 18, + contract: address!("0xE0B52e49357Fd4DAf2c15e02058DCE6BC0057db4"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), +}; + +pub static AMP_137_4F27054D: TokenInfo = TokenInfo { + name: "Amp", + symbol: "AMP", + decimals: 18, + contract: address!("0x0621d647cecbFb64b79E44302c1933cB4f27054d"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/12409/thumb/amp-200x200.png?1599625397"), +}; + +pub static BALANCER_137_3B0E76A3: TokenInfo = TokenInfo { + name: "Balancer", + symbol: "BAL", + decimals: 18, + contract: address!("0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png"), +}; + +pub static BAND_PROTOCOL_137_D82606AC: TokenInfo = TokenInfo { + name: "Band Protocol", + symbol: "BAND", + decimals: 18, + contract: address!("0xA8b1E0764f85f53dfe21760e8AfE5446D82606ac"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/9545/thumb/band-protocol.png?1568730326"), +}; + +pub static BANCOR_NETWORK_TOKEN_137_2A4F7842: TokenInfo = TokenInfo { + name: "Bancor Network Token", + symbol: "BNT", + decimals: 18, + contract: address!("0xc26D47d5c33aC71AC5CF9F776D63Ba292a4F7842"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png"), +}; + +pub static COMPOUND_137_837AEF5C: TokenInfo = TokenInfo { + name: "Compound", + symbol: "COMP", + decimals: 18, + contract: address!("0x8505b9d2254A7Ae468c0E9dd10Ccea3A837aef5c"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), +}; + +pub static CURVE_DAO_TOKEN_137_33A610AF: TokenInfo = TokenInfo { + name: "Curve DAO Token", + symbol: "CRV", + decimals: 18, + contract: address!("0x172370d5Cd63279eFa6d502DAB29171933a610AF"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), +}; + +pub static CIVIC_137_398B02BE: TokenInfo = TokenInfo { + name: "Civic", + symbol: "CVC", + decimals: 8, + contract: address!("0x66Dc5A08091d1968e08C16aA5b27BAC8398b02Be"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556"), +}; + +pub static DAI_STABLECOIN_137_39C6A063: TokenInfo = TokenInfo { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + contract: address!("0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), +}; + +pub static ETHEREUM_NAME_SERVICE_137_90EE7C4F: TokenInfo = TokenInfo { + name: "Ethereum Name Service", + symbol: "ENS", + decimals: 18, + contract: address!("0xbD7A5Cf51d22930B8B3Df6d834F9BCEf90EE7c4f"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140"), +}; + +pub static GNOSIS_TOKEN_137_7DF024A8: TokenInfo = TokenInfo { + name: "Gnosis Token", + symbol: "GNO", + decimals: 18, + contract: address!("0x5FFD62D3C3eE2E81C00A7b9079FB248e7dF024A8"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png"), +}; + +pub static THE_GRAPH_137_499F5531: TokenInfo = TokenInfo { + name: "The Graph", + symbol: "GRT", + decimals: 18, + contract: address!("0x5fe2B58c013d7601147DcdD68C143A77499f5531"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566"), +}; + +pub static KEEP_NETWORK_137_2EB0C72C: TokenInfo = TokenInfo { + name: "Keep Network", + symbol: "KEEP", + decimals: 18, + contract: address!("0x42f37A1296b2981F7C3cAcEd84c5096b2Eb0C72C"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/3373/thumb/IuNzUb5b_400x400.jpg?1589526336"), +}; + +pub static KYBER_NETWORK_CRYSTAL_137_9CFA1DC7: TokenInfo = TokenInfo { + name: "Kyber Network Crystal", + symbol: "KNC", + decimals: 18, + contract: address!("0x324b28d6565f784d596422B0F2E5aB6e9CFA1Dc7"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png"), +}; + +pub static CHAINLINK_TOKEN_137_3FABAD39: TokenInfo = TokenInfo { + name: "ChainLink Token", + symbol: "LINK", + decimals: 18, + contract: address!("0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), +}; + +pub static LOOM_NETWORK_137_1193F6B3: TokenInfo = TokenInfo { + name: "Loom Network", + symbol: "LOOM", + decimals: 18, + contract: address!("0x66EfB7cC647e0efab02eBA4316a2d2941193F6b3"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0/logo.png"), +}; + +pub static LOOPRINGCOIN_V2_137_BB47DDC1: TokenInfo = TokenInfo { + name: "LoopringCoin V2", + symbol: "LRC", + decimals: 18, + contract: address!("0x84e1670F61347CDaeD56dcc736FB990fBB47ddC1"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png"), +}; + +pub static DECENTRALAND_137_33606FD4: TokenInfo = TokenInfo { + name: "Decentraland", + symbol: "MANA", + decimals: 18, + contract: address!("0xA1c57f48F0Deb89f569dFbE6E2B7f46D33606fD4"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745"), +}; + +pub static POLYGON_137_00001010: TokenInfo = TokenInfo { + name: "Polygon", + symbol: "MATIC", + decimals: 18, + contract: address!("0x0000000000000000000000000000000000001010"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), +}; + +pub static MAKER_137_E01FF61D: TokenInfo = TokenInfo { + name: "Maker", + symbol: "MKR", + decimals: 18, + contract: address!("0x6f7C932e7684666C9fd1d44527765433e01fF61d"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png"), +}; + +pub static NUMERAIRE_137_11F46729: TokenInfo = TokenInfo { + name: "Numeraire", + symbol: "NMR", + decimals: 18, + contract: address!("0x0Bf519071b02F22C17E7Ed5F4002ee1911f46729"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png"), +}; + +pub static ORCHID_137_D31F6060: TokenInfo = TokenInfo { + name: "Orchid", + symbol: "OXT", + decimals: 18, + contract: address!("0x9880e3dDA13c8e7D4804691A45160102d31F6060"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x4575f41308EC1483f3d399aa9a2826d74Da13Deb/logo.png"), +}; + +pub static REPUBLIC_TOKEN_137_26ED89D0: TokenInfo = TokenInfo { + name: "Republic Token", + symbol: "REN", + decimals: 18, + contract: address!("0x19782D3Dc4701cEeeDcD90f0993f0A9126ed89d0"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png"), +}; + +pub static REPUTATION_AUGUR_V2_137_7363F733: TokenInfo = TokenInfo { + name: "Reputation Augur v2", + symbol: "REPv2", + decimals: 18, + contract: address!("0x6563c1244820CfBd6Ca8820FBdf0f2847363F733"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x221657776846890989a759BA2973e427DfF5C9bB/logo.png"), +}; + +pub static SYNTHETIX_NETWORK_TOKEN_137_11FEF68A: TokenInfo = TokenInfo { + name: "Synthetix Network Token", + symbol: "SNX", + decimals: 18, + contract: address!("0x50B728D8D964fd00C2d0AAD81718b71311feF68a"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), +}; + +pub static STORJ_TOKEN_137_5A3F5792: TokenInfo = TokenInfo { + name: "Storj Token", + symbol: "STORJ", + decimals: 8, + contract: address!("0xd72357dAcA2cF11A5F155b9FF7880E595A3F5792"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png"), +}; + +pub static SYNTH_SUSD_137_6E03A7A0: TokenInfo = TokenInfo { + name: "Synth sUSD", + symbol: "sUSD", + decimals: 18, + contract: address!("0xF81b4Bec6Ca8f9fe7bE01CA734F55B2b6e03A7a0"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765"), +}; + +pub static UMA_VOTING_TOKEN_V1_137_77A6B731: TokenInfo = TokenInfo { + name: "UMA Voting Token v1", + symbol: "UMA", + decimals: 18, + contract: address!("0x3066818837c5e6eD6601bd5a91B0762877A6B731"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), +}; + +pub static UNISWAP_137_7FB5180F: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0xb33EaAd8d922B1083446DC23f610c2567fB5180f"), + chain: 137, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static USDCOIN_137_3D5C3359: TokenInfo = TokenInfo { + name: "USDCoin", + symbol: "USDC", + decimals: 6, + contract: address!("0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), +}; + +pub static USDCOIN_POS: TokenInfo = TokenInfo { + name: "USDCoin (PoS)", + symbol: "USDC.e", + decimals: 6, + contract: address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), +}; + +pub static TETHER_USD_137_04B58E8F: TokenInfo = TokenInfo { + name: "Tether USD", + symbol: "USDT", + decimals: 6, + contract: address!("0xc2132D05D31c914a87C6611C10748AEb04B58e8F"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), +}; + +pub static VANAR_CHAIN: TokenInfo = TokenInfo { + name: "Vanar Chain", + symbol: "VANRY", + decimals: 18, + contract: address!("0x8DE5B80a0C1B02Fe4976851D030B36122dbb8624"), + chain: 137, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/33466/large/apple-touch-icon.png?1701942541"), +}; + +pub static VOXIES: TokenInfo = TokenInfo { + name: "Voxies", + symbol: "VOXEL", + decimals: 18, + contract: address!("0xd0258a3fD00f38aa8090dfee343f10A9D4d30D3F"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/21260/large/voxies.png"), +}; + +pub static WRAPPED_BTC_137_47D9BFD6: TokenInfo = TokenInfo { + name: "Wrapped BTC", + symbol: "WBTC", + decimals: 8, + contract: address!("0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), +}; + +pub static WRAPPED_ETHER_137_F1B9F619: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static WRAPPED_MATIC: TokenInfo = TokenInfo { + name: "Wrapped Matic", + symbol: "WMATIC", + decimals: 18, + contract: address!("0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), +}; + +pub static XSGD_137_8D201995: TokenInfo = TokenInfo { + name: "XSGD", + symbol: "XSGD", + decimals: 6, + contract: address!("0xDC3326e71D45186F113a2F448984CA0e8D201995"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623"), +}; + +pub static YEARN_FINANCE_137_465260B6: TokenInfo = TokenInfo { + name: "yearn finance", + symbol: "YFI", + decimals: 18, + contract: address!("0xDA537104D6A5edd53c6fBba9A898708E465260b6"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), +}; + +pub static LAYERZERO_137_F13271CD: TokenInfo = TokenInfo { + name: "LayerZero", + symbol: "ZRO", + decimals: 18, + contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), + chain: 137, + logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), +}; + +pub static TOKEN_0X_PROTOCOL_TOKEN_137_CA6BE3D5: TokenInfo = TokenInfo { + name: "0x Protocol Token", + symbol: "ZRX", + decimals: 18, + contract: address!("0x5559Edb74751A0edE9DeA4DC23aeE72cCA6bE3D5"), + chain: 137, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), +}; + +pub static SOL_WORMHOLE_143_245217F1: TokenInfo = TokenInfo { + name: "SOL Wormhole ", + symbol: "SOL", + decimals: 9, + contract: address!("0xea17E5a9efEBf1477dB45082d67010E2245217f1"), + chain: 143, + logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), +}; + +pub static USDCOIN_143_5AAFB603: TokenInfo = TokenInfo { + name: "USDCoin", + symbol: "USDC", + decimals: 6, + contract: address!("0x754704Bc059F8C67012fEd69BC8A327a5aafb603"), + chain: 143, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), +}; + +pub static TETHER_USD_143_750FC82D: TokenInfo = TokenInfo { + name: "Tether USD", + symbol: "USDT", + decimals: 6, + contract: address!("0xe7cd86e13AC4309349F30B3435a9d337750fC82D"), + chain: 143, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), +}; + +pub static WRAPPED_BTC_143_230D2B9C: TokenInfo = TokenInfo { + name: "Wrapped BTC", + symbol: "WBTC", + decimals: 8, + contract: address!("0x0555E30da8f98308EdB960aa94C0Db47230d2B9c"), + chain: 143, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), +}; + +pub static WRAPPED_ETHER_143_35481242: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0xEE8c0E9f1BFFb4Eb878d8f15f368A02a35481242"), + chain: 143, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static GLOBAL_DOLLAR_196_933D2DC8: TokenInfo = TokenInfo { + name: "Global Dollar", + symbol: "USDG", + decimals: 6, + contract: address!("0x4ae46a509F6b1D9056937BA4500cb143933D2dc8"), + chain: 196, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/51281/large/GDN_USDG_Token_200x200.png?1730484111"), +}; + +pub static ZKSYNC: TokenInfo = TokenInfo { + name: "ZKsync", + symbol: "ZK", + decimals: 18, + contract: address!("0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E"), + chain: 324, + logo_uri: Some("https://assets.coingecko.com/coins/images/38043/large/ZKTokenBlack.png?17186145029"), +}; + +pub static BRIDGED_USDC: TokenInfo = TokenInfo { + name: "Bridged USDC", + symbol: "USDC.e", + decimals: 6, + contract: address!("0x79A02482A880bCE3F13e09Da970dC34db4CD24d1"), + chain: 480, + logo_uri: Some("https://assets.coingecko.com/coins/images/35218/large/USDC_Icon.png?1707908537"), +}; + +pub static WRAPPED_BTC_480_2D70CFA3: TokenInfo = TokenInfo { + name: "Wrapped BTC", + symbol: "WBTC", + decimals: 8, + contract: address!("0x03C7054BCB39f7b2e5B2c7AcB37583e32D70Cfa3"), + chain: 480, + logo_uri: Some("https://assets.coingecko.com/coins/images/7598/large/wrapped_bitcoin_wbtc.png?1696507857"), +}; + +pub static WRAPPED_ETHER_480_00000006: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0x4200000000000000000000000000000000000006"), + chain: 480, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static USDCOIN_1868_4AACC369: TokenInfo = TokenInfo { + name: "USDCoin", + symbol: "USDC", + decimals: 6, + contract: address!("0xbA9986D2381edf1DA03B0B9c1f8b00dc4AacC369"), + chain: 1868, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), +}; + +pub static TETHER_USD_1868_97B5AE35: TokenInfo = TokenInfo { + name: "Tether USD", + symbol: "USDT", + decimals: 6, + contract: address!("0x3A337a6adA9d885b6Ad95ec48F9b75f197b5AE35"), + chain: 1868, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), +}; + +pub static WRAPPED_ETHER_1868_00000006: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0x4200000000000000000000000000000000000006"), + chain: 1868, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static TOKEN_1INCH_8453_1E111CBE: TokenInfo = TokenInfo { + name: "1inch", + symbol: "1INCH", + decimals: 18, + contract: address!("0xc5fecC3a29Fb57B5024eEc8a2239d4621e111CBE"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), +}; + +pub static AAVE_8453_D17F814B: TokenInfo = TokenInfo { + name: "Aave", + symbol: "AAVE", + decimals: 18, + contract: address!("0x63706e401c06ac8513145b7687A14804d17f814b"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), +}; + +pub static ARCBLOCK_8453_7C1FA556: TokenInfo = TokenInfo { + name: "Arcblock", + symbol: "ABT", + decimals: 18, + contract: address!("0xe2A8cCB00E328a0EC2204CB0c736309D7c1fa556"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/2341/thumb/arcblock.png?1547036543"), +}; + +pub static AMBIRE_ADEX_8453_A3E0EFD9: TokenInfo = TokenInfo { + name: "Ambire AdEx", + symbol: "ADX", + decimals: 18, + contract: address!("0x3c87e7AF3cDBAe5bB56b4936325Ea95CA3E0EfD9"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/847/thumb/Ambire_AdEx_Symbol_color.png?1655432540"), +}; + +pub static AERODROME_FINANCE: TokenInfo = TokenInfo { + name: "Aerodrome Finance", + symbol: "AERO", + decimals: 18, + contract: address!("0x940181a94A35A4569E4529A3CDfB74e38FD98631"), + chain: 8453, + logo_uri: Some("https://basescan.org/token/images/aerodrome_32.png"), +}; + +pub static AIXBT_BY_VIRTUALS: TokenInfo = TokenInfo { + name: "aixbt by Virtuals", + symbol: "AIXBT", + decimals: 18, + contract: address!("0x4F9Fd6Be4a90f2620860d680c0d4d5Fb53d1A825"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/51784/large/3.png?1731981138"), +}; + +pub static ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_8453_D59F3DCC: TokenInfo = TokenInfo { + name: "Alethea Artificial Liquid Intelligence", + symbol: "ALI", + decimals: 18, + contract: address!("0x97c806e7665d3AFd84A8Fe1837921403D59F3Dcc"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848"), +}; + +pub static AUSTRALIAN_DIGITAL_DOLLAR: TokenInfo = TokenInfo { + name: "Australian Digital Dollar", + symbol: "AUDD", + decimals: 6, + contract: address!("0x449B3317a6d1efb1Bc3ba0700C9EaA4FFFf4Ae65"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/33263/large/AUDD-Logo-Blue_512.png?1701319895"), +}; + +pub static AVANTIS: TokenInfo = TokenInfo { + name: "Avantis", + symbol: "AVNT", + decimals: 18, + contract: address!("0x696F9436B67233384889472Cd7cD58A6fB5DF4f1"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/68972/large/avnt-token.png?1757134448"), +}; + +pub static AWE_NETWORK: TokenInfo = TokenInfo { + name: "AWE Network", + symbol: "AWE", + decimals: 18, + contract: address!("0x1B4617734C43F6159F3a70b7E06d883647512778"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/8713/large/awe-network.jpg?1747816016"), +}; + +pub static B3: TokenInfo = TokenInfo { + name: "B3", + symbol: "B3", + decimals: 18, + contract: address!("0xB3B32F9f8827D4634fE7d973Fa1034Ec9fdDB3B3"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54287/large/B3.png?1739001374"), +}; + +pub static HARRYPOTTEROBAMASONIC10INU_8453_D39A1A29: TokenInfo = TokenInfo { + name: "HarryPotterObamaSonic10Inu", + symbol: "BITCOIN", + decimals: 8, + contract: address!("0x2a06A17CBC6d0032Cac2c6696DA90f29D39a1a29"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224"), +}; + +pub static BANKRCOIN: TokenInfo = TokenInfo { + name: "BankrCoin", + symbol: "BNKR", + decimals: 18, + contract: address!("0x22aF33FE49fD1Fa80c7149773dDe5890D3c76F3b"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/52626/large/bankr-static.png?1736405365"), +}; + +pub static COINBASE_WRAPPED_ADA: TokenInfo = TokenInfo { + name: "Coinbase Wrapped ADA", + symbol: "cbADA", + decimals: 6, + contract: address!("0xcbADA732173e39521CDBE8bf59a6Dc85A9fc7b8c"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/66647/large/Coinbase_Wrapped_Ada_%28cbADA%29.png?1750129533"), +}; + +pub static COINBASE_WRAPPED_BTC_8453_0EED33BF: TokenInfo = TokenInfo { + name: "Coinbase Wrapped BTC", + symbol: "cbBTC", + decimals: 8, + contract: address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/40143/standard/cbbtc.webp"), +}; + +pub static COINBASE_WRAPPED_DOGE: TokenInfo = TokenInfo { + name: "Coinbase Wrapped DOGE", + symbol: "CBDOGE", + decimals: 8, + contract: address!("0xcbD06E5A2B0C65597161de254AA074E489dEb510"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/66268/large/Coinbase_Wrapped_Doge_%28cbDOGE%29.png?1749023465"), +}; + +pub static COINBASE_WRAPPED_STAKED_ETH_8453_CF0DEC22: TokenInfo = TokenInfo { + name: "Coinbase Wrapped Staked ETH", + symbol: "cbETH", + decimals: 18, + contract: address!("0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22"), + chain: 8453, + logo_uri: Some("https://ethereum-optimism.github.io/data/cbETH/logo.svg"), +}; + +pub static COINBASE_WRAPPED_LTC: TokenInfo = TokenInfo { + name: "Coinbase Wrapped LTC", + symbol: "cbLTC", + decimals: 8, + contract: address!("0xcb17C9Db87B595717C857a08468793f5bAb6445F"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/66646/large/Coinbase_Wrapped_Litecoin_%28cbLTC%29.png?1750129508"), +}; + +pub static COINBASE_WRAPPED_XRP: TokenInfo = TokenInfo { + name: "Coinbase Wrapped XRP", + symbol: "cbXRP", + decimals: 6, + contract: address!("0xcb585250f852C6c6bf90434AB21A00f02833a4af"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/66267/large/Coinbase_Wrapped_XPR_%28cbXRP%29.png?1749023398"), +}; + +pub static TOKENBOT: TokenInfo = TokenInfo { + name: "tokenbot", + symbol: "CLANKER", + decimals: 18, + contract: address!("0x1bc0c42215582d5A085795f4baDbaC3ff36d1Bcb"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/51440/large/CLANKER.png?1731232869"), +}; + +pub static COMPOUND_8453_976840E0: TokenInfo = TokenInfo { + name: "Compound", + symbol: "COMP", + decimals: 18, + contract: address!("0x9e1028F5F1D5eDE59748FFceE5532509976840E0"), + chain: 8453, + logo_uri: Some("https://ethereum-optimism.github.io/data/COMP/logo.svg"), +}; + +pub static COOKIE: TokenInfo = TokenInfo { + name: "Cookie", + symbol: "COOKIE", + decimals: 18, + contract: address!("0xC0041EF357B183448B235a8Ea73Ce4E4eC8c265F"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/38450/large/cookie_token_logo_200x200.png?1733194528"), +}; + +pub static CURVE_DAO_TOKEN_8453_67DD0415: TokenInfo = TokenInfo { + name: "Curve DAO Token", + symbol: "CRV", + decimals: 18, + contract: address!("0x8Ee73c484A26e0A5df2Ee2a4960B789967dd0415"), + chain: 8453, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), +}; + +pub static CARTESI_8453_76138D45: TokenInfo = TokenInfo { + name: "Cartesi", + symbol: "CTSI", + decimals: 18, + contract: address!("0x259Fac10c5CbFEFE3E710e1D9467f70a76138d45"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), +}; + +pub static CRYPTEX_FINANCE_8453_D4666E14: TokenInfo = TokenInfo { + name: "Cryptex Finance", + symbol: "CTX", + decimals: 18, + contract: address!("0xBB22Ff867F8Ca3D5F2251B4084F6Ec86D4666E14"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171"), +}; + +pub static COVALENT_X_TOKEN_8453_8EB628FF: TokenInfo = TokenInfo { + name: "Covalent X Token", + symbol: "CXT", + decimals: 18, + contract: address!("0xB1E1f3Cc2B6fE4420C1Ac82022b457018Eb628ff"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/39177/large/CXT_Ticker.png?1720829918"), +}; + +pub static DAI_STABLECOIN_8453_917DB0CB: TokenInfo = TokenInfo { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + contract: address!("0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb"), + chain: 8453, + logo_uri: Some("https://ethereum-optimism.github.io/data/DAI/logo.svg"), +}; + +pub static DEGEN: TokenInfo = TokenInfo { + name: "Degen", + symbol: "DEGEN", + decimals: 18, + contract: address!("0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/34515/large/android-chrome-512x512.png?1706198225"), +}; + +pub static DOGINME: TokenInfo = TokenInfo { + name: "doginme", + symbol: "doginme", + decimals: 18, + contract: address!("0x6921B130D297cc43754afba22e5EAc0FBf8Db75b"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/35123/large/doginme-logo1-transparent200.png?1710856784"), +}; + +pub static DOVU_8453_B953F865: TokenInfo = TokenInfo { + name: "DOVU", + symbol: "DOVU", + decimals: 8, + contract: address!("0xB38266e0e9D9681b77aEB0A280E98131b953F865"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/31930/large/Dovu_Icon_Black_%281%29.png?1696530738"), +}; + +pub static DERIVE_8453_B645D083: TokenInfo = TokenInfo { + name: "Derive", + symbol: "DRV", + decimals: 18, + contract: address!("0x9d0E8f5b25384C7310CB8C6aE32C8fbeb645d083"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695"), +}; + +pub static DEFINITIVE: TokenInfo = TokenInfo { + name: "Definitive", + symbol: "EDGE", + decimals: 18, + contract: address!("0xED6E000dEF95780fb89734c07EE2ce9F6dcAf110"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/55072/large/EDGE-120x120.png?1743598652"), +}; + +pub static ELSA: TokenInfo = TokenInfo { + name: "Elsa", + symbol: "ELSA", + decimals: 18, + contract: address!("0x29cC30f9D113B356Ce408667aa6433589CeCBDcA"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/71623/large/Red_circle_white_logo_512x512_%281%29.png?1768570174"), +}; + +pub static EURC: TokenInfo = TokenInfo { + name: "EURC", + symbol: "EURC", + decimals: 6, + contract: address!("0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/26045/standard/euro.png"), +}; + +pub static FAI: TokenInfo = TokenInfo { + name: "FAI", + symbol: "FAI", + decimals: 18, + contract: address!("0xb33Ff54b9F7242EF1593d2C9Bcd8f9df46c77935"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/52315/large/FAI.png?1733076295"), +}; + +pub static FLOCK: TokenInfo = TokenInfo { + name: "Flock", + symbol: "FLOCK", + decimals: 18, + contract: address!("0x5aB3D4c385B400F3aBB49e80DE2fAF6a88A7B691"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/53178/large/FLock_Token_Logo.png?1735561398"), +}; + +pub static FLUID: TokenInfo = TokenInfo { + name: "Fluid", + symbol: "FLUID", + decimals: 18, + contract: address!("0x61E030A56D33e8260FdD81f03B162A79Fe3449Cd"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/14688/large/Logo_1_(brighter).png?1734430693"), +}; + +pub static SPORT_FUN: TokenInfo = TokenInfo { + name: "Sport.fun", + symbol: "FUN1", + decimals: 18, + contract: address!("0x16EE7ecAc70d1028E7712751E2Ee6BA808a7dd92"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/71076/large/sport-fun-logo.png?1766298060"), +}; + +pub static HOME: TokenInfo = TokenInfo { + name: "HOME", + symbol: "HOME", + decimals: 18, + contract: address!("0x4BfAa776991E85e5f8b1255461cbbd216cFc714f"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54873/large/defi-app.png?1742235743"), +}; + +pub static HYPERLANE: TokenInfo = TokenInfo { + name: "Hyperlane", + symbol: "HYPER", + decimals: 18, + contract: address!("0xC9d23ED2ADB0f551369946BD377f8644cE1ca5c4"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/55298/large/Hyperlane.png?1745248900"), +}; + +pub static IOTEX_8453_27AE38C1: TokenInfo = TokenInfo { + name: "IoTeX", + symbol: "IOTX", + decimals: 18, + contract: address!("0xBCBAf311ceC8a4EAC0430193A528d9FF27ae38C1"), + chain: 8453, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/2777.png"), +}; + +pub static GEOJAM_8453_3AA2A057: TokenInfo = TokenInfo { + name: "Geojam", + symbol: "JAM", + decimals: 18, + contract: address!("0xFf9957816c813C5Ad0b9881A8990Df1E3AA2a057"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/24648/thumb/ey40AzBN_400x400.jpg?1648507272"), +}; + +pub static KAITO: TokenInfo = TokenInfo { + name: "KAITO", + symbol: "KAITO", + decimals: 18, + contract: address!("0x98d0baa52b2D063E780DE12F615f963Fe8537553"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54411/large/Qm4DW488_400x400.jpg?1739552780"), +}; + +pub static KEYBOARD_CAT: TokenInfo = TokenInfo { + name: "Keyboard Cat", + symbol: "KEYCAT", + decimals: 18, + contract: address!("0x9a26F5433671751C3276a065f57e5a02D2817973"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/36608/large/keyboard_cat.jpeg?1711965348"), +}; + +pub static KRYLL_8453_611F9F7A: TokenInfo = TokenInfo { + name: "KRYLL", + symbol: "KRL", + decimals: 18, + contract: address!("0xDAE49C25fAd3a62a8e8bFB6dA12c46bE611f9f7a"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979"), +}; + +pub static KEETA: TokenInfo = TokenInfo { + name: "Keeta", + symbol: "KTA", + decimals: 18, + contract: address!("0xc0634090F2Fe6c6d75e61Be2b949464aBB498973"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54723/large/2025-03-05_22.53.06.jpg?1741234207"), +}; + +pub static LCX_8453_71D3C171: TokenInfo = TokenInfo { + name: "LCX", + symbol: "LCX", + decimals: 18, + contract: address!("0xd7468c14ae76C3Fc308aEAdC223D5D1F71d3c171"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/9985/thumb/zRPSu_0o_400x400.jpg?1574327008"), +}; + +pub static LIQUITY_8453_BDDC125C: TokenInfo = TokenInfo { + name: "Liquity", + symbol: "LQTY", + decimals: 18, + contract: address!("0x5259384690aCF240e9b0A8811bD0FFbFBDdc125C"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180"), +}; + +pub static MAMO: TokenInfo = TokenInfo { + name: "Mamo", + symbol: "MAMO", + decimals: 18, + contract: address!("0x7300B37DfdfAb110d83290A29DfB31B1740219fE"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/55958/large/Mamo_Circle_200x200_TransBG.png?1748974093"), +}; + +pub static NOICE: TokenInfo = TokenInfo { + name: "Noice", + symbol: "NOICE", + decimals: 18, + contract: address!("0x9Cb41FD9dC6891BAe8187029461bfAADF6CC0C69"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/55981/large/tCtKSYL3_400x400.jpg?1747925133"), +}; + +pub static ODOS_TOKEN: TokenInfo = TokenInfo { + name: "Odos Token", + symbol: "ODOS", + decimals: 18, + contract: address!("0xca73ed1815e5915489570014e024b7EbE65dE679"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/52914/large/odos.jpg?1734678948"), +}; + +pub static PENDLE_8453_029EEB3E: TokenInfo = TokenInfo { + name: "Pendle", + symbol: "PENDLE", + decimals: 18, + contract: address!("0xA99F6e6785Da0F5d6fB42495Fe424BCE029Eeb3E"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728"), +}; + +pub static PEPE_8453_8B982BE3: TokenInfo = TokenInfo { + name: "Pepe", + symbol: "PEPE", + decimals: 18, + contract: address!("0xB4fDe59a779991bfB6a52253B51947828b982be3"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725"), +}; + +pub static PERPETUAL_PROTOCOL_8453_DAAD58DE: TokenInfo = TokenInfo { + name: "Perpetual Protocol", + symbol: "PERP", + decimals: 18, + contract: address!("0xCD6dDDa305955AcD6b94b934f057E8b0daaD58dE"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), +}; + +pub static PRIME_8453_A5ADD21B: TokenInfo = TokenInfo { + name: "Prime", + symbol: "PRIME", + decimals: 18, + contract: address!("0xfA980cEd6895AC314E7dE34Ef1bFAE90a5AdD21b"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222"), +}; + +pub static PROPY_8453_9230438B: TokenInfo = TokenInfo { + name: "Propy", + symbol: "PRO", + decimals: 8, + contract: address!("0x18dD5B087bCA9920562aFf7A0199b96B9230438b"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/869/thumb/propy.png?1548332100"), +}; + +pub static PROMPT: TokenInfo = TokenInfo { + name: "Prompt", + symbol: "PROMPT", + decimals: 18, + contract: address!("0x30c7235866872213F68cb1F08c37Cb9eCCB93452"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/55169/large/wayfinder.jpg?1744336900"), +}; + +pub static RAVEDAO: TokenInfo = TokenInfo { + name: "RaveDAO", + symbol: "RAVE", + decimals: 18, + contract: address!("0x1aA8fD5BCce2231C6100d55Bf8B377cff33Acfc3"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/70544/large/coin.jpeg?1762452940"), +}; + +pub static RECALL_NETWORK: TokenInfo = TokenInfo { + name: "Recall Network", + symbol: "RECALL", + decimals: 18, + contract: address!("0x1f16e03C1a5908818F47f6EE7bB16690b40D0671"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/69994/large/recall-logo.jpeg?1760337415"), +}; + +pub static RAINBOW: TokenInfo = TokenInfo { + name: "Rainbow", + symbol: "RNBW", + decimals: 18, + contract: address!("0xa53887F7e7c1bf5010b8627F1C1ba94fE7a5d6E0"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/69445/large/RNBW-200px.png?1770053251"), +}; + +pub static RESEARCHCOIN: TokenInfo = TokenInfo { + name: "ResearchCoin", + symbol: "RSC", + decimals: 18, + contract: address!("0xFbB75A59193A3525a8825BeBe7D4b56899E2f7e1"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/28146/large/RH_BOTTLE_CLEAN_Aug_2024_1.png?1732742001"), +}; + +pub static RESERVE_RIGHTS_8453_6072F64A: TokenInfo = TokenInfo { + name: "Reserve Rights", + symbol: "RSR", + decimals: 18, + contract: address!("0xaB36452DbAC151bE02b16Ca17d8919826072f64a"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856"), +}; + +pub static SAPIEN: TokenInfo = TokenInfo { + name: "Sapien", + symbol: "SAPIEN", + decimals: 18, + contract: address!("0xC729777d0470F30612B1564Fd96E8Dd26f5814E3"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/68423/large/logo.png?1755710030"), +}; + +pub static SEAMLESSS: TokenInfo = TokenInfo { + name: "Seamlesss", + symbol: "SEAM", + decimals: 18, + contract: address!("0x1C7a460413dD4e964f96D8dFC56E7223cE88CD85"), + chain: 8453, + logo_uri: Some("https://basescan.org/token/images/seamless_32.png"), +}; + +pub static STATUS_8453_2E8AC09E: TokenInfo = TokenInfo { + name: "Status", + symbol: "SNT", + decimals: 18, + contract: address!("0x662015EC830DF08C0FC45896FaB726542e8AC09E"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778"), +}; + +pub static SYNTHETIX_NETWORK_TOKEN_8453_327FDA66: TokenInfo = TokenInfo { + name: "Synthetix Network Token", + symbol: "SNX", + decimals: 18, + contract: address!("0x22e6966B799c4D5B13BE962E1D117b56327FDa66"), + chain: 8453, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), +}; + +pub static SPX6900_8453_6819BB2C: TokenInfo = TokenInfo { + name: "SPX6900", + symbol: "SPX", + decimals: 8, + contract: address!("0x50dA645f148798F68EF2d7dB7C1CB22A6819bb2C"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083"), +}; + +pub static SUPERFLUID_TOKEN: TokenInfo = TokenInfo { + name: "Superfluid Token", + symbol: "SUP", + decimals: 18, + contract: address!("0xa69f80524381275A7fFdb3AE01c54150644c8792"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/68697/large/sup.png?1756287343"), +}; + +pub static SUSHI_8453_98B2AFBA: TokenInfo = TokenInfo { + name: "Sushi", + symbol: "SUSHI", + decimals: 18, + contract: address!("0x7D49a065D17d6d4a55dc13649901fdBB98B2AFBA"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), +}; + +pub static SYNDICATE: TokenInfo = TokenInfo { + name: "Syndicate", + symbol: "SYND", + decimals: 18, + contract: address!("0x11dC28D01984079b7efE7763b533e6ed9E3722B9"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/69122/large/synd.png?1757576144"), +}; + +pub static TBTC_8453_22AB794B: TokenInfo = TokenInfo { + name: "tBTC", + symbol: "tBTC", + decimals: 18, + contract: address!("0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b"), + chain: 8453, + logo_uri: Some("https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png"), +}; + +pub static TOSHI: TokenInfo = TokenInfo { + name: "Toshi", + symbol: "TOSHI", + decimals: 18, + contract: address!("0xAC1Bd2486aAf3B5C0fc3Fd868558b082a531B2B4"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/31126/large/Toshi_Logo_-_Circular.png?1721677476"), +}; + +pub static TOWNS: TokenInfo = TokenInfo { + name: "Towns", + symbol: "TOWNS", + decimals: 18, + contract: address!("0x00000000A22C618fd6b4D7E9A335C4B96B189a38"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/55230/large/yImUvwK__400x400.png?1744857671"), +}; + +pub static INTUITION: TokenInfo = TokenInfo { + name: "Intuition", + symbol: "TRUST", + decimals: 18, + contract: address!("0x6cd905dF2Ed214b22e0d48FF17CD4200C1C6d8A3"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/55976/large/intuition_trust.jpg?1747904133"), +}; + +pub static UNISWAP_8453_114A3C83: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0xc3De830EA07524a0761646a6a4e4be0e114a3C83"), + chain: 8453, + logo_uri: Some("https://ethereum-optimism.github.io/data/UNI/logo.png"), +}; + +pub static SUPERFORM: TokenInfo = TokenInfo { + name: "Superform", + symbol: "UP", + decimals: 18, + contract: address!("0x5b2193fDc451C1f847bE09CA9d13A4Bf60f8c86B"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/70945/large/superform.png?1764747920"), +}; + +pub static USD_BASE_COIN: TokenInfo = TokenInfo { + name: "USD Base Coin", + symbol: "USDbC", + decimals: 6, + contract: address!("0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA"), + chain: 8453, + logo_uri: Some("https://ethereum-optimism.github.io/data/USDC/logo.png"), +}; + +pub static USD_COIN: TokenInfo = TokenInfo { + name: "USD Coin", + symbol: "USDC", + decimals: 6, + contract: address!("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"), + chain: 8453, + logo_uri: Some("https://ethereum-optimism.github.io/data/USDC/logo.png"), +}; + +pub static VENICE_TOKEN: TokenInfo = TokenInfo { + name: "Venice Token", + symbol: "VVV", + decimals: 18, + contract: address!("0xacfE6019Ed1A7Dc6f7B508C02d1b04ec88cC21bf"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/54023/standard/Venice_Token_(1).png?1738017546"), +}; + +pub static WALLETCONNECT_TOKEN_8453_DD927945: TokenInfo = TokenInfo { + name: "WalletConnect Token", + symbol: "WCT", + decimals: 18, + contract: address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/50390/large/wc-token1.png?1727569464"), +}; + +pub static MOONWELL: TokenInfo = TokenInfo { + name: "Moonwell", + symbol: "WELL", + decimals: 18, + contract: address!("0xA88594D404727625A9437C3f886C7643872296AE"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/26133/large/WELL.png?1696525221"), +}; + +pub static WRAPPED_ETHER_8453_00000006: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0x4200000000000000000000000000000000000006"), + chain: 8453, + logo_uri: Some("https://ethereum-optimism.github.io/data/WETH/logo.png"), +}; + +pub static WORLD_MOBILE_TOKEN: TokenInfo = TokenInfo { + name: "World Mobile Token", + symbol: "WMTX", + decimals: 18, + contract: address!("0x3e31966d4f81C72D2a55310A6365A56A4393E98D"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/17333/large/Token_icon_round_1024.png?1741247846"), +}; + +pub static XYO_NETWORK_8453_223ADC94: TokenInfo = TokenInfo { + name: "XYO Network", + symbol: "XYO", + decimals: 18, + contract: address!("0xD7B99ffB8B2afc6fe013a17207cbe50f223aDc94"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/4519/thumb/XYO_Network-logo.png?1547039819"), +}; + +pub static YEARN_FINANCE_8453_AD3CB239: TokenInfo = TokenInfo { + name: "yearn finance", + symbol: "YFI", + decimals: 18, + contract: address!("0x9EaF8C1E34F05a589EDa6BAfdF391Cf6Ad3CB239"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), +}; + +pub static YIELD_GUILD_GAMES_8453_F5EF1799: TokenInfo = TokenInfo { + name: "Yield Guild Games", + symbol: "YGG", + decimals: 18, + contract: address!("0xaAC78d1219c08AecC8e37e03858FE885f5EF1799"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/17358/thumb/le1nzlO6_400x400.jpg?1632465691"), +}; + +pub static HORIZEN: TokenInfo = TokenInfo { + name: "Horizen", + symbol: "ZEN", + decimals: 18, + contract: address!("0xf43eB8De897Fbc7F2502483B2Bef7Bb9EA179229"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/691/large/Horizen2.0-logo_icon-on-yellow_%281%29.png?1751696763"), +}; + +pub static BOUNDLESS_8453_FBBCE7CF: TokenInfo = TokenInfo { + name: "Boundless", + symbol: "ZKC", + decimals: 18, + contract: address!("0xAA61bB7777bD01B684347961918f1E07fBbCe7CF"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/68462/large/boundless.png?1755826792"), +}; + +pub static ZORA: TokenInfo = TokenInfo { + name: "Zora", + symbol: "ZORA", + decimals: 18, + contract: address!("0x1111111111166b7FE7bd91427724B487980aFc69"), + chain: 8453, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54693/large/zora.jpg?1741094751"), +}; + +pub static LAYERZERO_8453_F13271CD: TokenInfo = TokenInfo { + name: "LayerZero", + symbol: "ZRO", + decimals: 18, + contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), + chain: 8453, + logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), +}; + +pub static TOKEN_0X_PROTOCOL_TOKEN_8453_BC9779D0: TokenInfo = TokenInfo { + name: "0x Protocol Token", + symbol: "ZRX", + decimals: 18, + contract: address!("0x3bB4445D30AC020a84c1b5A8A2C6248ebC9779D0"), + chain: 8453, + logo_uri: Some("https://ethereum-optimism.github.io/data/ZRX/logo.png"), +}; + +pub static TOKEN_1INCH_42161_3F4BB9AF: TokenInfo = TokenInfo { + name: "1inch", + symbol: "1INCH", + decimals: 18, + contract: address!("0x6314C31A7a1652cE482cffe247E9CB7c3f4BB9aF"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), +}; + +pub static AAVE_42161_CE967196: TokenInfo = TokenInfo { + name: "Aave", + symbol: "AAVE", + decimals: 18, + contract: address!("0xba5DdD1f9d7F570dc94a51479a000E3BCE967196"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), +}; + +pub static ACROSS_PROTOCOL_TOKEN_42161_03D9C99D: TokenInfo = TokenInfo { + name: "Across Protocol Token", + symbol: "ACX", + decimals: 18, + contract: address!("0x53691596d1BCe8CEa565b84d4915e69e03d9C99d"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/28161/large/across-200x200.png?1696527165"), +}; + +pub static AEVO_42161_2B9783CD: TokenInfo = TokenInfo { + name: "Aevo", + symbol: "AEVO", + decimals: 18, + contract: address!("0x377c1Fc73D4D0f5600cd943776CED07c2B9783cd"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/35893/standard/aevo.png"), +}; + +pub static AGEUR_42161_723528E7: TokenInfo = TokenInfo { + name: "agEur", + symbol: "agEUR", + decimals: 18, + contract: address!("0xFA5Ed56A203466CbBC2430a43c66b9D8723528E7"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), +}; + +pub static ADVENTURE_GOLD_42161_012A3B9C: TokenInfo = TokenInfo { + name: "Adventure Gold", + symbol: "AGLD", + decimals: 18, + contract: address!("0xb7910E8b16e63EFD51d5D1a093d56280012A3B9C"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/18125/thumb/lpgblc4h_400x400.jpg?1630570955"), +}; + +pub static AIOZ_NETWORK_42161_E1569923: TokenInfo = TokenInfo { + name: "AIOZ Network", + symbol: "AIOZ", + decimals: 18, + contract: address!("0xeC76E8fe6e2242e6c2117caA244B9e2DE1569923"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14631/thumb/aioz_logo.png?1617413126"), +}; + +pub static ALEPH_IM_42161_8E245A6C: TokenInfo = TokenInfo { + name: "Aleph im", + symbol: "ALEPH", + decimals: 18, + contract: address!("0xe7dcD50836d0A28c959c72D72122fEDB8E245A6C"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11676/thumb/Monochram-aleph.png?1608483725"), +}; + +pub static ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_42161_FC0A71D1: TokenInfo = TokenInfo { + name: "Alethea Artificial Liquid Intelligence", + symbol: "ALI", + decimals: 18, + contract: address!("0xeF6124368c0B56556667e0de77eA008DfC0a71d1"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/22062/thumb/alethea-logo-transparent-colored.png?1642748848"), +}; + +pub static ALPHA_VENTURE_DAO_42161_0A6B2646: TokenInfo = TokenInfo { + name: "Alpha Venture DAO", + symbol: "ALPHA", + decimals: 18, + contract: address!("0xC9CBf102c73fb77Ec14f8B4C8bd88e050a6b2646"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876"), +}; + +pub static ANKR_42161_C1E95447: TokenInfo = TokenInfo { + name: "Ankr", + symbol: "ANKR", + decimals: 18, + contract: address!("0x1bfc5d35bf0f7B9e15dc24c78b8C02dbC1e95447"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978"), +}; + +pub static APECOIN_42161_DBAD2210: TokenInfo = TokenInfo { + name: "ApeCoin", + symbol: "APE", + decimals: 18, + contract: address!("0x74885b4D524d497261259B38900f54e6dbAd2210"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/24383/small/apecoin.jpg?1647476455"), +}; + +pub static API3_42161_92CA7811: TokenInfo = TokenInfo { + name: "API3", + symbol: "API3", + decimals: 18, + contract: address!("0xF01dB12F50D0CDF5Fe360ae005b9c52F92CA7811"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13256/thumb/api3.jpg?1606751424"), +}; + +pub static ARBITRUM_42161_E49E6548: TokenInfo = TokenInfo { + name: "Arbitrum", + symbol: "ARB", + decimals: 18, + contract: address!("0x912CE59144191C1204E64559FE8253a0e49E6548"), + chain: 42161, + logo_uri: Some("https://arbitrum.foundation/logo.png"), +}; + +pub static ARKHAM_42161_DA4E656E: TokenInfo = TokenInfo { + name: "Arkham", + symbol: "ARKM", + decimals: 18, + contract: address!("0xDac5094B7D59647626444a4F905060FCda4E656E"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/30929/standard/Arkham_Logo_CG.png?1696529771"), +}; + +pub static AUTOMATA_42161_75714D03: TokenInfo = TokenInfo { + name: "Automata", + symbol: "ATA", + decimals: 18, + contract: address!("0xAC9Ac2C17cdFED4AbC80A53c5553388575714d03"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/15985/thumb/ATA.jpg?1622535745"), +}; + +pub static AETHIR_TOKEN_42161_49092FB4: TokenInfo = TokenInfo { + name: "Aethir Token", + symbol: "ATH", + decimals: 18, + contract: address!("0xc7dEf82Ba77BAF30BbBc9b6162DC075b49092fb4"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/36179/large/logogram_circle_dark_green_vb_green_(1).png?1718232706"), +}; + +pub static AXELAR_42161_E2C6810F: TokenInfo = TokenInfo { + name: "Axelar", + symbol: "AXL", + decimals: 6, + contract: address!("0x23ee2343B892b1BB63503a4FAbc840E0e2C6810f"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg"), +}; + +pub static AXIE_INFINITY_42161_3E5D0089: TokenInfo = TokenInfo { + name: "Axie Infinity", + symbol: "AXS", + decimals: 18, + contract: address!("0xe88998Fb579266628aF6a03e3821d5983e5D0089"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13029/thumb/axie_infinity_logo.png?1604471082"), +}; + +pub static BADGER_DAO_42161_0D76472E: TokenInfo = TokenInfo { + name: "Badger DAO", + symbol: "BADGER", + decimals: 18, + contract: address!("0xBfa641051Ba0a0Ad1b0AcF549a89536A0D76472E"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13287/thumb/badger_dao_logo.jpg?1607054976"), +}; + +pub static BALANCER_42161_F56A56B8: TokenInfo = TokenInfo { + name: "Balancer", + symbol: "BAL", + decimals: 18, + contract: address!("0x040d1EdC9569d4Bab2D15287Dc5A4F10F56a56B8"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xba100000625a3754423978a60c9317c58a424e3D/logo.png"), +}; + +pub static BASIC_ATTENTION_TOKEN_42161_616AEE75: TokenInfo = TokenInfo { + name: "Basic Attention Token", + symbol: "BAT", + decimals: 18, + contract: address!("0x3450687EF141dCd6110b77c2DC44B008616AeE75"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427"), +}; + +pub static BICONOMY_42161_60A8E74D: TokenInfo = TokenInfo { + name: "Biconomy", + symbol: "BICO", + decimals: 18, + contract: address!("0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/21061/thumb/biconomy_logo.jpg?1638269749"), +}; + +pub static BITDAO_42161_EB921C2A: TokenInfo = TokenInfo { + name: "BitDAO", + symbol: "BIT", + decimals: 18, + contract: address!("0x406C8dB506653D882295875F633bEC0bEb921C2A"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/17627/thumb/rI_YptK8.png?1653983088"), +}; + +pub static HARRYPOTTEROBAMASONIC10INU_42161_13BD565D: TokenInfo = TokenInfo { + name: "HarryPotterObamaSonic10Inu", + symbol: "BITCOIN", + decimals: 8, + contract: address!("0xf7e17BA61973bcDB61f471eFb989E47d13bD565D"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/30323/large/hpos10i_logo_casino_night-dexview.png?1696529224"), +}; + +pub static BLUR_42161_FE606EB2: TokenInfo = TokenInfo { + name: "Blur", + symbol: "BLUR", + decimals: 18, + contract: address!("0xEf171a5BA71348eff16616fd692855c2Fe606EB2"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/28453/large/blur.png?1670745921"), +}; + +pub static BANCOR_NETWORK_TOKEN_42161_BA06D073: TokenInfo = TokenInfo { + name: "Bancor Network Token", + symbol: "BNT", + decimals: 18, + contract: address!("0x7A24159672b83ED1b89467c9d6A99556bA06D073"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C/logo.png"), +}; + +pub static BARNBRIDGE_42161_EE64A4E1: TokenInfo = TokenInfo { + name: "BarnBridge", + symbol: "BOND", + decimals: 18, + contract: address!("0x0D81E50bC677fa67341c44D7eaA9228DEE64A4e1"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12811/thumb/barnbridge.jpg?1602728853"), +}; + +pub static BINANCE_USD_42161_462629A2: TokenInfo = TokenInfo { + name: "Binance USD", + symbol: "BUSD", + decimals: 18, + contract: address!("0x31190254504622cEFdFA55a7d3d272e6462629a2"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), +}; + +pub static PANCAKESWAP_42161_7CF58860: TokenInfo = TokenInfo { + name: "PancakeSwap", + symbol: "CAKE", + decimals: 18, + contract: address!("0xCdc343ebf71e38F003eD6c80171F5B8D7cF58860"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/12632/large/pancakeswap-cake-logo_%281%29.png?1696512440"), +}; + +pub static COINBASE_WRAPPED_BTC_42161_0EED33BF: TokenInfo = TokenInfo { + name: "Coinbase Wrapped BTC", + symbol: "cbBTC", + decimals: 8, + contract: address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/40143/large/cbbtc.webp"), +}; + +pub static COINBASE_WRAPPED_STAKED_ETH_42161_EAE7732F: TokenInfo = TokenInfo { + name: "Coinbase Wrapped Staked ETH", + symbol: "cbETH", + decimals: 18, + contract: address!("0x1DEBd73E752bEaF79865Fd6446b0c970EaE7732f"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/27008/large/cbeth.png"), +}; + +pub static CELO_NATIVE_ASSET_WORMHOLE_42161_1EF4F336: TokenInfo = TokenInfo { + name: "Celo native asset (Wormhole)", + symbol: "CELO", + decimals: 18, + contract: address!("0x4E51aC49bC5e2d87e0EF713E9e5AB2D71EF4F336"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/celo_wh.png"), +}; + +pub static CELER_NETWORK_42161_40F345AB: TokenInfo = TokenInfo { + name: "Celer Network", + symbol: "CELR", + decimals: 18, + contract: address!("0x3a8B787f78D775AECFEEa15706D4221B40F345AB"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/4379/thumb/Celr.png?1554705437"), +}; + +pub static COMPOUND_42161_5C6C91DE: TokenInfo = TokenInfo { + name: "Compound", + symbol: "COMP", + decimals: 18, + contract: address!("0x354A6dA3fcde098F8389cad84b0182725c6C91dE"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), +}; + +pub static COTI_42161_D81EA101: TokenInfo = TokenInfo { + name: "COTI", + symbol: "COTI", + decimals: 18, + contract: address!("0x6FE14d3CC2f7bDdffBa5CdB3BBE7467dd81ea101"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/2962/thumb/Coti.png?1559653863"), +}; + +pub static COW_PROTOCOL_42161_F5C87A04: TokenInfo = TokenInfo { + name: "CoW Protocol", + symbol: "COW", + decimals: 18, + contract: address!("0xcb8b5CD20BdCaea9a010aC1F8d835824F5C87A04"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/24384/large/CoW-token_logo.png?1719524382"), +}; + +pub static COVALENT_42161_657273BF: TokenInfo = TokenInfo { + name: "Covalent", + symbol: "CQT", + decimals: 18, + contract: address!("0x69b937dB799a9BECC9E8A6F0a5d36eA3657273bf"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14168/thumb/covalent-cqt.png?1624545218"), +}; + +pub static CRONOS_42161_676F354C: TokenInfo = TokenInfo { + name: "Cronos", + symbol: "CRO", + decimals: 8, + contract: address!("0x8ea3156f834A0dfC78F1A5304fAC2CdA676F354C"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/7310/thumb/oCw2s3GI_400x400.jpeg?1645172042"), +}; + +pub static CURVE_DAO_TOKEN_42161_FA034978: TokenInfo = TokenInfo { + name: "Curve DAO Token", + symbol: "CRV", + decimals: 18, + contract: address!("0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xD533a949740bb3306d119CC777fa900bA034cd52/logo.png"), +}; + +pub static CARTESI_42161_1B476999: TokenInfo = TokenInfo { + name: "Cartesi", + symbol: "CTSI", + decimals: 18, + contract: address!("0x319f865b287fCC10b30d8cE6144e8b6D1b476999"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), +}; + +pub static CRYPTEX_FINANCE_42161_0425E12B: TokenInfo = TokenInfo { + name: "Cryptex Finance", + symbol: "CTX", + decimals: 18, + contract: address!("0x84F5c2cFba754E76DD5aE4fB369CfC920425E12b"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14932/thumb/glossy_icon_-_C200px.png?1619073171"), +}; + +pub static CIVIC_42161_1DDBF144: TokenInfo = TokenInfo { + name: "Civic", + symbol: "CVC", + decimals: 8, + contract: address!("0x9DfFB23CAd3322440bCcFF7aB1C58E781dDBF144"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/788/thumb/civic.png?1547034556"), +}; + +pub static CONVEX_FINANCE_42161_520829C5: TokenInfo = TokenInfo { + name: "Convex Finance", + symbol: "CVX", + decimals: 18, + contract: address!("0xaAFcFD42c9954C6689ef1901e03db742520829c5"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/15585/thumb/convex.png?1621256328"), +}; + +pub static DAI_STABLECOIN_42161_C9000DA1: TokenInfo = TokenInfo { + name: "Dai Stablecoin", + symbol: "DAI", + decimals: 18, + contract: address!("0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png"), +}; + +pub static DEXTOOLS_42161_9B64E227: TokenInfo = TokenInfo { + name: "DexTools", + symbol: "DEXT", + decimals: 18, + contract: address!("0x3Be7cB2e9413Ef8F42b4A202a0114EB59b64e227"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11603/thumb/dext.png?1605790188"), +}; + +pub static DIA_42161_E17AC05E: TokenInfo = TokenInfo { + name: "DIA", + symbol: "DIA", + decimals: 18, + contract: address!("0xca642467C6Ebe58c13cB4A7091317f34E17ac05e"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11955/thumb/image.png?1646041751"), +}; + +pub static DISTRICT0X_42161_A49AD47A: TokenInfo = TokenInfo { + name: "district0x", + symbol: "DNT", + decimals: 18, + contract: address!("0xE3696a02b2C9557639E29d829E9C45EFa49aD47A"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/849/thumb/district0x.png?1547223762"), +}; + +pub static DEFI_PULSE_INDEX_42161_B68DD74C: TokenInfo = TokenInfo { + name: "DeFi Pulse Index", + symbol: "DPI", + decimals: 18, + contract: address!("0x4667cf53C4eDF659E402B733BEA42B18B68dd74c"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12465/thumb/defi_pulse_index_set.png?1600051053"), +}; + +pub static DERIVE_42161_90ABB135: TokenInfo = TokenInfo { + name: "Derive", + symbol: "DRV", + decimals: 18, + contract: address!("0x77b7787a09818502305C95d68A2571F090abb135"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/52889/large/Token_Logo.png?1734601695"), +}; + +pub static DYDX_42161_8CC90C5A: TokenInfo = TokenInfo { + name: "dYdX", + symbol: "DYDX", + decimals: 18, + contract: address!("0x51863cB90Ce5d6dA9663106F292fA27c8CC90c5a"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/17500/thumb/hjnIm9bV.jpg?1628009360"), +}; + +pub static EIGENLAYER_42161_6F96C248: TokenInfo = TokenInfo { + name: "EigenLayer", + symbol: "EIGEN", + decimals: 18, + contract: address!("0x606C3e5075e5555e79Aa15F1E9FACB776F96C248"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/37441/large/eigen.jpg?1728023974"), +}; + +pub static DOGELON_MARS_42161_17077FD4: TokenInfo = TokenInfo { + name: "Dogelon Mars", + symbol: "ELON", + decimals: 18, + contract: address!("0x3e4Cff6E50F37F731284A92d44AE943e17077fD4"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14962/thumb/6GxcPRo3_400x400.jpg?1619157413"), +}; + +pub static ETHENA_42161_8EA977D8: TokenInfo = TokenInfo { + name: "Ethena", + symbol: "ENA", + decimals: 18, + contract: address!("0xdf8F0c63D9335A0AbD89F9F752d293A98EA977d8"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/36530/standard/ethena.png"), +}; + +pub static ENJIN_COIN_42161_63806758: TokenInfo = TokenInfo { + name: "Enjin Coin", + symbol: "ENJ", + decimals: 18, + contract: address!("0x7fa9549791EFc9030e1Ed3F25D18014163806758"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/1102/thumb/enjin-coin-logo.png?1547035078"), +}; + +pub static ETHEREUM_NAME_SERVICE_42161_E70D7C28: TokenInfo = TokenInfo { + name: "Ethereum Name Service", + symbol: "ENS", + decimals: 18, + contract: address!("0xfeA31d704DEb0975dA8e77Bf13E04239e70d7c28"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/19785/thumb/acatxTm8_400x400.jpg?1635850140"), +}; + +pub static ETHERNITY_CHAIN_42161_4D667F96: TokenInfo = TokenInfo { + name: "Ethernity Chain", + symbol: "ERN", + decimals: 18, + contract: address!("0x2354c8e9Ea898c751F1A15Addeb048714D667f96"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14238/thumb/LOGO_HIGH_QUALITY.png?1647831402"), +}; + +pub static ESPRESSO_42161_065C94F1: TokenInfo = TokenInfo { + name: "Espresso", + symbol: "ESP", + decimals: 18, + contract: address!("0x3b8db18e69d6686Ad9371A423aFe3Dd1065C94f1"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/67626/large/espresso.jpg?1753324525"), +}; + +pub static ETHER_FI_42161_4DFD5736: TokenInfo = TokenInfo { + name: "Ether.fi", + symbol: "ETHFI", + decimals: 18, + contract: address!("0x07D65C18CECbA423298c0aEB5d2BeDED4DFd5736"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/35958/standard/etherfi.jpeg"), +}; + +pub static EURO_COIN_42161_1FC52A48: TokenInfo = TokenInfo { + name: "Euro Coin", + symbol: "EURC", + decimals: 6, + contract: address!("0x863708032B5c328e11aBcbC0DF9D79C71Fc52a48"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/26045/thumb/euro-coin.png?1655394420"), +}; + +pub static HARVEST_FINANCE_42161_24C83C70: TokenInfo = TokenInfo { + name: "Harvest Finance", + symbol: "FARM", + decimals: 18, + contract: address!("0x8553d254Cb6934b16F87D2e486b64BbD24C83C70"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12304/thumb/Harvest.png?1613016180"), +}; + +pub static FETCH_AI_42161_7DCC4CC9: TokenInfo = TokenInfo { + name: "Fetch ai", + symbol: "FET", + decimals: 18, + contract: address!("0x4BE87C766A7CE11D5Cc864b6C3Abb7457dCC4cC9"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/5681/thumb/Fetch.jpg?1572098136"), +}; + +pub static STAFI_42161_767C7282: TokenInfo = TokenInfo { + name: "Stafi", + symbol: "FIS", + decimals: 18, + contract: address!("0x849B40AB2469309117Ed1038c5A99894767C7282"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12423/thumb/stafi_logo.jpg?1599730991"), +}; + +pub static FLOKI_42161_B4905FAE: TokenInfo = TokenInfo { + name: "FLOKI", + symbol: "FLOKI", + decimals: 9, + contract: address!("0xA8C25FdC09763A176353CC6a76882e05b4905FAe"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/16746/standard/PNG_image.png?1696516318"), +}; + +pub static FLUX_42161_D685710A: TokenInfo = TokenInfo { + name: "Flux", + symbol: "FLUX", + decimals: 18, + contract: address!("0x63806C056Fa458c548Fb416B15E358A9D685710A"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x720CD16b011b987Da3518fbf38c3071d4F0D1495/logo.png"), +}; + +pub static FORTA_42161_CC3D2923: TokenInfo = TokenInfo { + name: "Forta", + symbol: "FORT", + decimals: 18, + contract: address!("0x3A1429d50E0cBBc45c997aF600541Fe1cc3D2923"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/25060/thumb/Forta_lgo_%281%29.png?1655353696"), +}; + +pub static SHAPESHIFT_FOX_TOKEN_42161_9E513C73: TokenInfo = TokenInfo { + name: "ShapeShift FOX Token", + symbol: "FOX", + decimals: 18, + contract: address!("0xf929de51D91C77E42f5090069E0AD7A09e513c73"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/9988/thumb/FOX.png?1574330622"), +}; + +pub static FRAX_42161_0BC51305: TokenInfo = TokenInfo { + name: "Frax", + symbol: "FRAX", + decimals: 18, + contract: address!("0x7468a5d8E02245B00E8C0217fCE021C70Bc51305"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), +}; + +pub static FANTOM_42161_D4C2DF37: TokenInfo = TokenInfo { + name: "Fantom", + symbol: "FTM", + decimals: 18, + contract: address!("0xd42785D323e608B9E99fa542bd8b1000D4c2Df37"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/4001/thumb/Fantom.png?1558015016"), +}; + +pub static FRAX_SHARE_42161_AFFFDEA4: TokenInfo = TokenInfo { + name: "Frax Share", + symbol: "FXS", + decimals: 18, + contract: address!("0xd9f9d2Ee2d3EFE420699079f16D9e924affFdEA4"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), +}; + +pub static GALXE_42161_9BFD1182: TokenInfo = TokenInfo { + name: "Galxe", + symbol: "GAL", + decimals: 18, + contract: address!("0xc27E7325a6BEA1FcC06de7941473f5279bfd1182"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/24530/thumb/GAL-Token-Icon.png?1651483533"), +}; + +pub static GALA_42161_2827FF8C: TokenInfo = TokenInfo { + name: "GALA", + symbol: "GALA", + decimals: 8, + contract: address!("0x2A676eeAd159c4C8e8593471c6d666F02827FF8C"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12493/standard/GALA-COINGECKO.png?1696512310"), +}; + +pub static GMX: TokenInfo = TokenInfo { + name: "GMX", + symbol: "GMX", + decimals: 18, + contract: address!("0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/18323/large/arbit.png?1631532468"), +}; + +pub static GNOSIS_TOKEN_42161_4DEB6CF1: TokenInfo = TokenInfo { + name: "Gnosis Token", + symbol: "GNO", + decimals: 18, + contract: address!("0xa0b862F60edEf4452F25B4160F177db44DeB6Cf1"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6810e776880C02933D47DB1b9fc05908e5386b96/logo.png"), +}; + +pub static THE_GRAPH_42161_EA7E88C7: TokenInfo = TokenInfo { + name: "The Graph", + symbol: "GRT", + decimals: 18, + contract: address!("0x9623063377AD1B27544C965cCd7342f7EA7e88C7"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566"), +}; + +pub static GITCOIN_42161_C437DEE0: TokenInfo = TokenInfo { + name: "Gitcoin", + symbol: "GTC", + decimals: 18, + contract: address!("0x7f9a7DB853Ca816B9A138AEe3380Ef34c437dEe0"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/15810/thumb/gitcoin.png?1621992929"), +}; + +pub static GYEN_42161_D9B6D5F7: TokenInfo = TokenInfo { + name: "GYEN", + symbol: "GYEN", + decimals: 6, + contract: address!("0x589d35656641d6aB57A545F08cf473eCD9B6D5F7"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14191/thumb/icon_gyen_200_200.png?1614843343"), +}; + +pub static HIGHSTREET_42161_615BCEEA: TokenInfo = TokenInfo { + name: "Highstreet", + symbol: "HIGH", + decimals: 18, + contract: address!("0xd12Eeb0142D4Efe7Af82e4f29E5Af382615bcEeA"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/18973/thumb/logosq200200Coingecko.png?1634090470"), +}; + +pub static HOPR_42161_70294EF7: TokenInfo = TokenInfo { + name: "HOPR", + symbol: "HOPR", + decimals: 18, + contract: address!("0x177F394A3eD18FAa85c1462Ae626438a70294EF7"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14061/thumb/Shared_HOPR_logo_512px.png?1614073468"), +}; + +pub static IDOS_TOKEN: TokenInfo = TokenInfo { + name: "idOS Token", + symbol: "IDOS", + decimals: 18, + contract: address!("0x68731d6F14B827bBCfFbEBb62b19Daa18de1d79c"), + chain: 42161, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/39596.png"), +}; + +pub static ILLUVIUM_42161_05488673: TokenInfo = TokenInfo { + name: "Illuvium", + symbol: "ILV", + decimals: 18, + contract: address!("0x61cA9D186f6b9a793BC08F6C79fd35f205488673"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14468/large/ILV.JPG"), +}; + +pub static IMMUTABLE_X_42161_FCA7783E: TokenInfo = TokenInfo { + name: "Immutable X", + symbol: "IMX", + decimals: 18, + contract: address!("0x3cFD99593a7F035F717142095a3898e3Fca7783e"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/17233/thumb/imx.png?1636691817"), +}; + +pub static INJECTIVE_42161_DF608F80: TokenInfo = TokenInfo { + name: "Injective", + symbol: "INJ", + decimals: 18, + contract: address!("0x2A2053cb633CAD465B4A8975eD3d7f09DF608F80"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12882/thumb/Secondary_Symbol.png?1628233237"), +}; + +pub static JASMYCOIN_42161_73E27083: TokenInfo = TokenInfo { + name: "JasmyCoin", + symbol: "JASMY", + decimals: 18, + contract: address!("0x25f05699548D3A0820b99f93c10c8BB573E27083"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13876/thumb/JASMY200x200.jpg?1612473259"), +}; + +pub static KINTO: TokenInfo = TokenInfo { + name: "Kinto", + symbol: "K", + decimals: 18, + contract: address!("0x010700AB046Dd8e92b0e3587842080Df36364ed3"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/54964/standard/k200.png?1742894885"), +}; + +pub static KRYLL_42161_B7307B69: TokenInfo = TokenInfo { + name: "KRYLL", + symbol: "KRL", + decimals: 18, + contract: address!("0xf75eE6D319741057a82a88Eeff1DbAFAB7307b69"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/2807/thumb/krl.png?1547036979"), +}; + +pub static KUJIRA_42161_5671E7CA: TokenInfo = TokenInfo { + name: "Kujira", + symbol: "KUJI", + decimals: 6, + contract: address!("0x3A18dcC9745eDcD1Ef33ecB93b0b6eBA5671e7Ca"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/20685/standard/kuji-200x200.png"), +}; + +pub static LIDO_DAO_42161_D85EFA60: TokenInfo = TokenInfo { + name: "Lido DAO", + symbol: "LDO", + decimals: 18, + contract: address!("0x13Ad51ed4F1B7e9Dc168d8a00cB3f4dDD85EfA60"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13573/thumb/Lido_DAO.png?1609873644"), +}; + +pub static CHAINLINK_TOKEN_42161_58539FB4: TokenInfo = TokenInfo { + name: "ChainLink Token", + symbol: "LINK", + decimals: 18, + contract: address!("0xf97f4df75117a78c1A5a0DBb814Af92458539FB4"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), +}; + +pub static LITENTRY_42161_30A40B25: TokenInfo = TokenInfo { + name: "Litentry", + symbol: "LIT", + decimals: 18, + contract: address!("0x349fc93da004a63F3B1343361465981330A40B25"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13825/large/logo_200x200.png"), +}; + +pub static LIVEPEER_42161_1CB8A839: TokenInfo = TokenInfo { + name: "Livepeer", + symbol: "LPT", + decimals: 18, + contract: address!("0x289ba1701C2F088cf0faf8B3705246331cB8A839"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/7137/thumb/logo-circle-green.png?1619593365"), +}; + +pub static LIQUITY_42161_CE3E1449: TokenInfo = TokenInfo { + name: "Liquity", + symbol: "LQTY", + decimals: 18, + contract: address!("0xfb9E5D956D889D91a82737B9bFCDaC1DCE3e1449"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14665/thumb/200-lqty-icon.png?1617631180"), +}; + +pub static LOOPRINGCOIN_V2_42161_1BAE7FBE: TokenInfo = TokenInfo { + name: "LoopringCoin V2", + symbol: "LRC", + decimals: 18, + contract: address!("0x46d0cE7de6247b0A95f67b43B589b4041BaE7fbE"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD/logo.png"), +}; + +pub static LIQUITY_USD_42161_2541425B: TokenInfo = TokenInfo { + name: "Liquity USD", + symbol: "LUSD", + decimals: 18, + contract: address!("0x93b346b6BC2548dA6A1E7d98E9a421B42541425b"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14666/thumb/Group_3.png?1617631327"), +}; + +pub static MAGIC: TokenInfo = TokenInfo { + name: "MAGIC", + symbol: "MAGIC", + decimals: 18, + contract: address!("0x539bdE0d7Dbd336b79148AA742883198BBF60342"), + chain: 42161, + logo_uri: Some("https://dynamic-assets.coinbase.com/30320a63f6038b944c9c0202fcb2392e6a1bd333814f74b4674774dd87f2d06d64fdd74c2f1ab4639917c75b749c323450408bec7a2737af8ae0c17871aa90de/asset_icons/98d278cda11639ed7449a0a3086cd2c83937ce71baf4ee43bb5b777423c00a75.png"), +}; + +pub static DECENTRALAND_42161_A165E231: TokenInfo = TokenInfo { + name: "Decentraland", + symbol: "MANA", + decimals: 18, + contract: address!("0x442d24578A564EF628A65e6a7E3e7be2a165E231"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/878/thumb/decentraland-mana.png?1550108745"), +}; + +pub static MASK_NETWORK_42161_5C313739: TokenInfo = TokenInfo { + name: "Mask Network", + symbol: "MASK", + decimals: 18, + contract: address!("0x533A7B414CD1236815a5e09F1E97FC7d5c313739"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14051/thumb/Mask_Network.jpg?1614050316"), +}; + +pub static MATH_42161_B17AC332: TokenInfo = TokenInfo { + name: "MATH", + symbol: "MATH", + decimals: 18, + contract: address!("0x99F40b01BA9C469193B360f72740E416B17Ac332"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11335/thumb/2020-05-19-token-200.png?1589940590"), +}; + +pub static POLYGON_42161_18BE0766: TokenInfo = TokenInfo { + name: "Polygon", + symbol: "MATIC", + decimals: 18, + contract: address!("0x561877b6b3DD7651313794e5F2894B2F18bE0766"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), +}; + +pub static METIS_42161_D2E33769: TokenInfo = TokenInfo { + name: "Metis", + symbol: "METIS", + decimals: 18, + contract: address!("0x7F728F3595db17B0B359f4FC47aE80FAd2e33769"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/15595/thumb/metis.jpeg?1660285312"), +}; + +pub static MAGIC_INTERNET_MONEY_42161_0C04DAF2: TokenInfo = TokenInfo { + name: "Magic Internet Money", + symbol: "MIM", + decimals: 18, + contract: address!("0xB20A02dfFb172C474BC4bDa3fD6f4eE70C04daf2"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612"), +}; + +pub static MAKER_42161_6F8F2879: TokenInfo = TokenInfo { + name: "Maker", + symbol: "MKR", + decimals: 18, + contract: address!("0x2e9a6Df78E42a30712c10a9Dc4b1C8656f8F2879"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png"), +}; + +pub static MELON_42161_7AE4B514: TokenInfo = TokenInfo { + name: "Melon", + symbol: "MLN", + decimals: 18, + contract: address!("0x8f5c1A99b1df736Ad685006Cb6ADCA7B7Ae4b514"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/605/thumb/melon.png?1547034295"), +}; + +pub static MANTLE_42161_EDF6C53A: TokenInfo = TokenInfo { + name: "Mantle", + symbol: "MNT", + decimals: 18, + contract: address!("0x9c1a1C7bA9c2602123FD7EF3eb41a769edf6C53A"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/30980/large/Mantle-Logo-mark.png?1739213200"), +}; + +pub static MOG_COIN_42161_206AABAC: TokenInfo = TokenInfo { + name: "Mog Coin", + symbol: "MOG", + decimals: 18, + contract: address!("0x96c42662820F6Ea32f0A61A06a38a72B206aABaC"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/31059/large/MOG_LOGO_200x200.png"), +}; + +pub static MORPHO_TOKEN_42161_02F620AC: TokenInfo = TokenInfo { + name: "Morpho Token", + symbol: "MORPHO", + decimals: 18, + contract: address!("0xE390C0B46bd723995BE02640E6F1e1c802F620AC"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/29837/large/Morpho-token-icon.png?1726771230"), +}; + +pub static MAPLE_42161_097F0CA0: TokenInfo = TokenInfo { + name: "Maple", + symbol: "MPL", + decimals: 18, + contract: address!("0x29024832eC3baBF5074D4F46102aA988097f0Ca0"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14097/thumb/photo_2021-05-03_14.20.41.jpeg?1620022863"), +}; + +pub static MULTICHAIN_42161_ECD9A39A: TokenInfo = TokenInfo { + name: "Multichain", + symbol: "MULTI", + decimals: 18, + contract: address!("0x7b9b94aebe5E2039531af8E31045f377EcD9A39A"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238"), +}; + +pub static GENSOKISHI_METAVERSE_42161_3E15992F: TokenInfo = TokenInfo { + name: "GensoKishi Metaverse", + symbol: "MV", + decimals: 18, + contract: address!("0x5445972E76c5e4CEdD12B6e2BceF69133E15992F"), + chain: 42161, + logo_uri: Some("https://s2.coinmarketcap.com/static/img/coins/64x64/17704.png"), +}; + +pub static MXC_42161_B6862ED6: TokenInfo = TokenInfo { + name: "MXC", + symbol: "MXC", + decimals: 18, + contract: address!("0x91b468Fe3dce581D7a6cFE34189F1314b6862eD6"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/4604/thumb/mxc.png?1655534336"), +}; + +pub static POLYSWARM_42161_FB920D5B: TokenInfo = TokenInfo { + name: "PolySwarm", + symbol: "NCT", + decimals: 18, + contract: address!("0x53236015A675fcB937485F1AE58040e4Fb920d5b"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/2843/thumb/ImcYCVfX_400x400.jpg?1628519767"), +}; + +pub static NKN_42161_0406177B: TokenInfo = TokenInfo { + name: "NKN", + symbol: "NKN", + decimals: 18, + contract: address!("0xBE06ca305A5Cb49ABf6B1840da7c42690406177b"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/3375/thumb/nkn.png?1548329212"), +}; + +pub static NUMERAIRE_42161_6B569711: TokenInfo = TokenInfo { + name: "Numeraire", + symbol: "NMR", + decimals: 18, + contract: address!("0x597701b32553b9fa473e21362D480b3a6B569711"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671/logo.png"), +}; + +pub static OCEAN_PROTOCOL_42161_AD8234DF: TokenInfo = TokenInfo { + name: "Ocean Protocol", + symbol: "OCEAN", + decimals: 18, + contract: address!("0x933d31561e470478079FEB9A6Dd2691fAD8234DF"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/3687/thumb/ocean-protocol-logo.jpg?1547038686"), +}; + +pub static ORIGIN_PROTOCOL_42161_58AE423E: TokenInfo = TokenInfo { + name: "Origin Protocol", + symbol: "OGN", + decimals: 18, + contract: address!("0x6FEb262FEb0f775B5312D2e009923f7f58AE423E"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/3296/thumb/op.jpg?1547037878"), +}; + +pub static OMG_NETWORK_42161_61421E8E: TokenInfo = TokenInfo { + name: "OMG Network", + symbol: "OMG", + decimals: 18, + contract: address!("0xd962C1895c46AC0378C502c207748b7061421e8e"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/776/thumb/OMG_Network.jpg?1591167168"), +}; + +pub static ONDO_FINANCE_42161_8B37A5E7: TokenInfo = TokenInfo { + name: "Ondo Finance", + symbol: "ONDO", + decimals: 18, + contract: address!("0xA2d52A05B8Bead5d824DF54Dd1AA63188B37A5E7"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/26580/standard/ONDO.png?1696525656"), +}; + +pub static ORION_PROTOCOL_42161_551E6218: TokenInfo = TokenInfo { + name: "Orion Protocol", + symbol: "ORN", + decimals: 8, + contract: address!("0x1BDCC2075d5370293E248Cab0173eC3E551e6218"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11841/thumb/orion_logo.png?1594943318"), +}; + +pub static PENDLE_42161_B9A8C9E8: TokenInfo = TokenInfo { + name: "Pendle", + symbol: "PENDLE", + decimals: 18, + contract: address!("0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728"), +}; + +pub static PEPE_42161_33959CBB: TokenInfo = TokenInfo { + name: "Pepe", + symbol: "PEPE", + decimals: 18, + contract: address!("0x35E6A59F786d9266c7961eA28c7b768B33959cbB"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/29850/large/pepe-token.jpeg?1682922725"), +}; + +pub static PERPETUAL_PROTOCOL_42161_F61D3DAC: TokenInfo = TokenInfo { + name: "Perpetual Protocol", + symbol: "PERP", + decimals: 18, + contract: address!("0x753D224bCf9AAFaCD81558c32341416df61D3DAC"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12381/thumb/60d18e06844a844ad75901a9_mark_only_03.png?1628674771"), +}; + +pub static PIRATE_NATION_42161_43D77CBF: TokenInfo = TokenInfo { + name: "Pirate Nation", + symbol: "PIRATE", + decimals: 18, + contract: address!("0xac7CE9F2794e01c0D27b096C52f592e343D77cbf"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/38524/standard/_Pirate_Transparent_200x200.png"), +}; + +pub static PLUME_42161_CB15BA13: TokenInfo = TokenInfo { + name: "Plume", + symbol: "PLUME", + decimals: 18, + contract: address!("0x73efDC761596328461B68E5FC58c3284CB15ba13"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/53623/large/plume-token.png?1736896935"), +}; + +pub static POLYGON_ECOSYSTEM_TOKEN_42161_68FE08CC: TokenInfo = TokenInfo { + name: "Polygon Ecosystem Token", + symbol: "POL", + decimals: 18, + contract: address!("0x044d8e7F3A17751D521efEa8CCf9282268fE08CC"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/32440/large/polygon.png?1698233684"), +}; + +pub static POLKASTARTER_42161_8B016B64: TokenInfo = TokenInfo { + name: "Polkastarter", + symbol: "POLS", + decimals: 18, + contract: address!("0xeeeB5EaC2dB7A7Fc28134aA3248580d48b016b64"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12648/thumb/polkastarter.png?1609813702"), +}; + +pub static POLYMATH_42161_B33809E9: TokenInfo = TokenInfo { + name: "Polymath", + symbol: "POLY", + decimals: 18, + contract: address!("0xE12F29704F635F4A6E7Ae154838d21F9B33809e9"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/2784/thumb/inKkF01.png?1605007034"), +}; + +pub static MARLIN_42161_C8BD9DDD: TokenInfo = TokenInfo { + name: "Marlin", + symbol: "POND", + decimals: 18, + contract: address!("0xdA0a57B710768ae17941a9Fa33f8B720c8bD9ddD"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/8903/thumb/POND_200x200.png?1622515451"), +}; + +pub static PORTAL_42161_9DB991DE: TokenInfo = TokenInfo { + name: "Portal", + symbol: "PORTAL", + decimals: 18, + contract: address!("0x6380F3d0C1412a80EB00F49064DA30749DB991DE"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/35436/standard/portal.jpeg"), +}; + +pub static POWER_LEDGER_42161_D423E4A6: TokenInfo = TokenInfo { + name: "Power Ledger", + symbol: "POWR", + decimals: 6, + contract: address!("0x4e91F2AF1ee0F84B529478f19794F5AFD423e4A6"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/1104/thumb/power-ledger.png?1547035082"), +}; + +pub static PRIME_42161_E7AC5067: TokenInfo = TokenInfo { + name: "Prime", + symbol: "PRIME", + decimals: 18, + contract: address!("0x8d8e1b6ffc6832E8D2eF0DE8a3d957cAE7ac5067"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/29053/large/PRIMELOGOOO.png?1676976222"), +}; + +pub static PARSIQ_42161_CAF60CD2: TokenInfo = TokenInfo { + name: "PARSIQ", + symbol: "PRQ", + decimals: 18, + contract: address!("0x82164a8B646401a8776F9dC5c8Cba35DcAf60Cd2"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11973/thumb/DsNgK0O.png?1596590280"), +}; + +pub static PAYPAL_USD_42161_0967342E: TokenInfo = TokenInfo { + name: "PayPal USD", + symbol: "PYUSD", + decimals: 6, + contract: address!("0x327006c8712FE0AbdbbD55B7999DB39b0967342E"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/31212/large/PYUSD_Logo_%282%29.png?1691458314"), +}; + +pub static QUANT_42161_3C7EFF85: TokenInfo = TokenInfo { + name: "Quant", + symbol: "QNT", + decimals: 18, + contract: address!("0xC7557C73e0eCa2E1BF7348bB6874Aee63C7eFF85"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/3370/thumb/5ZOu7brX_400x400.jpg?1612437252"), +}; + +pub static RADICLE_42161_12155E49: TokenInfo = TokenInfo { + name: "Radicle", + symbol: "RAD", + decimals: 18, + contract: address!("0x3c45038f4807c5bb72F6BC72c2A2B9c012155e49"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14013/thumb/radicle.png?1614402918"), +}; + +pub static RAI_REFLEX_INDEX_42161_78D419F2: TokenInfo = TokenInfo { + name: "Rai Reflex Index", + symbol: "RAI", + decimals: 18, + contract: address!("0xaeF5bbcbFa438519a5ea80B4c7181B4E78d419f2"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334"), +}; + +pub static RARIBLE_42161_63C1B8E0: TokenInfo = TokenInfo { + name: "Rarible", + symbol: "RARI", + decimals: 18, + contract: address!("0xCf78572A8fE97b2B9a4B9709f6a7D9a863c1b8E0"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11845/thumb/Rari.png?1594946953"), +}; + +pub static RUBIC_42161_5CBC335F: TokenInfo = TokenInfo { + name: "Rubic", + symbol: "RBC", + decimals: 18, + contract: address!("0x2E9AE8f178d5Ea81970C7799A377B3985cbC335F"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12629/thumb/200x200.png?1607952509"), +}; + +pub static REPUBLIC_TOKEN_42161_1C79A204: TokenInfo = TokenInfo { + name: "Republic Token", + symbol: "REN", + decimals: 18, + contract: address!("0x9fA891e1dB0a6D1eEAC4B929b5AAE1011C79a204"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x408e41876cCCDC0F92210600ef50372656052a38/logo.png"), +}; + +pub static REQUEST_42161_8BB92171: TokenInfo = TokenInfo { + name: "Request", + symbol: "REQ", + decimals: 18, + contract: address!("0x1Cb5bBc64e148C5b889E3c667B49edF78BB92171"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/1031/thumb/Request_icon_green.png?1643250951"), +}; + +pub static RARI_GOVERNANCE_TOKEN_42161_CD794794: TokenInfo = TokenInfo { + name: "Rari Governance Token", + symbol: "RGT", + decimals: 18, + contract: address!("0xef888bcA6AB6B1d26dbeC977C455388ecd794794"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12900/thumb/Rari_Logo_Transparent.png?1613978014"), +}; + +pub static IEXEC_RLC_42161_5D794E66: TokenInfo = TokenInfo { + name: "iExec RLC", + symbol: "RLC", + decimals: 9, + contract: address!("0xE575586566b02A16338c199c23cA6d295D794e66"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1604543202"), +}; + +pub static RENDER_TOKEN_42161_6F21E279: TokenInfo = TokenInfo { + name: "Render Token", + symbol: "RNDR", + decimals: 18, + contract: address!("0xC8a4EeA31E9B6b61c406DF013DD4FEc76f21E279"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11636/thumb/rndr.png?1638840934"), +}; + +pub static ROCKET_POOL_PROTOCOL_42161_1D0CC507: TokenInfo = TokenInfo { + name: "Rocket Pool Protocol", + symbol: "RPL", + decimals: 18, + contract: address!("0xB766039cc6DB368759C1E56B79AFfE831d0Cc507"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/2090/large/rocket_pool_%28RPL%29.png?1696503058"), +}; + +pub static RESERVE_RIGHTS_42161_DBD2E594: TokenInfo = TokenInfo { + name: "Reserve Rights", + symbol: "RSR", + decimals: 18, + contract: address!("0xCa5Ca9083702c56b481D1eec86F1776FDbd2e594"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/8365/large/RSR_Blue_Circle_1000.png?1721777856"), +}; + +pub static THE_SANDBOX_42161_D64E3DAC: TokenInfo = TokenInfo { + name: "The Sandbox", + symbol: "SAND", + decimals: 18, + contract: address!("0xd1318eb19DBF2647743c720ed35174efd64e3DAC"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1597397942"), +}; + +pub static STADER_42161_92F34B63: TokenInfo = TokenInfo { + name: "Stader", + symbol: "SD", + decimals: 18, + contract: address!("0x1629c4112952a7a377cB9B8d7d8c903092f34B63"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/20658/standard/SD_Token_Logo.png"), +}; + +pub static SHIBA_INU_42161_E3872FD1: TokenInfo = TokenInfo { + name: "Shiba Inu", + symbol: "SHIB", + decimals: 18, + contract: address!("0x5033833c9fe8B9d3E09EEd2f73d2aaF7E3872fd1"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11939/thumb/shiba.png?1622619446"), +}; + +pub static SKALE_42161_37267878: TokenInfo = TokenInfo { + name: "SKALE", + symbol: "SKL", + decimals: 18, + contract: address!("0x4F9b7DEDD8865871dF65c5D26B1c2dD537267878"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/13245/thumb/SKALE_token_300x300.png?1606789574"), +}; + +pub static STATUS_42161_A6415160: TokenInfo = TokenInfo { + name: "Status", + symbol: "SNT", + decimals: 18, + contract: address!("0x707F635951193dDaFBB40971a0fCAAb8A6415160"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/779/thumb/status.png?1548610778"), +}; + +pub static SYNTHETIX_NETWORK_TOKEN_42161_BCA37D60: TokenInfo = TokenInfo { + name: "Synthetix Network Token", + symbol: "SNX", + decimals: 18, + contract: address!("0xcBA56Cd8216FCBBF3fA6DF6137F3147cBcA37D60"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), +}; + +pub static UNISOCKS_42161_A3B264E7: TokenInfo = TokenInfo { + name: "Unisocks", + symbol: "SOCKS", + decimals: 18, + contract: address!("0xb2BE52744a804Cc732d606817C2572C5A3B264e7"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/10717/thumb/qFrcoiM.png?1582525244"), +}; + +pub static SOL_WORMHOLE_42161_EC617124: TokenInfo = TokenInfo { + name: "SOL Wormhole ", + symbol: "SOL", + decimals: 9, + contract: address!("0xb74Da9FE2F96B9E0a5f4A3cf0b92dd2bEC617124"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), +}; + +pub static SPELL_TOKEN_42161_FE15D2AF: TokenInfo = TokenInfo { + name: "Spell Token", + symbol: "SPELL", + decimals: 18, + contract: address!("0x3E6648C5a70A150A88bCE65F4aD4d506Fe15d2AF"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862"), +}; + +pub static SPX6900_42161_5D2BA901: TokenInfo = TokenInfo { + name: "SPX6900", + symbol: "SPX", + decimals: 8, + contract: address!("0x53e70cc1d527b524A1C46Eaa892e4CB35d2ba901"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/31401/large/sticker_(1).jpg?1702371083"), +}; + +pub static SQD: TokenInfo = TokenInfo { + name: "SQD", + symbol: "SQD", + decimals: 18, + contract: address!("0x1337420dED5ADb9980CFc35f8f2B054ea86f8aB1"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/37869/standard/New_Logo_SQD_Icon.png?1720048443"), +}; + +pub static STARGATE_FINANCE_42161_A16313EC: TokenInfo = TokenInfo { + name: "Stargate Finance", + symbol: "STG", + decimals: 18, + contract: address!("0xe018C7a3d175Fb0fE15D70Da2c874d3CA16313EC"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518"), +}; + +pub static STORJ_TOKEN_42161_7AA2FCC2: TokenInfo = TokenInfo { + name: "Storj Token", + symbol: "STORJ", + decimals: 8, + contract: address!("0xE6320ebF209971b4F4696F7f0954b8457Aa2FCC2"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC/logo.png"), +}; + +pub static SUPERFARM_42161_26498956: TokenInfo = TokenInfo { + name: "SuperFarm", + symbol: "SUPER", + decimals: 18, + contract: address!("0x7f9cf5a2630a0d58567122217dF7609c26498956"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14040/thumb/6YPdWn6.png?1613975899"), +}; + +pub static SYNTH_SUSD_42161_9D112F95: TokenInfo = TokenInfo { + name: "Synth sUSD", + symbol: "sUSD", + decimals: 18, + contract: address!("0xA970AF1a584579B618be4d69aD6F73459D112F95"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/5013/thumb/sUSD.png?1616150765"), +}; + +pub static SUSHI_42161_0D85C61A: TokenInfo = TokenInfo { + name: "Sushi", + symbol: "SUSHI", + decimals: 18, + contract: address!("0xd4d42F0b6DEF4CE0383636770eF773390d85c61A"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), +}; + +pub static SWELL_42161_A58F2571: TokenInfo = TokenInfo { + name: "Swell", + symbol: "SWELL", + decimals: 18, + contract: address!("0x2C96bE2612bec20fe2975C3ACFcbBe61a58f2571"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/28777/large/swell1.png?1727899715"), +}; + +pub static SYNAPSE_42161_375EAD84: TokenInfo = TokenInfo { + name: "Synapse", + symbol: "SYN", + decimals: 18, + contract: address!("0x1bCfc0B4eE1471674cd6A9F6B363A034375eAD84"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049"), +}; + +pub static THRESHOLD_NETWORK_42161_DEC21F55: TokenInfo = TokenInfo { + name: "Threshold Network", + symbol: "T", + decimals: 18, + contract: address!("0x0945Cae3ae47cb384b2d47BC448Dc6A9dEC21F55"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/22228/thumb/nFPNiSbL_400x400.jpg?1641220340"), +}; + +pub static TBTC_42161_0A572594: TokenInfo = TokenInfo { + name: "tBTC", + symbol: "tBTC", + decimals: 18, + contract: address!("0x7E2a1eDeE171C5B19E6c54D73752396C0A572594"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/uniswap/assets/master/blockchains/ethereum/assets/0x18084fbA666a33d37592fA2633fD49a74DD93a88/logo.png"), +}; + +pub static TELLOR_42161_10D88242: TokenInfo = TokenInfo { + name: "Tellor", + symbol: "TRB", + decimals: 18, + contract: address!("0xd58D345Fd9c82262E087d2D0607624B410D88242"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/9644/thumb/Blk_icon_current.png?1584980686"), +}; + +pub static TRIBE_42161_03914A5A: TokenInfo = TokenInfo { + name: "Tribe", + symbol: "TRIBE", + decimals: 18, + contract: address!("0xBfAE6fecD8124ba33cbB2180aAb0Fe4c03914A5A"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/14575/thumb/tribe.PNG?1617487954"), +}; + +pub static TURBO_42161_EDE4576A: TokenInfo = TokenInfo { + name: "Turbo", + symbol: "TURBO", + decimals: 18, + contract: address!("0x5C816d4582c857dcadb1bB1F62Ad6c9DEde4576a"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/30117/large/TurboMark-QL_200.png?1708079597"), +}; + +pub static UMA_VOTING_TOKEN_V1_42161_9B0C3B22: TokenInfo = TokenInfo { + name: "UMA Voting Token v1", + symbol: "UMA", + decimals: 18, + contract: address!("0xd693Ec944A85eeca4247eC1c3b130DCa9B0C3b22"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), +}; + +pub static UNISWAP_42161_72F1F7F0: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0"), + chain: 42161, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static WORLD_LIBERTY_FINANCIAL_USD_42161_DD217A33: TokenInfo = TokenInfo { + name: "World Liberty Financial USD", + symbol: "USD1", + decimals: 18, + contract: address!("0x7550dE0A4b9Fb8CAbA8c32E72Ee356AFdd217A33"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/54977/large/USD1_1000x1000_transparent.png?1749297002"), +}; + +pub static USDCOIN_42161_268E5831: TokenInfo = TokenInfo { + name: "USDCoin", + symbol: "USDC", + decimals: 6, + contract: address!("0xaf88d065e77c8cC2239327C5EDb3A432268e5831"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), +}; + +pub static BRIDGED_USDC_42161_BDDB5CC8: TokenInfo = TokenInfo { + name: "Bridged USDC", + symbol: "USDC.e", + decimals: 6, + contract: address!("0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), +}; + +pub static PAX_DOLLAR_42161_B699DF8F: TokenInfo = TokenInfo { + name: "Pax Dollar", + symbol: "USDP", + decimals: 18, + contract: address!("0x78df3a6044Ce3cB1905500345B967788b699dF8f"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/6013/standard/Pax_Dollar.png?1696506427"), +}; + +pub static USDS_STABLECOIN_42161_749B876B: TokenInfo = TokenInfo { + name: "USDS Stablecoin", + symbol: "USDS", + decimals: 18, + contract: address!("0x6491c05A82219b8D1479057361ff1654749b876b"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/39926/large/usds.webp?1726666683"), +}; + +pub static USUAL_42161_2140ABBB: TokenInfo = TokenInfo { + name: "USUAL", + symbol: "USUAL", + decimals: 18, + contract: address!("0x7639AB8599f1b417CbE4ceD492fB30162140AbbB"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/51091/large/USUAL.jpg?1730035787"), +}; + +pub static WRAPPED_AMPLEFORTH_42161_8AE650BB: TokenInfo = TokenInfo { + name: "Wrapped Ampleforth", + symbol: "WAMPL", + decimals: 18, + contract: address!("0x1c8Ec4DE3c2BFD3050695D89853EC6d78AE650bb"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/20825/thumb/photo_2021-11-25_02-05-11.jpg?1637811951"), +}; + +pub static WRAPPED_BTC_42161_AEFC5B0F: TokenInfo = TokenInfo { + name: "Wrapped BTC", + symbol: "WBTC", + decimals: 8, + contract: address!("0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), +}; + +pub static WRAPPED_ETHER_42161_523FBAB1: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static WORLD_LIBERTY_FINANCIAL_42161_0E1980BF: TokenInfo = TokenInfo { + name: "World Liberty Financial", + symbol: "WLFI", + decimals: 18, + contract: address!("0x4D1d7134B87490AE5eEbdB22A5820d7d0E1980bf"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/50767/large/wlfi.png?1756438915"), +}; + +pub static WOO_NETWORK_42161_3AEFD07B: TokenInfo = TokenInfo { + name: "WOO Network", + symbol: "WOO", + decimals: 18, + contract: address!("0xcAFcD85D8ca7Ad1e1C6F82F651fA15E33AEfD07b"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), +}; + +pub static TETHER_GOLD_42161_CFC6C9D3: TokenInfo = TokenInfo { + name: "Tether Gold", + symbol: "XAUT", + decimals: 6, + contract: address!("0x9B86f3c7d145979ec6b2F42eD7f92D06cfC6C9d3"), + chain: 42161, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/10481/large/Tether_Gold.png?1696510471"), +}; + +pub static CHAIN_42161_4DEEAFED: TokenInfo = TokenInfo { + name: "Chain", + symbol: "XCN", + decimals: 18, + contract: address!("0x58BbC087e36Db40a84b22c1B93a042294deEAFEd"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/24210/thumb/Chain_icon_200x200.png?1646895054"), +}; + +pub static XSGD_42161_4C1C4302: TokenInfo = TokenInfo { + name: "XSGD", + symbol: "XSGD", + decimals: 6, + contract: address!("0xa05245Ade25cC1063EE50Cf7c083B4524c1C4302"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/12832/standard/StraitsX_Singapore_Dollar_%28XSGD%29_Token_Logo.png?1696512623"), +}; + +pub static YEARN_FINANCE_42161_085B1582: TokenInfo = TokenInfo { + name: "yearn finance", + symbol: "YFI", + decimals: 18, + contract: address!("0x82e3A8F066a6989666b031d916c43672085b1582"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), +}; + +pub static ZETACHAIN_42161_47B88954: TokenInfo = TokenInfo { + name: "Zetachain", + symbol: "Zeta", + decimals: 18, + contract: address!("0x6DdBbcE7858D276678FC2B36123fD60547b88954"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/26718/standard/Twitter_icon.png?1696525788"), +}; + +pub static LAYERZERO_42161_F13271CD: TokenInfo = TokenInfo { + name: "LayerZero", + symbol: "ZRO", + decimals: 18, + contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), + chain: 42161, + logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), +}; + +pub static TOKEN_0X_PROTOCOL_TOKEN_42161_19235AE2: TokenInfo = TokenInfo { + name: "0x Protocol Token", + symbol: "ZRX", + decimals: 18, + contract: address!("0xBD591Bd4DdB64b77B5f76Eab8f03d02519235Ae2"), + chain: 42161, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), +}; + +pub static WRAPPED_BITCOIN: TokenInfo = TokenInfo { + name: "Wrapped Bitcoin", + symbol: "BTC", + decimals: 18, + contract: address!("0xD629eb00dEced2a080B7EC630eF6aC117e614f1b"), + chain: 42220, + logo_uri: Some("https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_WBTC.png"), +}; + +pub static CELO: TokenInfo = TokenInfo { + name: "Celo", + symbol: "CELO", + decimals: 18, + contract: address!("0x471EcE3750Da237f93B8E339c536989b8978a438"), + chain: 42220, + logo_uri: Some("https://raw.githubusercontent.com/ubeswap/default-token-list/master/assets/asset_CELO.png"), +}; + +pub static USDCOIN_42220_8B32118C: TokenInfo = TokenInfo { + name: "USDCoin", + symbol: "USDC", + decimals: 6, + contract: address!("0xcebA9300f2b948710d2653dD7B07f33A8B32118C"), + chain: 42220, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"), +}; + +pub static TETHER_USD_42220_87483D5E: TokenInfo = TokenInfo { + name: "Tether USD", + symbol: "USDT", + decimals: 6, + contract: address!("0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e"), + chain: 42220, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), +}; + +pub static WRAPPED_ETHER_42220_622F4361: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0x2DEf4285787d58a2f811AF24755A8150622f4361"), + chain: 42220, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static TOKEN_1INCH_43114_8B28F267: TokenInfo = TokenInfo { + name: "1inch", + symbol: "1INCH", + decimals: 18, + contract: address!("0xd501281565bf7789224523144Fe5D98e8B28f267"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028"), +}; + +pub static AAVE_43114_E5D386D9: TokenInfo = TokenInfo { + name: "Aave", + symbol: "AAVE", + decimals: 18, + contract: address!("0x63a72806098Bd3D9520cC43356dD78afe5D386D9"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/12645/thumb/AAVE.png?1601374110"), +}; + +pub static AGEUR_43114_F1F96C57: TokenInfo = TokenInfo { + name: "agEur", + symbol: "agEUR", + decimals: 18, + contract: address!("0xAEC8318a9a59bAEb39861d10ff6C7f7bf1F96C57"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/19479/standard/agEUR.png?1696518915"), +}; + +pub static ALPHA_VENTURE_DAO_43114_7A8E208F: TokenInfo = TokenInfo { + name: "Alpha Venture DAO", + symbol: "ALPHA", + decimals: 18, + contract: address!("0x2147EFFF675e4A4eE1C2f918d181cDBd7a8E208f"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/12738/thumb/AlphaToken_256x256.png?1617160876"), +}; + +pub static ANKR_43114_2C84B4DE: TokenInfo = TokenInfo { + name: "Ankr", + symbol: "ANKR", + decimals: 18, + contract: address!("0x20CF1b6E9d856321ed4686877CF4538F2C84B4dE"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1608111978"), +}; + +pub static AXELAR_43114_CE194C5D: TokenInfo = TokenInfo { + name: "Axelar", + symbol: "AXL", + decimals: 6, + contract: address!("0x44c784266cf024a60e8acF2427b9857Ace194C5d"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/27277/large/V-65_xQ1_400x400.jpeg"), +}; + +pub static BASIC_ATTENTION_TOKEN_43114_A4690588: TokenInfo = TokenInfo { + name: "Basic Attention Token", + symbol: "BAT", + decimals: 18, + contract: address!("0x98443B96EA4b0858FDF3219Cd13e98C7A4690588"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1547034427"), +}; + +pub static BINANCE_USD_43114_39D2DB39: TokenInfo = TokenInfo { + name: "Binance USD", + symbol: "BUSD", + decimals: 18, + contract: address!("0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/9576/thumb/BUSD.png?1568947766"), +}; + +pub static COMPOUND_43114_906E2437: TokenInfo = TokenInfo { + name: "Compound", + symbol: "COMP", + decimals: 18, + contract: address!("0xc3048E19E76CB9a3Aa9d77D8C03c29Fc906e2437"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xc00e94Cb662C3520282E6f5717214004A7f26888/logo.png"), +}; + +pub static CARTESI_43114_0FABF552: TokenInfo = TokenInfo { + name: "Cartesi", + symbol: "CTSI", + decimals: 18, + contract: address!("0x6b289CCeAA8639e3831095D75A3e43520faBf552"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/11038/thumb/cartesi.png?1592288021"), +}; + +pub static DAI_E_TOKEN: TokenInfo = TokenInfo { + name: "DAI.e Token", + symbol: "DAI.e", + decimals: 18, + contract: address!("0xd586E7F844cEa2F87f50152665BCbc2C279D8d70"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/avalanchec/assets/0xd586E7F844cEa2F87f50152665BCbc2C279D8d70/logo.png"), +}; + +pub static DEFI_YIELD_PROTOCOL_43114_91BCEF17: TokenInfo = TokenInfo { + name: "DeFi Yield Protocol", + symbol: "DYP", + decimals: 18, + contract: address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/13480/thumb/DYP_Logo_Symbol-8.png?1655809066"), +}; + +pub static EURO_COIN_43114_505C2ACD: TokenInfo = TokenInfo { + name: "Euro Coin", + symbol: "EURC", + decimals: 6, + contract: address!("0xC891EB4cbdEFf6e073e859e987815Ed1505c2ACD"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/26045/standard/euro.png?1696525125"), +}; + +pub static FLUX_43114_C20DAF55: TokenInfo = TokenInfo { + name: "Flux", + symbol: "FLUX", + decimals: 8, + contract: address!("0xc4B06F17ECcB2215a5DBf042C672101Fc20daF55"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x720CD16b011b987Da3518fbf38c3071d4F0D1495/logo.png"), +}; + +pub static FRAX_43114_21A1DA64: TokenInfo = TokenInfo { + name: "Frax", + symbol: "FRAX", + decimals: 18, + contract: address!("0xD24C2Ad096400B6FBcd2ad8B24E7acBc21A1da64"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/13422/thumb/frax_logo.png?1608476506"), +}; + +pub static FRAX_SHARE_43114_3FC8E387: TokenInfo = TokenInfo { + name: "Frax Share", + symbol: "FXS", + decimals: 18, + contract: address!("0x214DB107654fF987AD859F34125307783fC8e387"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/13423/thumb/frax_share.png?1608478989"), +}; + +pub static GMX_43114_5011C661: TokenInfo = TokenInfo { + name: "GMX", + symbol: "GMX", + decimals: 18, + contract: address!("0x62edc0692BD897D2295872a9FFCac5425011c661"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/18323/large/arbit.png?1631532468"), +}; + +pub static THE_GRAPH_43114_69E85CB9: TokenInfo = TokenInfo { + name: "The Graph", + symbol: "GRT", + decimals: 18, + contract: address!("0x8a0cAc13c7da965a312f08ea4229c37869e85cB9"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/13397/thumb/Graph_Token.png?1608145566"), +}; + +pub static GUNZ: TokenInfo = TokenInfo { + name: "GUNZ", + symbol: "GUN", + decimals: 18, + contract: address!("0x26deBD39D5eD069770406FCa10A0E4f8d2c743eB"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/55027/standard/gunz.jpg?1743262298"), +}; + +pub static CHAINLINK_TOKEN_43114_413227A3: TokenInfo = TokenInfo { + name: "ChainLink Token", + symbol: "LINK", + decimals: 18, + contract: address!("0x5947BB275c521040051D82396192181b413227A3"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"), +}; + +pub static MAGIC_INTERNET_MONEY_43114_8CB8C18D: TokenInfo = TokenInfo { + name: "Magic Internet Money", + symbol: "MIM", + decimals: 18, + contract: address!("0x130966628846BFd36ff31a822705796e8cb8C18D"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/16786/thumb/mimlogopng.png?1624979612"), +}; + +pub static MAKER_43114_AAB72D42: TokenInfo = TokenInfo { + name: "Maker", + symbol: "MKR", + decimals: 18, + contract: address!("0x88128fd4b259552A9A1D457f435a6527AAb72d42"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2/logo.png"), +}; + +pub static MULTICHAIN_43114_3C8764E3: TokenInfo = TokenInfo { + name: "Multichain", + symbol: "MULTI", + decimals: 18, + contract: address!("0x9Fb9a33956351cf4fa040f65A13b835A3C8764E3"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/22087/thumb/1_Wyot-SDGZuxbjdkaOeT2-A.png?1640764238"), +}; + +pub static PENDLE_43114_62EA213B: TokenInfo = TokenInfo { + name: "Pendle", + symbol: "PENDLE", + decimals: 18, + contract: address!("0xfB98B335551a418cD0737375a2ea0ded62Ea213b"), + chain: 43114, + logo_uri: Some("https://coin-images.coingecko.com/coins/images/15069/large/Pendle_Logo_Normal-03.png?1696514728"), +}; + +pub static RAI_REFLEX_INDEX_43114_031BFF7D: TokenInfo = TokenInfo { + name: "Rai Reflex Index", + symbol: "RAI", + decimals: 18, + contract: address!("0x97Cd1CFE2ed5712660bb6c14053C0EcB031Bff7d"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/14004/thumb/RAI-logo-coin.png?1613592334"), +}; + +pub static SYNTHETIX_NETWORK_TOKEN_43114_BA4B209B: TokenInfo = TokenInfo { + name: "Synthetix Network Token", + symbol: "SNX", + decimals: 18, + contract: address!("0xBeC243C995409E6520D7C41E404da5dEba4b209B"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F/logo.png"), +}; + +pub static SOL_WORMHOLE_43114_06D2478F: TokenInfo = TokenInfo { + name: "SOL Wormhole ", + symbol: "SOL", + decimals: 9, + contract: address!("0xFE6B19286885a4F7F55AdAD09C3Cd1f906D2478F"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/22876/thumb/SOL_wh_small.png?1644224316"), +}; + +pub static SPELL_TOKEN_43114_1A2F7814: TokenInfo = TokenInfo { + name: "Spell Token", + symbol: "SPELL", + decimals: 18, + contract: address!("0xCE1bFFBD5374Dac86a2893119683F4911a2F7814"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/15861/thumb/abracadabra-3.png?1622544862"), +}; + +pub static STARGATE_FINANCE_43114_F56E7590: TokenInfo = TokenInfo { + name: "Stargate Finance", + symbol: "STG", + decimals: 18, + contract: address!("0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/24413/thumb/STG_LOGO.png?1647654518"), +}; + +pub static SUSHI_43114_722E4F76: TokenInfo = TokenInfo { + name: "Sushi", + symbol: "SUSHI", + decimals: 18, + contract: address!("0x37B608519F91f70F2EeB0e5Ed9AF4061722e4F76"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/12271/thumb/512x512_Logo_no_chop.png?1606986688"), +}; + +pub static SYNAPSE_43114_E09CA251: TokenInfo = TokenInfo { + name: "Synapse", + symbol: "SYN", + decimals: 18, + contract: address!("0x1f1E7c893855525b303f99bDF5c3c05Be09ca251"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/18024/thumb/syn.png?1635002049"), +}; + +pub static UMA_VOTING_TOKEN_V1_43114_0A5B2339: TokenInfo = TokenInfo { + name: "UMA Voting Token v1", + symbol: "UMA", + decimals: 18, + contract: address!("0x3Bd2B1c7ED8D396dbb98DED3aEbb41350a5b2339"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828/logo.png"), +}; + +pub static UNI_E_TOKEN: TokenInfo = TokenInfo { + name: "UNI.e Token", + symbol: "UNI.e", + decimals: 18, + contract: address!("0x8eBAf22B6F053dFFeaf46f4Dd9eFA95D89ba8580"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/avalanchec/assets/0x8eBAf22B6F053dFFeaf46f4Dd9eFA95D89ba8580/logo.png"), +}; + +pub static USDC_TOKEN: TokenInfo = TokenInfo { + name: "USDC Token", + symbol: "USDC", + decimals: 6, + contract: address!("0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/avalanchec/assets/0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E/logo.png"), +}; + +pub static TETHER_USD_43114_4DF4A8C7: TokenInfo = TokenInfo { + name: "Tether USD", + symbol: "USDT", + decimals: 6, + contract: address!("0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"), +}; + +pub static WRAPPED_AVAX: TokenInfo = TokenInfo { + name: "Wrapped AVAX", + symbol: "WAVAX", + decimals: 18, + contract: address!("0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/avalanchec/assets/0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7/logo.png"), +}; + +pub static WRAPPED_BTC_43114_5187B218: TokenInfo = TokenInfo { + name: "Wrapped BTC", + symbol: "WBTC", + decimals: 8, + contract: address!("0x50b7545627a5162F82A992c33b87aDc75187B218"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599/logo.png"), +}; + +pub static WRAPPED_ETHER_43114_6BC10BAB: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static WOO_NETWORK_43114_5F58D083: TokenInfo = TokenInfo { + name: "WOO Network", + symbol: "WOO", + decimals: 18, + contract: address!("0xaBC9547B534519fF73921b1FBA6E672b5f58D083"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/12921/thumb/w2UiemF__400x400.jpg?1603670367"), +}; + +pub static YEARN_FINANCE_43114_922F52DC: TokenInfo = TokenInfo { + name: "yearn finance", + symbol: "YFI", + decimals: 18, + contract: address!("0x9eAaC1B23d935365bD7b542Fe22cEEe2922f52dc"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/11849/thumb/yfi-192x192.png?1598325330"), +}; + +pub static LAYERZERO_43114_F13271CD: TokenInfo = TokenInfo { + name: "LayerZero", + symbol: "ZRO", + decimals: 18, + contract: address!("0x6985884C4392D348587B19cb9eAAf157F13271cd"), + chain: 43114, + logo_uri: Some("https://assets.coingecko.com/coins/images/28206/standard/ftxG9_TJ_400x400.jpeg?1696527208"), +}; + +pub static TOKEN_0X_PROTOCOL_TOKEN_43114_75CDE0D2: TokenInfo = TokenInfo { + name: "0x Protocol Token", + symbol: "ZRX", + decimals: 18, + contract: address!("0x596fA47043f99A4e0F122243B841E55375cdE0d2"), + chain: 43114, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xE41d2489571d322189246DaFA5ebDe1F4699F498/logo.png"), +}; + +pub static WRAPPED_ETHER_80001_C5D1C0AA: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa"), + chain: 80001, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static WRAPPED_MATIC_80001_FB032889: TokenInfo = TokenInfo { + name: "Wrapped Matic", + symbol: "WMATIC", + decimals: 18, + contract: address!("0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889"), + chain: 80001, + logo_uri: Some("https://assets.coingecko.com/coins/images/4713/thumb/matic-token-icon.png?1624446912"), +}; + +pub static BLAST: TokenInfo = TokenInfo { + name: "Blast", + symbol: "BLAST", + decimals: 18, + contract: address!("0xb1a5700fA2358173Fe465e6eA4Ff52E36e88E2ad"), + chain: 81457, + logo_uri: Some("https://assets.coingecko.com/coins/images/35494/standard/Blast.jpg?1719385662"), +}; + +pub static USD_COIN_BRIDGED_FROM_ETHEREUM: TokenInfo = TokenInfo { + name: "USD Coin (Bridged from Ethereum)", + symbol: "USDzC", + decimals: 6, + contract: address!("0xCccCCccc7021b32EBb4e8C08314bD62F7c653EC4"), + chain: 7777777, + logo_uri: Some("https://assets.coingecko.com/coins/images/35218/large/USDC_Icon.png?1707908537"), +}; + +pub static UNISWAP_11155111_4201F984: TokenInfo = TokenInfo { + name: "Uniswap", + symbol: "UNI", + decimals: 18, + contract: address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"), + chain: 11155111, + logo_uri: Some("ipfs://QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg"), +}; + +pub static WRAPPED_ETHER_11155111_324D6B14: TokenInfo = TokenInfo { + name: "Wrapped Ether", + symbol: "WETH", + decimals: 18, + contract: address!("0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"), + chain: 11155111, + logo_uri: Some("https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"), +}; + +pub static TOKENS: &[&TokenInfo] = &[ + &TOKEN_1INCH, + &ANCIENT8, + &AAVE, + &ARCBLOCK, + &ALCHEMY_PAY, + &ACROSS_PROTOCOL_TOKEN, + &AMBIRE_ADEX, + &AERGO, + &AEVO, + &AGEUR, + &ADVENTURE_GOLD, + &AIOZ_NETWORK, + &ALCHEMIX, + &ALEPH_IM, + &ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE, + &MY_NEIGHBOR_ALICE, + &ALLORA, + &ALPHA_VENTURE_DAO, + &ALTLAYER, + &, + &ANKR, + &ARAGON, + &APECOIN, + &API3, + &APRIORI, + &APU_APUSTAJA, + &ARBITRUM, + &ARKHAM, + &ARPA_CHAIN, + &ASH, + &ASSEMBLE_PROTOCOL, + &AIRSWAP, + &AUTOMATA, + &AETHIR_TOKEN, + &BOUNCE, + &AUDD, + &AUDIUS, + &ARTVERSE_TOKEN, + &AXELAR, + &AXIE_INFINITY, + &AZTEC, + &BADGER_DAO, + &BALANCER, + &BAND_PROTOCOL, + &LOMBARD, + &BASIC_ATTENTION_TOKEN, + &BEAM, + &BICONOMY, + &BIG_TIME, + &BIO, + &BITDAO, + &HARRYPOTTEROBAMASONIC10INU, + &BLUR, + &BLUZELLE, + &BANCOR_NETWORK_TOKEN, + &BOBA_NETWORK, + &BOB, + &BARNBRIDGE, + &BREVIS, + &BRAINTRUST, + &BINANCE_USD, + &COIN98, + &PANCAKESWAP, + &COINBASE_WRAPPED_BTC, + &COINBASE_WRAPPED_STAKED_ETH, + &CELO_NATIVE_ASSET_WORMHOLE, + &CELER_NETWORK, + &CENTRIFUGE, + &CHROMIA, + &CHILIZ, + &CLOVER_FINANCE, + &COMPOUND, + &CORN, + &COTI, + &CIRCUITS_OF_VALUE, + &COW_PROTOCOL, + &CLEARPOOL, + &COVALENT, + &CRONOS, + &CRYPTERIUM, + &CURVE_DAO_TOKEN, + &CARTESI, + &CRYPTEX_FINANCE, + &SOMNIUM_SPACE_CUBES, + &CIVIC, + &CONVEX_FINANCE, + &COVALENT_X_TOKEN, + &DAI_STABLECOIN, + &MINES_OF_DALARNIA, + &DERIVADAO, + &DENT, + &DEXTOOLS, + &DIA, + &DISTRICT0X, + &DOLOMITE, + &DOVU, + &DEFI_PULSE_INDEX, + &DREP, + &DERIVE, + &DYDX, + &DEFI_YIELD_PROTOCOL, + &EIGENLAYER, + &ELASTOS, + &DOGELON_MARS, + ÐENA, + &ENJIN_COIN, + ÐEREUM_NAME_SERVICE, + &CALDERA, + ÐERNITY_CHAIN, + &ESPRESSO, + ÐER_FI, + &EULER, + &EURO_COIN, + &SCHUMAN_EUR_P, + &QUANTOZ_EURQ, + &STABLR_EURO, + &HARVEST_FINANCE, + &FETCH_AI, + &FIDELITY_DIGITAL_DOLLAR, + &STAFI, + &FLOKI, + &FLUX, + &FORTA, + &LEFORTH_GOVERNANCE_TOKEN, + &SHAPESHIFT_FOX_TOKEN, + &FRAX, + &FANTOM, + &FUNCTION_X, + &FRAX_SHARE, + &GRAVITY, + &GALXE, + &GALA, + &GOLDFINCH, + &AAVEGOTCHI, + &GOLEM, + &GNOSIS_TOKEN, + &GODS_UNCHAINED, + &THE_GRAPH, + &GITCOIN, + &GEMINI_DOLLAR, + ÐGAS, + &GYEN, + &HASHFLOW, + &HIGHSTREET, + &HOPR, + &IDEX, + &ILLUVIUM, + &IMMUNEFI, + &IMMUTABLE_X, + &INDEX_COOPERATIVE, + &INJECTIVE, + &INVERSE_FINANCE, + &INFINEX, + &IOTEX, + &IRYS, + &GEOJAM, + &JASMYCOIN, + &JUPITER, + &KEEP_NETWORK, + &KERNELDAO, + &SELFKEY, + &KITE, + &KYBER_NETWORK_CRYSTAL, + &KEEP3RV1, + &KRYLL, + &KUJIRA, + &LAYER3, + &LAGRANGE, + &LCX, + &LIDO_DAO, + &LINEA, + &CHAINLINK_TOKEN, + &LITENTRY, + &LIGHTER, + &LEAGUE_OF_KINGDOMS, + &LOOM_NETWORK, + &LIVEPEER, + &LIQUITY, + &LOOPRINGCOIN_V2, + &BLOCKLORDS, + &LIQUID_STAKED_ETH, + &LISK, + &LIQUITY_USD, + &DECENTRALAND, + &MASK_NETWORK, + &MATH, + &POLYGON, + &MERIT_CIRCLE, + &MOSS_CARBON_CREDIT, + &MEASURABLE_DATA_TOKEN, + &MEMECOIN, + &METIS, + &MAGIC_INTERNET_MONEY, + &MIRROR_PROTOCOL, + &MAKER, + &MELON, + &MANTLE, + &MOG_COIN, + &MONAVALE, + &MORPHO_TOKEN, + &MOVEMENT, + &MAPLE, + &METAL, + &MULTICHAIN, + &MSTABLE_USD, + &MUSE_DAO, + &GENSOKISHI_METAVERSE, + &MXC, + &POLYSWARM, + &NEIRO, + &NEWTON, + &NKN, + &NUMERAIRE, + &NOMINA, + &NUCYPHER, + &OCEAN_PROTOCOL, + &ORIGIN_PROTOCOL, + &OMG_NETWORK, + &OMNI_NETWORK, + &ONDO_FINANCE, + &ORCA_ALLIANCE, + &ORION_PROTOCOL, + &ORCHID, + &PAYPEREX, + &PAX_GOLD, + &PLAYDAPP, + &PENDLE, + &PEPE, + &PERPETUAL_PROTOCOL, + &PIRATE_NATION, + &PLUTON, + &PLUME, + &POLYGON_ECOSYSTEM_TOKEN, + &POLKASTARTER, + &POLYMATH, + &MARLIN, + &PORTAL, + &POWER_LEDGER, + &PRIME, + &PROPY, + &SUCCINCT, + &PARSIQ, + &PSTAKE_FINANCE, + &PUFFER_FINANCE, + &PAYPAL_USD, + &QUANT, + &QREDO, + &QUANTSTAMP, + &QUICKSWAP, + &RADICLE, + &RAI_REFLEX_INDEX, + &SUPERRARE, + &RARIBLE, + &RUBIC, + &RIBBON_FINANCE, + &REDSTONE, + &REPUBLIC_TOKEN, + &REPUTATION_AUGUR_V1, + &REPUTATION_AUGUR_V2, + &REQUEST, + &REVV, + &RENZO, + &RARI_GOVERNANCE_TOKEN, + &IEXEC_RLC, + &RAYLS, + &RLUSD, + &RALLY, + &RENDER_TOKEN, + &ROBO_TOKEN, + &ROOK, + &ROCKET_POOL_PROTOCOL, + &RESERVE_RIGHTS, + &SAFE, + &THE_SANDBOX, + &STADER, + &SENTIENT, + &SHIBA_INU, + &SHPING, + &SKALE, + &SKY_GOVERNANCE_TOKEN, + &SMOOTH_LOVE_POTION, + &STATUS, + &SYNTHETIX_NETWORK_TOKEN, + &UNISOCKS, + &SOL_WORMHOLE, + &SPELL_TOKEN, + &SPARK, + &SPX6900, + &STARGATE_FINANCE, + &STORJ_TOKEN, + &STARKNET, + &STOX, + &SUKU, + &SUPERFARM, + &SYNTH_SUSD, + &SUSHI, + &SWELL, + &SWFTCOIN, + &SWIPE, + &SPACE_AND_TIME, + &SYLO, + &SYNAPSE, + &SYRUP_TOKEN, + &THRESHOLD_NETWORK, + &TBTC, + &TERM_FINANCE, + &THEORIQ, + &CHRONOTECH, + &ALIEN_WORLDS, + &TOKEMAK, + &TOKENFI, + &TE_FOOD, + &ORIGINTRAIL, + &TELLOR, + &TREEHOUSE_TOKEN, + &TRIA, + &TRIBE, + &TRUEFI, + &TURBO, + &THE_VIRTUA_KOLECT, + &UMA_VOTING_TOKEN_V1, + &UNIFI_PROTOCOL_DAO, + &UNISWAP, + &PAWTOCOL, + &WORLD_LIBERTY_FINANCIAL_USD, + &USDCOIN, + &GLOBAL_DOLLAR, + &PAX_DOLLAR, + &QUANTOZ_USDQ, + &STABLR_USD, + &USDS_STABLECOIN, + &TETHER_USD, + &USUAL, + &VANRY, + &VOYAGER_TOKEN, + &WRAPPED_AMPLEFORTH, + &WRAPPED_ANALOG_ONE_TOKEN, + &WRAPPED_BTC, + &WRAPPED_CENTRIFUGE, + &WALLETCONNECT_TOKEN, + &WRAPPED_ETHER, + &WORLD_LIBERTY_FINANCIAL, + &WOO_NETWORK, + &ANOMA, + &TETHER_GOLD, + &CHAIN, + &XSGD, + &XYO_NETWORK, + &YIELD_BASIS, + &YEARN_FINANCE, + &DFI_MONEY, + &YIELD_GUILD_GAMES, + &ZAMA, + &ZETACHAIN, + &BOUNDLESS, + &ZKPASS, + &LAYERZERO, + &TOKEN_0X_PROTOCOL_TOKEN, + &DAI_STABLECOIN_3_CE07538D, + &UNISWAP_3_4201F984, + &WRAPPED_ETHER_3_AA0CD5AB, + &DAI_STABLECOIN_4_A8FC4735, + &MAKER_4_359AAD85, + &UNISWAP_4_4201F984, + &WRAPPED_ETHER_4_AA0CD5AB, + &UNISWAP_5_4201F984, + &WRAPPED_ETHER_5_2B2208D6, + &TOKEN_1INCH_10_94736426, + &AAVE_10_950C9278, + &ACROSS_PROTOCOL_TOKEN_10_FDD1B76B, + &ARPA_CHAIN_10_C9BFA31E, + &BALANCER_10_E9379921, + &BICONOMY_10_C0FB1C9D, + &BOBA_NETWORK_10_CB88854D, + &BARNBRIDGE_10_3F276747, + &BRAINTRUST_10_E141254E, + &BINANCE_USD_10_39D2DB39, + &COINBASE_WRAPPED_STAKED_ETH_10_78DCF3B2, + &CELO_NATIVE_ASSET_WORMHOLE_10_B9B5C349, + &CURVE_DAO_TOKEN_10_0605FB53, + &CARTESI_10_071295BF, + &CYBER, + &DAI_STABLECOIN_10_C9000DA1, + &DERIVE_10_72BBA100, + ÐEREUM_NAME_SERVICE_10_5E890A00, + &STAFI_10_911BAD41, + &SHAPESHIFT_FOX_TOKEN_10_37CED174, + &FRAX_10_9A53F475, + &FRAX_SHARE_10_1C2205BE, + &GITCOIN_10_46445B08, + &GYEN_10_D9B6D5F7, + &KRYLL_10_C9022021, + &KUJIRA_10_5671E7CA, + &LIDO_DAO_10_2596735F, + &CHAINLINK_TOKEN_10_38FFA7F6, + &LOOPRINGCOIN_V2_10_1464907E, + &LIQUITY_USD_10_9B7B2819, + &MASK_NETWORK_10_BDF63798, + &MAKER_10_27F2FCB5, + &OCEAN_PROTOCOL_10_B8B49F9E, + &OPTIMISM, + &PENDLE_10_796E66E1, + &PEPE_10_9DDB16F5, + &PERPETUAL_PROTOCOL_10_976840E0, + &RAI_REFLEX_INDEX_10_7705448B, + &RARI_GOVERNANCE_TOKEN_10_DCEC711A, + &ROCKET_POOL_PROTOCOL_10_C14D1401, + &STATUS_10_64CFB6B2, + &SYNTHETIX_NETWORK_TOKEN_10_3D7599B4, + &SOL_WORMHOLE_10_7FA664F1, + &SUKU_10_0B9E50A4, + &SYNTH_SUSD_10_751EC8D9, + &SUSHI_10_0F60112B, + &THRESHOLD_NETWORK_10_8C734EA7, + &TELLOR_10_E3CEB888, + &UMA_VOTING_TOKEN_V1_10_855A77EA, + &UNISWAP_10_0E816691, + &USDCOIN_10_D097FF85, + &USDCOIN_BRIDGED_FROM_ETHEREUM, + &TETHER_USD_10_8CE58E58, + &VELODROME_FINANCE, + &WRAPPED_BTC_10_BF0A2095, + &WALLETCONNECT_TOKEN_10_DD927945, + &WRAPPED_ETHER_10_00000006, + &WORLDCOIN, + &WOO_NETWORK_10_51A5E527, + &XYO_NETWORK_10_DBD81FC8, + &YEARN_FINANCE_10_FEE9107B, + &LAYERZERO_10_F13271CD, + &TOKEN_0X_PROTOCOL_TOKEN_10_FA3C2F33, + &DAI_STABLECOIN_42_B64CA6AA, + &MAKER_42_71A4FFCD, + &UNISWAP_42_4201F984, + &WRAPPED_ETHER_42_C2CF029C, + &TOKEN_1INCH_56_4120C302, + &AAVE_56_7E58F802, + &ALCHEMY_PAY_56_7003056D, + &AMBIRE_ADEX_56_A7077819, + &AGEUR_56_D5FE5F89, + &AIOZ_NETWORK_56_9FC3741D, + &ALEPH_IM_56_DE9038C4, + &MY_NEIGHBOR_ALICE_56_745D63E8, + &ALPHA_VENTURE_DAO_56_13B40975, + &ANKR_56_531B08E3, + &ARPA_CHAIN_56_FA2D6F7E, + &ASTER, + &AUTOMATA_56_2F141225, + &AXELAR_56_C96F1F65, + &AXIE_INFINITY_56_D4D2F8A0, + &BLUZELLE_56_DA0ACDA2, + &BINANCE_USD_56_DD087D56, + &COIN98_56_90F1C3A6, + &CHROMIA_56_32B224FE, + &CLOVER_FINANCE_56_367A4E4D, + &COMPOUND_56_8CAD67E8, + &CIRCUITS_OF_VALUE_56_2B141464, + &CARTESI_56_2D033EF2, + &DAI_STABLECOIN_56_58B1DBC3, + &MINES_OF_DALARNIA_56_D45CD978, + &DEXTOOLS_56_C29896E3, + &DIA_56_7E0901DD, + &DREP_56_01A705FF, + &DEFI_YIELD_PROTOCOL_56_91BCEF17, + &DOGELON_MARS_56_D9BE2540, + &HARVEST_FINANCE_56_A5D33743, + &FETCH_AI_56_8691FA7F, + &FLOKI_56_5363D37E, + &FRAX_56_53E89F40, + &FANTOM_56_AF29DCFE, + &FRAX_SHARE_56_5EADB9EE, + &GALXE_56_40497AA5, + ÐGAS_56_B72F7D49, + &HASHFLOW_56_35883E47, + &HIGHSTREET_56_1FFEED63, + &INJECTIVE_56_EBE4D495, + &JUPITER_56_8E140CE7, + &KUJIRA_56_7C9FB5CC, + &CHAINLINK_TOKEN_56_111A51BD, + &MASK_NETWORK_56_F4D568A3, + &MATH_56_98A36983, + &POLYGON_56_5ED682BD, + &MERIT_CIRCLE_56_4EF9E5D6, + &METIS_56_B0820639, + &MAGIC_INTERNET_MONEY_56_19F433BA, + &MIRROR_PROTOCOL_56_10D8C2C9, + &MULTICHAIN_56_3C8764E3, + &PERPETUAL_PROTOCOL_56_84C7C6F5, + &POLKASTARTER_56_0887F570, + &PARSIQ_56_93D2A577, + &PSTAKE_FINANCE_56_F58A7C0C, + &REVV_56_8D702A93, + &STADER_56_0B5481E8, + &SOL_WORMHOLE_56_D3AEA76E, + &STARGATE_FINANCE_56_9631D62B, + &SUPERFARM_56_CC4F0D4D, + &SUSHI_56_FC9124C4, + &SWFTCOIN_56_55DFBAD3, + &SWIPE_56_FABA485A, + &SYNAPSE_56_1F9E9484, + &CHRONOTECH_56_DE5D7F68, + &ALIEN_WORLDS_56_EBD57C95, + &UNIFI_PROTOCOL_DAO_56_6B814D8B, + &UNISWAP_56_A02CE9B1, + &PAWTOCOL_56_94334EE4, + &USDCOIN_56_32CD580D, + &TETHER_USD_56_B3197955, + &WRAPPED_BNB, + &WRAPPED_ETHER_56_59F933F8, + &WOO_NETWORK_56_9E945D4B, + &CHAIN_56_DF88A05B, + &LAYERZERO_56_F13271CD, + &TOKEN_1INCH_130_A9ACD06E, + &ANCIENT8_130_FEF7759A, + &AAVE_130_BEEAAE1E, + &ARCBLOCK_130_FE5675BC, + &ALCHEMY_PAY_130_E66ECF77, + &ACROSS_PROTOCOL_TOKEN_130_62BBB32C, + &AMBIRE_ADEX_130_A299A500, + &AERGO_130_F15873B5, + &AEVO_130_60D60F8B, + &AGEUR_130_C681A118, + &ADVENTURE_GOLD_130_412721CF, + &AIOZ_NETWORK_130_6CF99B1A, + &ALCHEMIX_130_5AEBDCD6, + &ALEPH_IM_130_4C15BB5C, + &ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_130_EEC73780, + &MY_NEIGHBOR_ALICE_130_8860960A, + &ALPHA_VENTURE_DAO_130_CEBD78D3, + &ALTLAYER_130_B3589153, + &_130_2BBC967F, + &ANKR_130_EFF97622, + &ARAGON_130_D4A31308, + &APECOIN_130_314046CF, + &API3_130_F678961B, + &APU_APUSTAJA_130_63B9E379, + &ARBITRUM_130_18A4B40D, + &ARKHAM_130_442EF089, + &ARPA_CHAIN_130_88E30B45, + &ASH_130_5A30D7FB, + &ASSEMBLE_PROTOCOL_130_5BA0ADA7, + &AIRSWAP_130_8C09AE56, + &AUTOMATA_130_D890C4B2, + &AETHIR_TOKEN_130_FEE183AB, + &BOUNCE_130_91BEF68E, + &AUDIUS_130_3C81684B, + &ARTVERSE_TOKEN_130_00939999, + &AXELAR_130_A4CBF2C9, + &AXIE_INFINITY_130_D188F927, + &BADGER_DAO_130_17388406, + &BALANCER_130_34A8ADDF, + &BAND_PROTOCOL_130_6A8857D5, + &BASIC_ATTENTION_TOKEN_130_508EA589, + &BEAM_130_F9500824, + &BICONOMY_130_1D0588E7, + &BIG_TIME_130_D2FA7CDC, + &BITDAO_130_FB523A5C, + &HARRYPOTTEROBAMASONIC10INU_130_9B3D706F, + &BLUR_130_2B9255EA, + &BLUZELLE_130_8EF471EE, + &BANCOR_NETWORK_TOKEN_130_472C5A62, + &BOBA_NETWORK_130_BBB41B05, + &BARNBRIDGE_130_61DF8972, + &BONK, + &BRAINTRUST_130_00986B71, + &BINANCE_USD_130_BDA9F9C6, + &COIN98_130_F8E4F8E1, + &COINBASE_WRAPPED_BTC_130_AB6A1EF1, + &COINBASE_WRAPPED_STAKED_ETH_130_8211DB59, + &CELO_NATIVE_ASSET_WORMHOLE_130_5A8A8D9C, + &CELER_NETWORK_130_48035703, + &CHROMIA_130_210A4E5B, + &CHILIZ_130_8B2396B0, + &CLOVER_FINANCE_130_FA41404C, + &COMPOUND_130_F2288656, + &COTI_130_32F499C3, + &CIRCUITS_OF_VALUE_130_CC295BEC, + &COW_PROTOCOL_130_B26D3996, + &CLEARPOOL_130_423DFB57, + &COVALENT_130_621F90C1, + &CRONOS_130_A30DE818, + &CRYPTERIUM_130_18B0D066, + &CURVE_DAO_TOKEN_130_D1C2CCB3, + &CARTESI_130_BAAED2C5, + &CRYPTEX_FINANCE_130_62FCB619, + &SOMNIUM_SPACE_CUBES_130_92C2F8AF, + &CIVIC_130_E85A01ED, + &CONVEX_FINANCE_130_F0087EA5, + &COVALENT_X_TOKEN_130_F14E5A09, + &DAI_STABLECOIN_130_19573F81, + &MINES_OF_DALARNIA_130_90288086, + &DERIVADAO_130_3A270265, + &DENT_130_328E874C, + &DEXTOOLS_130_1723CDDD, + &DIA_130_3F9543C2, + &DISTRICT0X_130_C1B9E545, + &DOGECOIN, + &DEFI_PULSE_INDEX_130_CD2F84F1, + &DREP_130_38EA9EE7, + &DYDX_130_5FAEB82C, + &DEFI_YIELD_PROTOCOL_130_9D598610, + &EIGENLAYER_130_D016C47D, + &ELASTOS_130_D8E8C1AB, + &DOGELON_MARS_130_26C1DE05, + ÐENA_130_A6CBD2DD, + &ENJIN_COIN_130_84A6D0A6, + ÐEREUM_NAME_SERVICE_130_B5F0383A, + ÐERNITY_CHAIN_130_A93CDB03, + ÐER_FI_130_58880821, + &EULER_130_5B5D03FE, + &EURO_COIN_130_2813B0A8, + &QUANTOZ_EURQ_130_24D7D72D, + &STABLR_EURO_130_9C36FB5F, + &HARVEST_FINANCE_130_31EE825F, + &FETCH_AI_130_DDD7DFE7, + &STAFI_130_A10764A6, + &FLOKI_130_6C51FA81, + &FORTA_130_D87D94E5, + &LEFORTH_GOVERNANCE_TOKEN_130_2220F12E, + &SHAPESHIFT_FOX_TOKEN_130_3B7A318E, + &FRAX_130_D74132B9, + &FANTOM_130_90DC7F0E, + &FUNCTION_X_130_1D7AF1AF, + &FRAX_SHARE_130_062021D6, + &GRAVITY_130_6FD8803C, + &GALXE_130_443D8675, + &GALA_130_B560FAC9, + &GOLDFINCH_130_B157D3D0, + &AAVEGOTCHI_130_840AD24B, + &GOLEM_130_E2C9F2B9, + &GNOSIS_TOKEN_130_E125A938, + &GODS_UNCHAINED_130_D3683F48, + &THE_GRAPH_130_B3204D71, + &GITCOIN_130_8FE5CF48, + &GEMINI_DOLLAR_130_5C0920A9, + &GYEN_130_A574C36F, + &HASHFLOW_130_8C34A28B, + &HIGHSTREET_130_B1374879, + &HOPR_130_AF385B36, + &HYPERLIQUID, + &IDEX_130_60EABE8E, + &ILLUVIUM_130_42F3E51F, + &IMMUTABLE_X_130_F5AA8053, + &INDEX_COOPERATIVE_130_121E39B7, + &INJECTIVE_130_9A89F9F8, + &INVERSE_FINANCE_130_9F7B54FB, + &IOTEX_130_E2B6843F, + &GEOJAM_130_1D5C61A8, + &JASMYCOIN_130_22720708, + &JUPITER_130_E5CAB8B2, + &JUPITER_130_2381AFAD, + &KEEP_NETWORK_130_EA6AFE80, + &SELFKEY_130_3F1BBFDC, + &KYBER_NETWORK_CRYSTAL_130_B7CD2284, + &KEEP3RV1_130_5FAD6A74, + &KRYLL_130_4F002943, + &KUJIRA_130_30258681, + &LAYER3_130_1B7B482C, + &LCX_130_46687782, + &LIDO_DAO_130_814E8829, + &CHAINLINK_TOKEN_130_9BBEEFB7, + &LITENTRY_130_91BE0FDF, + &LEAGUE_OF_KINGDOMS_130_AAC89733, + &LOOM_NETWORK_130_009F523C, + &LIVEPEER_130_F35B73E3, + &LIQUITY_130_53C71A60, + &LOOPRINGCOIN_V2_130_A8AB158A, + &BLOCKLORDS_130_0C7BEE3F, + &LIQUITY_USD_130_D72577FB, + &DECENTRALAND_130_00FE358B, + &MASK_NETWORK_130_1B9512C4, + &MATH_130_99ED2C97, + &POLYGON_130_6507176B, + &MERIT_CIRCLE_130_2D657399, + &MOSS_CARBON_CREDIT_130_7E6ACC40, + &MEASURABLE_DATA_TOKEN_130_31BFEFF4, + &MEMECOIN_130_8E3E7D06, + &METIS_130_B3A8F102, + &MAGIC_INTERNET_MONEY_130_3E3602AB, + &MIRROR_PROTOCOL_130_4A72D717, + &MELON_130_4DC3C117, + &MOG_COIN_130_78921EBD, + &MONAVALE_130_1C7A1087, + &MOVEMENT_130_0FF19949, + &MAPLE_130_D752A219, + &METAL_130_6CFAD9EA, + &MULTICHAIN_130_D82B4701, + &MSTABLE_USD_130_B40A8DD1, + &MUSE_DAO_130_81D5F345, + &GENSOKISHI_METAVERSE_130_FF182974, + &MXC_130_02727794, + &POLYSWARM_130_795032DF, + &NEIRO_130_87696276, + &NKN_130_336BAF62, + &NUMERAIRE_130_DBDA20FC, + &NUCYPHER_130_AACEA6B9, + &OCEAN_PROTOCOL_130_3CD79208, + &ORIGIN_PROTOCOL_130_EE18C880, + &OMG_NETWORK_130_8EE37383, + &OMNI_NETWORK_130_959EB0E3, + &ONDO_FINANCE_130_85321557, + &ORCA_ALLIANCE_130_1BE3E8C0, + &ORION_PROTOCOL_130_B6EAF396, + &ORCHID_130_52B98042, + &PAYPEREX_130_0D292327, + &PLAYDAPP_130_1E75D6AC, + &PEPE_130_9074952B, + &PERPETUAL_PROTOCOL_130_CCFEC7D5, + &PIRATE_NATION_130_18D064C6, + &PLUTON_130_ABB6F6C7, + &POLYGON_ECOSYSTEM_TOKEN_130_E5682E95, + &POLKASTARTER_130_DC306503, + &POLYMATH_130_D538D863, + &MARLIN_130_4D4782D5, + &PORTAL_130_0F2A5642, + &POWER_LEDGER_130_DFFA6BFF, + &PRIME_130_CBF9FEE0, + &PROPY_130_1F41A7C9, + &PARSIQ_130_0ABF3DEF, + &PSTAKE_FINANCE_130_E7D7CAA2, + &PUFFER_FINANCE_130_38B560D2, + &PAYPAL_USD_130_8E6207C5, + &QUANT_130_98C360D4, + &QREDO_130_8C1068B8, + &QUANTSTAMP_130_6BB5EABB, + &QUICKSWAP_130_F8E6CAC2, + &RADICLE_130_F08A1A45, + &RAI_REFLEX_INDEX_130_89F34A66, + &SUPERRARE_130_E025BB6F, + &RARIBLE_130_03C8561C, + &RUBIC_130_66B403E3, + &RIBBON_FINANCE_130_C841CD3E, + &REPUBLIC_TOKEN_130_8261617E, + &REPUTATION_AUGUR_V1_130_B2816FC4, + &REPUTATION_AUGUR_V2_130_1E72A8C4, + &REQUEST_130_9D8663CD, + &REVV_130_0F9CA657, + &RENZO_130_AAD6C9AB, + &RARI_GOVERNANCE_TOKEN_130_946CF284, + &IEXEC_RLC_130_B3347ACB, + &RALLY_130_3F88C889, + &RENDER_TOKEN_130_8D649868, + &ROOK_130_9DE41D99, + &RESERVE_RIGHTS_130_B1889066, + &SAFE_130_10EFD888, + &THE_SANDBOX_130_2CAF25CA, + &STADER_130_B32D72E5, + &SHIBA_INU_130_5664158E, + &SHPING_130_66024F2F, + &SKALE_130_8AD20C01, + &SKY_GOVERNANCE_TOKEN_130_D07074E4, + &SMOOTH_LOVE_POTION_130_96CB03B3, + &STATUS_130_265ABF5F, + &SYNTHETIX_NETWORK_TOKEN_130_59E6BC88, + &UNISOCKS_130_DC4627AB, + &SOL_WORMHOLE_130_C3D054FE, + &SOLANA, + &SPELL_TOKEN_130_C17FEF7F, + &SPX6900_130_036DD629, + &STARGATE_FINANCE_130_19373135, + &STORJ_TOKEN_130_C9951835, + &STARKNET_130_2332C72E, + &STOX_130_CACCEA22, + &SUKU_130_82176525, + &SUPERFARM_130_2BD86D3D, + &SYNTH_SUSD_130_9B3A6A0F, + &SUSHI_130_BDFB3CE5, + &SWELL_130_028A5870, + &SWFTCOIN_130_45AF1616, + &SWIPE_130_9785C2E1, + &SYLO_130_CFFCF85E, + &SYNAPSE_130_81888A48, + &SYRUP_TOKEN_130_8CD6FA96, + &THRESHOLD_NETWORK_130_48F2AD54, + &BITTENSOR, + &TBTC_130_20BC7814, + &CHRONOTECH_130_1EDA749C, + &ALIEN_WORLDS_130_A9A46C68, + &TOKEMAK_130_36213E0B, + &TE_FOOD_130_A7BD5AC6, + &ORIGINTRAIL_130_DBAE6F2E, + &TELLOR_130_6D8EC63B, + &TRIBE_130_33DACDBD, + &TRUEFI_130_F30CFE0E, + &TURBO_130_F2D202A1, + &THE_VIRTUA_KOLECT_130_13BD9D5D, + &UMA_VOTING_TOKEN_V1_130_72435F8C, + &UNIFI_PROTOCOL_DAO_130_0408A30B, + &UNISWAP_130_7CE9EA21, + &PAWTOCOL_130_3E264D36, + &USDCOIN_130_0EF57AD6, + &GLOBAL_DOLLAR_130_A9F86F1E, + &PAX_DOLLAR_130_6DE0FEFF, + &QUANTOZ_USDQ_130_7B2F3A5F, + &STABLR_USD_130_004C06A7, + &USDS_STABLECOIN_130_3B2F7BB4, + &TETHER_USD_130_54C75518, + &USUAL_130_98BC5950, + &VANRY_130_01564A0B, + &VOYAGER_TOKEN_130_8FFE537F, + &WRAPPED_AMPLEFORTH_130_06364A49, + &WRAPPED_BTC_130_4EC4AFB8, + &WRAPPED_CENTRIFUGE_130_D72E82C4, + &WRAPPED_ETHER_130_00000006, + &DOGWIFHAT, + &WOO_NETWORK_130_EFD89E62, + &CHAIN_130_DC06A12F, + &PLASMA, + &XRP, + &XSGD_130_021265C3, + &XYO_NETWORK_130_2AEBE4EA, + &YEARN_FINANCE_130_F84A3201, + &DFI_MONEY_130_6C18A07E, + &YIELD_GUILD_GAMES_130_76E36F4B, + &ZCASH, + &ZETACHAIN_130_B3CB3CA4, + &LAYERZERO_130_7ED29CFB, + &TOKEN_0X_PROTOCOL_TOKEN_130_A6E7EDF5, + &AAVE_137_2B21C90B, + &AGEUR_137_C0057DB4, + &_137_4F27054D, + &BALANCER_137_3B0E76A3, + &BAND_PROTOCOL_137_D82606AC, + &BANCOR_NETWORK_TOKEN_137_2A4F7842, + &COMPOUND_137_837AEF5C, + &CURVE_DAO_TOKEN_137_33A610AF, + &CIVIC_137_398B02BE, + &DAI_STABLECOIN_137_39C6A063, + ÐEREUM_NAME_SERVICE_137_90EE7C4F, + &GNOSIS_TOKEN_137_7DF024A8, + &THE_GRAPH_137_499F5531, + &KEEP_NETWORK_137_2EB0C72C, + &KYBER_NETWORK_CRYSTAL_137_9CFA1DC7, + &CHAINLINK_TOKEN_137_3FABAD39, + &LOOM_NETWORK_137_1193F6B3, + &LOOPRINGCOIN_V2_137_BB47DDC1, + &DECENTRALAND_137_33606FD4, + &POLYGON_137_00001010, + &MAKER_137_E01FF61D, + &NUMERAIRE_137_11F46729, + &ORCHID_137_D31F6060, + &REPUBLIC_TOKEN_137_26ED89D0, + &REPUTATION_AUGUR_V2_137_7363F733, + &SYNTHETIX_NETWORK_TOKEN_137_11FEF68A, + &STORJ_TOKEN_137_5A3F5792, + &SYNTH_SUSD_137_6E03A7A0, + &UMA_VOTING_TOKEN_V1_137_77A6B731, + &UNISWAP_137_7FB5180F, + &USDCOIN_137_3D5C3359, + &USDCOIN_POS, + &TETHER_USD_137_04B58E8F, + &VANAR_CHAIN, + &VOXIES, + &WRAPPED_BTC_137_47D9BFD6, + &WRAPPED_ETHER_137_F1B9F619, + &WRAPPED_MATIC, + &XSGD_137_8D201995, + &YEARN_FINANCE_137_465260B6, + &LAYERZERO_137_F13271CD, + &TOKEN_0X_PROTOCOL_TOKEN_137_CA6BE3D5, + &SOL_WORMHOLE_143_245217F1, + &USDCOIN_143_5AAFB603, + &TETHER_USD_143_750FC82D, + &WRAPPED_BTC_143_230D2B9C, + &WRAPPED_ETHER_143_35481242, + &GLOBAL_DOLLAR_196_933D2DC8, + &ZKSYNC, + &BRIDGED_USDC, + &WRAPPED_BTC_480_2D70CFA3, + &WRAPPED_ETHER_480_00000006, + &USDCOIN_1868_4AACC369, + &TETHER_USD_1868_97B5AE35, + &WRAPPED_ETHER_1868_00000006, + &TOKEN_1INCH_8453_1E111CBE, + &AAVE_8453_D17F814B, + &ARCBLOCK_8453_7C1FA556, + &AMBIRE_ADEX_8453_A3E0EFD9, + &AERODROME_FINANCE, + &AIXBT_BY_VIRTUALS, + &ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_8453_D59F3DCC, + &AUSTRALIAN_DIGITAL_DOLLAR, + &AVANTIS, + &AWE_NETWORK, + &B3, + &HARRYPOTTEROBAMASONIC10INU_8453_D39A1A29, + &BANKRCOIN, + &COINBASE_WRAPPED_ADA, + &COINBASE_WRAPPED_BTC_8453_0EED33BF, + &COINBASE_WRAPPED_DOGE, + &COINBASE_WRAPPED_STAKED_ETH_8453_CF0DEC22, + &COINBASE_WRAPPED_LTC, + &COINBASE_WRAPPED_XRP, + &TOKENBOT, + &COMPOUND_8453_976840E0, + &COOKIE, + &CURVE_DAO_TOKEN_8453_67DD0415, + &CARTESI_8453_76138D45, + &CRYPTEX_FINANCE_8453_D4666E14, + &COVALENT_X_TOKEN_8453_8EB628FF, + &DAI_STABLECOIN_8453_917DB0CB, + &DEGEN, + &DOGINME, + &DOVU_8453_B953F865, + &DERIVE_8453_B645D083, + &DEFINITIVE, + &ELSA, + &EURC, + &FAI, + &FLOCK, + &FLUID, + &SPORT_FUN, + &HOME, + &HYPERLANE, + &IOTEX_8453_27AE38C1, + &GEOJAM_8453_3AA2A057, + &KAITO, + &KEYBOARD_CAT, + &KRYLL_8453_611F9F7A, + &KEETA, + &LCX_8453_71D3C171, + &LIQUITY_8453_BDDC125C, + &MAMO, + &NOICE, + &ODOS_TOKEN, + &PENDLE_8453_029EEB3E, + &PEPE_8453_8B982BE3, + &PERPETUAL_PROTOCOL_8453_DAAD58DE, + &PRIME_8453_A5ADD21B, + &PROPY_8453_9230438B, + &PROMPT, + &RAVEDAO, + &RECALL_NETWORK, + &RAINBOW, + &RESEARCHCOIN, + &RESERVE_RIGHTS_8453_6072F64A, + &SAPIEN, + &SEAMLESSS, + &STATUS_8453_2E8AC09E, + &SYNTHETIX_NETWORK_TOKEN_8453_327FDA66, + &SPX6900_8453_6819BB2C, + &SUPERFLUID_TOKEN, + &SUSHI_8453_98B2AFBA, + &SYNDICATE, + &TBTC_8453_22AB794B, + &TOSHI, + &TOWNS, + &INTUITION, + &UNISWAP_8453_114A3C83, + &SUPERFORM, + &USD_BASE_COIN, + &USD_COIN, + &VENICE_TOKEN, + &WALLETCONNECT_TOKEN_8453_DD927945, + &MOONWELL, + &WRAPPED_ETHER_8453_00000006, + &WORLD_MOBILE_TOKEN, + &XYO_NETWORK_8453_223ADC94, + &YEARN_FINANCE_8453_AD3CB239, + &YIELD_GUILD_GAMES_8453_F5EF1799, + &HORIZEN, + &BOUNDLESS_8453_FBBCE7CF, + &ZORA, + &LAYERZERO_8453_F13271CD, + &TOKEN_0X_PROTOCOL_TOKEN_8453_BC9779D0, + &TOKEN_1INCH_42161_3F4BB9AF, + &AAVE_42161_CE967196, + &ACROSS_PROTOCOL_TOKEN_42161_03D9C99D, + &AEVO_42161_2B9783CD, + &AGEUR_42161_723528E7, + &ADVENTURE_GOLD_42161_012A3B9C, + &AIOZ_NETWORK_42161_E1569923, + &ALEPH_IM_42161_8E245A6C, + &ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_42161_FC0A71D1, + &ALPHA_VENTURE_DAO_42161_0A6B2646, + &ANKR_42161_C1E95447, + &APECOIN_42161_DBAD2210, + &API3_42161_92CA7811, + &ARBITRUM_42161_E49E6548, + &ARKHAM_42161_DA4E656E, + &AUTOMATA_42161_75714D03, + &AETHIR_TOKEN_42161_49092FB4, + &AXELAR_42161_E2C6810F, + &AXIE_INFINITY_42161_3E5D0089, + &BADGER_DAO_42161_0D76472E, + &BALANCER_42161_F56A56B8, + &BASIC_ATTENTION_TOKEN_42161_616AEE75, + &BICONOMY_42161_60A8E74D, + &BITDAO_42161_EB921C2A, + &HARRYPOTTEROBAMASONIC10INU_42161_13BD565D, + &BLUR_42161_FE606EB2, + &BANCOR_NETWORK_TOKEN_42161_BA06D073, + &BARNBRIDGE_42161_EE64A4E1, + &BINANCE_USD_42161_462629A2, + &PANCAKESWAP_42161_7CF58860, + &COINBASE_WRAPPED_BTC_42161_0EED33BF, + &COINBASE_WRAPPED_STAKED_ETH_42161_EAE7732F, + &CELO_NATIVE_ASSET_WORMHOLE_42161_1EF4F336, + &CELER_NETWORK_42161_40F345AB, + &COMPOUND_42161_5C6C91DE, + &COTI_42161_D81EA101, + &COW_PROTOCOL_42161_F5C87A04, + &COVALENT_42161_657273BF, + &CRONOS_42161_676F354C, + &CURVE_DAO_TOKEN_42161_FA034978, + &CARTESI_42161_1B476999, + &CRYPTEX_FINANCE_42161_0425E12B, + &CIVIC_42161_1DDBF144, + &CONVEX_FINANCE_42161_520829C5, + &DAI_STABLECOIN_42161_C9000DA1, + &DEXTOOLS_42161_9B64E227, + &DIA_42161_E17AC05E, + &DISTRICT0X_42161_A49AD47A, + &DEFI_PULSE_INDEX_42161_B68DD74C, + &DERIVE_42161_90ABB135, + &DYDX_42161_8CC90C5A, + &EIGENLAYER_42161_6F96C248, + &DOGELON_MARS_42161_17077FD4, + ÐENA_42161_8EA977D8, + &ENJIN_COIN_42161_63806758, + ÐEREUM_NAME_SERVICE_42161_E70D7C28, + ÐERNITY_CHAIN_42161_4D667F96, + &ESPRESSO_42161_065C94F1, + ÐER_FI_42161_4DFD5736, + &EURO_COIN_42161_1FC52A48, + &HARVEST_FINANCE_42161_24C83C70, + &FETCH_AI_42161_7DCC4CC9, + &STAFI_42161_767C7282, + &FLOKI_42161_B4905FAE, + &FLUX_42161_D685710A, + &FORTA_42161_CC3D2923, + &SHAPESHIFT_FOX_TOKEN_42161_9E513C73, + &FRAX_42161_0BC51305, + &FANTOM_42161_D4C2DF37, + &FRAX_SHARE_42161_AFFFDEA4, + &GALXE_42161_9BFD1182, + &GALA_42161_2827FF8C, + &GMX, + &GNOSIS_TOKEN_42161_4DEB6CF1, + &THE_GRAPH_42161_EA7E88C7, + &GITCOIN_42161_C437DEE0, + &GYEN_42161_D9B6D5F7, + &HIGHSTREET_42161_615BCEEA, + &HOPR_42161_70294EF7, + &IDOS_TOKEN, + &ILLUVIUM_42161_05488673, + &IMMUTABLE_X_42161_FCA7783E, + &INJECTIVE_42161_DF608F80, + &JASMYCOIN_42161_73E27083, + &KINTO, + &KRYLL_42161_B7307B69, + &KUJIRA_42161_5671E7CA, + &LIDO_DAO_42161_D85EFA60, + &CHAINLINK_TOKEN_42161_58539FB4, + &LITENTRY_42161_30A40B25, + &LIVEPEER_42161_1CB8A839, + &LIQUITY_42161_CE3E1449, + &LOOPRINGCOIN_V2_42161_1BAE7FBE, + &LIQUITY_USD_42161_2541425B, + &MAGIC, + &DECENTRALAND_42161_A165E231, + &MASK_NETWORK_42161_5C313739, + &MATH_42161_B17AC332, + &POLYGON_42161_18BE0766, + &METIS_42161_D2E33769, + &MAGIC_INTERNET_MONEY_42161_0C04DAF2, + &MAKER_42161_6F8F2879, + &MELON_42161_7AE4B514, + &MANTLE_42161_EDF6C53A, + &MOG_COIN_42161_206AABAC, + &MORPHO_TOKEN_42161_02F620AC, + &MAPLE_42161_097F0CA0, + &MULTICHAIN_42161_ECD9A39A, + &GENSOKISHI_METAVERSE_42161_3E15992F, + &MXC_42161_B6862ED6, + &POLYSWARM_42161_FB920D5B, + &NKN_42161_0406177B, + &NUMERAIRE_42161_6B569711, + &OCEAN_PROTOCOL_42161_AD8234DF, + &ORIGIN_PROTOCOL_42161_58AE423E, + &OMG_NETWORK_42161_61421E8E, + &ONDO_FINANCE_42161_8B37A5E7, + &ORION_PROTOCOL_42161_551E6218, + &PENDLE_42161_B9A8C9E8, + &PEPE_42161_33959CBB, + &PERPETUAL_PROTOCOL_42161_F61D3DAC, + &PIRATE_NATION_42161_43D77CBF, + &PLUME_42161_CB15BA13, + &POLYGON_ECOSYSTEM_TOKEN_42161_68FE08CC, + &POLKASTARTER_42161_8B016B64, + &POLYMATH_42161_B33809E9, + &MARLIN_42161_C8BD9DDD, + &PORTAL_42161_9DB991DE, + &POWER_LEDGER_42161_D423E4A6, + &PRIME_42161_E7AC5067, + &PARSIQ_42161_CAF60CD2, + &PAYPAL_USD_42161_0967342E, + &QUANT_42161_3C7EFF85, + &RADICLE_42161_12155E49, + &RAI_REFLEX_INDEX_42161_78D419F2, + &RARIBLE_42161_63C1B8E0, + &RUBIC_42161_5CBC335F, + &REPUBLIC_TOKEN_42161_1C79A204, + &REQUEST_42161_8BB92171, + &RARI_GOVERNANCE_TOKEN_42161_CD794794, + &IEXEC_RLC_42161_5D794E66, + &RENDER_TOKEN_42161_6F21E279, + &ROCKET_POOL_PROTOCOL_42161_1D0CC507, + &RESERVE_RIGHTS_42161_DBD2E594, + &THE_SANDBOX_42161_D64E3DAC, + &STADER_42161_92F34B63, + &SHIBA_INU_42161_E3872FD1, + &SKALE_42161_37267878, + &STATUS_42161_A6415160, + &SYNTHETIX_NETWORK_TOKEN_42161_BCA37D60, + &UNISOCKS_42161_A3B264E7, + &SOL_WORMHOLE_42161_EC617124, + &SPELL_TOKEN_42161_FE15D2AF, + &SPX6900_42161_5D2BA901, + &SQD, + &STARGATE_FINANCE_42161_A16313EC, + &STORJ_TOKEN_42161_7AA2FCC2, + &SUPERFARM_42161_26498956, + &SYNTH_SUSD_42161_9D112F95, + &SUSHI_42161_0D85C61A, + &SWELL_42161_A58F2571, + &SYNAPSE_42161_375EAD84, + &THRESHOLD_NETWORK_42161_DEC21F55, + &TBTC_42161_0A572594, + &TELLOR_42161_10D88242, + &TRIBE_42161_03914A5A, + &TURBO_42161_EDE4576A, + &UMA_VOTING_TOKEN_V1_42161_9B0C3B22, + &UNISWAP_42161_72F1F7F0, + &WORLD_LIBERTY_FINANCIAL_USD_42161_DD217A33, + &USDCOIN_42161_268E5831, + &BRIDGED_USDC_42161_BDDB5CC8, + &PAX_DOLLAR_42161_B699DF8F, + &USDS_STABLECOIN_42161_749B876B, + &USUAL_42161_2140ABBB, + &WRAPPED_AMPLEFORTH_42161_8AE650BB, + &WRAPPED_BTC_42161_AEFC5B0F, + &WRAPPED_ETHER_42161_523FBAB1, + &WORLD_LIBERTY_FINANCIAL_42161_0E1980BF, + &WOO_NETWORK_42161_3AEFD07B, + &TETHER_GOLD_42161_CFC6C9D3, + &CHAIN_42161_4DEEAFED, + &XSGD_42161_4C1C4302, + &YEARN_FINANCE_42161_085B1582, + &ZETACHAIN_42161_47B88954, + &LAYERZERO_42161_F13271CD, + &TOKEN_0X_PROTOCOL_TOKEN_42161_19235AE2, + &WRAPPED_BITCOIN, + &CELO, + &USDCOIN_42220_8B32118C, + &TETHER_USD_42220_87483D5E, + &WRAPPED_ETHER_42220_622F4361, + &TOKEN_1INCH_43114_8B28F267, + &AAVE_43114_E5D386D9, + &AGEUR_43114_F1F96C57, + &ALPHA_VENTURE_DAO_43114_7A8E208F, + &ANKR_43114_2C84B4DE, + &AXELAR_43114_CE194C5D, + &BASIC_ATTENTION_TOKEN_43114_A4690588, + &BINANCE_USD_43114_39D2DB39, + &COMPOUND_43114_906E2437, + &CARTESI_43114_0FABF552, + &DAI_E_TOKEN, + &DEFI_YIELD_PROTOCOL_43114_91BCEF17, + &EURO_COIN_43114_505C2ACD, + &FLUX_43114_C20DAF55, + &FRAX_43114_21A1DA64, + &FRAX_SHARE_43114_3FC8E387, + &GMX_43114_5011C661, + &THE_GRAPH_43114_69E85CB9, + &GUNZ, + &CHAINLINK_TOKEN_43114_413227A3, + &MAGIC_INTERNET_MONEY_43114_8CB8C18D, + &MAKER_43114_AAB72D42, + &MULTICHAIN_43114_3C8764E3, + &PENDLE_43114_62EA213B, + &RAI_REFLEX_INDEX_43114_031BFF7D, + &SYNTHETIX_NETWORK_TOKEN_43114_BA4B209B, + &SOL_WORMHOLE_43114_06D2478F, + &SPELL_TOKEN_43114_1A2F7814, + &STARGATE_FINANCE_43114_F56E7590, + &SUSHI_43114_722E4F76, + &SYNAPSE_43114_E09CA251, + &UMA_VOTING_TOKEN_V1_43114_0A5B2339, + &UNI_E_TOKEN, + &USDC_TOKEN, + &TETHER_USD_43114_4DF4A8C7, + &WRAPPED_AVAX, + &WRAPPED_BTC_43114_5187B218, + &WRAPPED_ETHER_43114_6BC10BAB, + &WOO_NETWORK_43114_5F58D083, + &YEARN_FINANCE_43114_922F52DC, + &LAYERZERO_43114_F13271CD, + &TOKEN_0X_PROTOCOL_TOKEN_43114_75CDE0D2, + &WRAPPED_ETHER_80001_C5D1C0AA, + &WRAPPED_MATIC_80001_FB032889, + &BLAST, + &USD_COIN_BRIDGED_FROM_ETHEREUM, + &UNISWAP_11155111_4201F984, + &WRAPPED_ETHER_11155111_324D6B14, +]; + +pub fn get_token( + chain_id: alloy::primitives::ChainId, + address: alloy::primitives::Address, +) -> Option<&'static TokenInfo> { + match (chain_id, address) { + (1, addr) if addr == address!("0x111111111117dC0aa78b770fA6A738034120C302") => Some(&TOKEN_1INCH), + (1, addr) if addr == address!("0x3E5A19c91266aD8cE2477B91585d1856B84062dF") => Some(&ANCIENT8), + (1, addr) if addr == address!("0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9") => Some(&AAVE), + (1, addr) if addr == address!("0xB98d4C97425d9908E66E53A6fDf673ACcA0BE986") => Some(&ARCBLOCK), + (1, addr) if addr == address!("0xEd04915c23f00A313a544955524EB7DBD823143d") => Some(&ALCHEMY_PAY), + (1, addr) if addr == address!("0x44108f0223A3C3028F5Fe7AEC7f9bb2E66beF82F") => Some(&ACROSS_PROTOCOL_TOKEN), + (1, addr) if addr == address!("0xADE00C28244d5CE17D72E40330B1c318cD12B7c3") => Some(&AMBIRE_ADEX), + (1, addr) if addr == address!("0x91Af0fBB28ABA7E31403Cb457106Ce79397FD4E6") => Some(&AERGO), + (1, addr) if addr == address!("0xB528edBef013aff855ac3c50b381f253aF13b997") => Some(&AEVO), + (1, addr) if addr == address!("0x1a7e4e63778B4f12a199C062f3eFdD288afCBce8") => Some(&AGEUR), + (1, addr) if addr == address!("0x32353A6C91143bfd6C7d363B546e62a9A2489A20") => Some(&ADVENTURE_GOLD), + (1, addr) if addr == address!("0x626E8036dEB333b408Be468F951bdB42433cBF18") => Some(&AIOZ_NETWORK), + (1, addr) if addr == address!("0xdBdb4d16EdA451D0503b854CF79D55697F90c8DF") => Some(&ALCHEMIX), + (1, addr) if addr == address!("0x27702a26126e0B3702af63Ee09aC4d1A084EF628") => Some(&ALEPH_IM), + (1, addr) if addr == address!("0x6B0b3a982b4634aC68dD83a4DBF02311cE324181") => Some(&ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE), + (1, addr) if addr == address!("0xAC51066d7bEC65Dc4589368da368b212745d63E8") => Some(&MY_NEIGHBOR_ALICE), + (1, addr) if addr == address!("0x8408D45b61f5823298F19a09B53b7339c0280489") => Some(&ALLORA), + (1, addr) if addr == address!("0xa1faa113cbE53436Df28FF0aEe54275c13B40975") => Some(&ALPHA_VENTURE_DAO), + (1, addr) if addr == address!("0x8457CA5040ad67fdebbCC8EdCE889A335Bc0fbFB") => Some(&ALTLAYER), + (1, addr) if addr == address!("0xfF20817765cB7f73d4bde2e66e067E58D11095C2") => Some(&), + (1, addr) if addr == address!("0x8290333ceF9e6D528dD5618Fb97a76f268f3EDD4") => Some(&ANKR), + (1, addr) if addr == address!("0xa117000000f279D81A1D3cc75430fAA017FA5A2e") => Some(&ARAGON), + (1, addr) if addr == address!("0x4d224452801ACEd8B2F0aebE155379bb5D594381") => Some(&APECOIN), + (1, addr) if addr == address!("0x0b38210ea11411557c13457D4dA7dC6ea731B88a") => Some(&API3), + (1, addr) if addr == address!("0x5A9610919f5e81183823A2be4Bd1BeB2B4da2a20") => Some(&APRIORI), + (1, addr) if addr == address!("0x594DaaD7D77592a2b97b725A7AD59D7E188b5bFa") => Some(&APU_APUSTAJA), + (1, addr) if addr == address!("0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1") => Some(&ARBITRUM), + (1, addr) if addr == address!("0x6E2a43be0B1d33b726f0CA3b8de60b3482b8b050") => Some(&ARKHAM), + (1, addr) if addr == address!("0xBA50933C268F567BDC86E1aC131BE072C6B0b71a") => Some(&ARPA_CHAIN), + (1, addr) if addr == address!("0x64D91f12Ece7362F91A6f8E7940Cd55F05060b92") => Some(&ASH), + (1, addr) if addr == address!("0x2565ae0385659badCada1031DB704442E1b69982") => Some(&ASSEMBLE_PROTOCOL), + (1, addr) if addr == address!("0x27054b13b1B798B345b591a4d22e6562d47eA75a") => Some(&AIRSWAP), + (1, addr) if addr == address!("0xA2120b9e674d3fC3875f415A7DF52e382F141225") => Some(&AUTOMATA), + (1, addr) if addr == address!("0xbe0Ed4138121EcFC5c0E56B40517da27E6c5226B") => Some(&AETHIR_TOKEN), + (1, addr) if addr == address!("0xA9B1Eb5908CfC3cdf91F9B8B3a74108598009096") => Some(&BOUNCE), + (1, addr) if addr == address!("0x4cCe605eD955295432958d8951D0B176C10720d5") => Some(&AUDD), + (1, addr) if addr == address!("0x18aAA7115705e8be94bfFEBDE57Af9BFc265B998") => Some(&AUDIUS), + (1, addr) if addr == address!("0x845576c64f9754CF09d87e45B720E82F3EeF522C") => Some(&ARTVERSE_TOKEN), + (1, addr) if addr == address!("0x467719aD09025FcC6cF6F8311755809d45a5E5f3") => Some(&AXELAR), + (1, addr) if addr == address!("0xBB0E17EF65F82Ab018d8EDd776e8DD940327B28b") => Some(&AXIE_INFINITY), + (1, addr) if addr == address!("0xA27EC0006e59f245217Ff08CD52A7E8b169E62D2") => Some(&AZTEC), + (1, addr) if addr == address!("0x3472A5A71965499acd81997a54BBA8D852C6E53d") => Some(&BADGER_DAO), + (1, addr) if addr == address!("0xba100000625a3754423978a60c9317c58a424e3D") => Some(&BALANCER), + (1, addr) if addr == address!("0xBA11D00c5f74255f56a5E366F4F77f5A186d7f55") => Some(&BAND_PROTOCOL), + (1, addr) if addr == address!("0xf0DB65D17e30a966C2ae6A21f6BBA71cea6e9754") => Some(&LOMBARD), + (1, addr) if addr == address!("0x0D8775F648430679A709E98d2b0Cb6250d2887EF") => Some(&BASIC_ATTENTION_TOKEN), + (1, addr) if addr == address!("0x62D0A8458eD7719FDAF978fe5929C6D342B0bFcE") => Some(&BEAM), + (1, addr) if addr == address!("0xF17e65822b568B3903685a7c9F496CF7656Cc6C2") => Some(&BICONOMY), + (1, addr) if addr == address!("0x64Bc2cA1Be492bE7185FAA2c8835d9b824c8a194") => Some(&BIG_TIME), + (1, addr) if addr == address!("0xcb1592591996765Ec0eFc1f92599A19767ee5ffA") => Some(&BIO), + (1, addr) if addr == address!("0x1A4b46696b2bB4794Eb3D4c26f1c55F9170fa4C5") => Some(&BITDAO), + (1, addr) if addr == address!("0x72e4f9F808C49A2a61dE9C5896298920Dc4EEEa9") => Some(&HARRYPOTTEROBAMASONIC10INU), + (1, addr) if addr == address!("0x5283D291DBCF85356A21bA090E6db59121208b44") => Some(&BLUR), + (1, addr) if addr == address!("0x5732046A883704404F284Ce41FfADd5b007FD668") => Some(&BLUZELLE), + (1, addr) if addr == address!("0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C") => Some(&BANCOR_NETWORK_TOKEN), + (1, addr) if addr == address!("0x42bBFa2e77757C645eeaAd1655E0911a7553Efbc") => Some(&BOBA_NETWORK), + (1, addr) if addr == address!("0xC9746F73cC33a36c2cD55b8aEFD732586946Cedd") => Some(&BOB), + (1, addr) if addr == address!("0x0391D2021f89DC339F60Fff84546EA23E337750f") => Some(&BARNBRIDGE), + (1, addr) if addr == address!("0x086F405146Ce90135750Bbec9A063a8B20A8bfFb") => Some(&BREVIS), + (1, addr) if addr == address!("0x799ebfABE77a6E34311eeEe9825190B9ECe32824") => Some(&BRAINTRUST), + (1, addr) if addr == address!("0x4Fabb145d64652a948d72533023f6E7A623C7C53") => Some(&BINANCE_USD), + (1, addr) if addr == address!("0xAE12C5930881c53715B369ceC7606B70d8EB229f") => Some(&COIN98), + (1, addr) if addr == address!("0x152649eA73beAb28c5b49B26eb48f7EAD6d4c898") => Some(&PANCAKESWAP), + (1, addr) if addr == address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf") => Some(&COINBASE_WRAPPED_BTC), + (1, addr) if addr == address!("0xBe9895146f7AF43049ca1c1AE358B0541Ea49704") => Some(&COINBASE_WRAPPED_STAKED_ETH), + (1, addr) if addr == address!("0x3294395e62F4eB6aF3f1Fcf89f5602D90Fb3Ef69") => Some(&CELO_NATIVE_ASSET_WORMHOLE), + (1, addr) if addr == address!("0x4F9254C83EB525f9FCf346490bbb3ed28a81C667") => Some(&CELER_NETWORK), + (1, addr) if addr == address!("0xcccCCCcCCC33D538DBC2EE4fEab0a7A1FF4e8A94") => Some(&CENTRIFUGE), + (1, addr) if addr == address!("0x8A2279d4A90B6fe1C4B30fa660cC9f926797bAA2") => Some(&CHROMIA), + (1, addr) if addr == address!("0x3506424F91fD33084466F402d5D97f05F8e3b4AF") => Some(&CHILIZ), + (1, addr) if addr == address!("0x80C62FE4487E1351b47Ba49809EBD60ED085bf52") => Some(&CLOVER_FINANCE), + (1, addr) if addr == address!("0xc00e94Cb662C3520282E6f5717214004A7f26888") => Some(&COMPOUND), + (1, addr) if addr == address!("0x44f49ff0da2498bCb1D3Dc7C0f999578F67FD8C6") => Some(&CORN), + (1, addr) if addr == address!("0xDDB3422497E61e13543BeA06989C0789117555c5") => Some(&COTI), + (1, addr) if addr == address!("0x3D658390460295FB963f54dC0899cfb1c30776Df") => Some(&CIRCUITS_OF_VALUE), + (1, addr) if addr == address!("0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB") => Some(&COW_PROTOCOL), + (1, addr) if addr == address!("0x66761Fa41377003622aEE3c7675Fc7b5c1C2FaC5") => Some(&CLEARPOOL), + (1, addr) if addr == address!("0xD417144312DbF50465b1C641d016962017Ef6240") => Some(&COVALENT), + (1, addr) if addr == address!("0xA0b73E1Ff0B80914AB6fe0444E65848C4C34450b") => Some(&CRONOS), + (1, addr) if addr == address!("0x08389495D7456E1951ddF7c3a1314A4bfb646d8B") => Some(&CRYPTERIUM), + (1, addr) if addr == address!("0xD533a949740bb3306d119CC777fa900bA034cd52") => Some(&CURVE_DAO_TOKEN), + (1, addr) if addr == address!("0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D") => Some(&CARTESI), + (1, addr) if addr == address!("0x321C2fE4446C7c963dc41Dd58879AF648838f98D") => Some(&CRYPTEX_FINANCE), + (1, addr) if addr == address!("0xDf801468a808a32656D2eD2D2d80B72A129739f4") => Some(&SOMNIUM_SPACE_CUBES), + (1, addr) if addr == address!("0x41e5560054824eA6B0732E656E3Ad64E20e94E45") => Some(&CIVIC), + (1, addr) if addr == address!("0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B") => Some(&CONVEX_FINANCE), + (1, addr) if addr == address!("0x7ABc8A5768E6bE61A6c693a6e4EAcb5B60602C4D") => Some(&COVALENT_X_TOKEN), + (1, addr) if addr == address!("0x6B175474E89094C44Da98b954EedeAC495271d0F") => Some(&DAI_STABLECOIN), + (1, addr) if addr == address!("0x081131434f93063751813C619Ecca9C4dC7862a3") => Some(&MINES_OF_DALARNIA), + (1, addr) if addr == address!("0x3A880652F47bFaa771908C07Dd8673A787dAEd3A") => Some(&DERIVADAO), + (1, addr) if addr == address!("0x3597bfD533a99c9aa083587B074434E61Eb0A258") => Some(&DENT), + (1, addr) if addr == address!("0xfB7B4564402E5500dB5bB6d63Ae671302777C75a") => Some(&DEXTOOLS), + (1, addr) if addr == address!("0x84cA8bc7997272c7CfB4D0Cd3D55cd942B3c9419") => Some(&DIA), + (1, addr) if addr == address!("0x0AbdAce70D3790235af448C88547603b945604ea") => Some(&DISTRICT0X), + (1, addr) if addr == address!("0x0F81001eF0A83ecCE5ccebf63EB302c70a39a654") => Some(&DOLOMITE), + (1, addr) if addr == address!("0x2aeAbde1aB736c59E9A19BeD67681869eEF39526") => Some(&DOVU), + (1, addr) if addr == address!("0x1494CA1F11D487c2bBe4543E90080AeBa4BA3C2b") => Some(&DEFI_PULSE_INDEX), + (1, addr) if addr == address!("0x3Ab6Ed69Ef663bd986Ee59205CCaD8A20F98b4c2") => Some(&DREP), + (1, addr) if addr == address!("0xB1D1eae60EEA9525032a6DCb4c1CE336a1dE71BE") => Some(&DERIVE), + (1, addr) if addr == address!("0x92D6C1e31e14520e676a687F0a93788B716BEff5") => Some(&DYDX), + (1, addr) if addr == address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17") => Some(&DEFI_YIELD_PROTOCOL), + (1, addr) if addr == address!("0xec53bF9167f50cDEB3Ae105f56099aaaB9061F83") => Some(&EIGENLAYER), + (1, addr) if addr == address!("0xe6fd75ff38Adca4B97FBCD938c86b98772431867") => Some(&ELASTOS), + (1, addr) if addr == address!("0x761D38e5ddf6ccf6Cf7c55759d5210750B5D60F3") => Some(&DOGELON_MARS), + (1, addr) if addr == address!("0x57e114B691Db790C35207b2e685D4A43181e6061") => Some(ÐENA), + (1, addr) if addr == address!("0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c") => Some(&ENJIN_COIN), + (1, addr) if addr == address!("0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72") => Some(ÐEREUM_NAME_SERVICE), + (1, addr) if addr == address!("0xE2AD0BF751834f2fbdC62A41014f84d67cA1de2A") => Some(&CALDERA), + (1, addr) if addr == address!("0xBBc2AE13b23d715c30720F079fcd9B4a74093505") => Some(ÐERNITY_CHAIN), + (1, addr) if addr == address!("0x031De51F3E8016514Bd0963d0B2AB825A591Db9A") => Some(&ESPRESSO), + (1, addr) if addr == address!("0xFe0c30065B384F05761f15d0CC899D4F9F9Cc0eB") => Some(ÐER_FI), + (1, addr) if addr == address!("0xd9Fcd98c322942075A5C3860693e9f4f03AAE07b") => Some(&EULER), + (1, addr) if addr == address!("0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c") => Some(&EURO_COIN), + (1, addr) if addr == address!("0x888883b5F5D21fb10Dfeb70e8f9722B9FB0E5E51") => Some(&SCHUMAN_EUR_P), + (1, addr) if addr == address!("0x8dF723295214Ea6f21026eeEb4382d475f146F9f") => Some(&QUANTOZ_EURQ), + (1, addr) if addr == address!("0x50753CfAf86c094925Bf976f218D043f8791e408") => Some(&STABLR_EURO), + (1, addr) if addr == address!("0xa0246c9032bC3A600820415aE600c6388619A14D") => Some(&HARVEST_FINANCE), + (1, addr) if addr == address!("0xaea46A60368A7bD060eec7DF8CBa43b7EF41Ad85") => Some(&FETCH_AI), + (1, addr) if addr == address!("0x7C135549504245B5eAe64fc0E99Fa5ebabb8e35D") => Some(&FIDELITY_DIGITAL_DOLLAR), + (1, addr) if addr == address!("0xef3A930e1FfFFAcd2fc13434aC81bD278B0ecC8d") => Some(&STAFI), + (1, addr) if addr == address!("0xcf0C122c6b73ff809C693DB761e7BaeBe62b6a2E") => Some(&FLOKI), + (1, addr) if addr == address!("0x720CD16b011b987Da3518fbf38c3071d4F0D1495") => Some(&FLUX), + (1, addr) if addr == address!("0x41545f8b9472D758bB669ed8EaEEEcD7a9C4Ec29") => Some(&FORTA), + (1, addr) if addr == address!("0x77FbA179C79De5B7653F68b5039Af940AdA60ce0") => Some(&LEFORTH_GOVERNANCE_TOKEN), + (1, addr) if addr == address!("0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d") => Some(&SHAPESHIFT_FOX_TOKEN), + (1, addr) if addr == address!("0x853d955aCEf822Db058eb8505911ED77F175b99e") => Some(&FRAX), + (1, addr) if addr == address!("0x4E15361FD6b4BB609Fa63C81A2be19d873717870") => Some(&FANTOM), + (1, addr) if addr == address!("0x8c15Ef5b4B21951d50E53E4fbdA8298FFAD25057") => Some(&FUNCTION_X), + (1, addr) if addr == address!("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0") => Some(&FRAX_SHARE), + (1, addr) if addr == address!("0x9C7BEBa8F6eF6643aBd725e45a4E8387eF260649") => Some(&GRAVITY), + (1, addr) if addr == address!("0x5fAa989Af96Af85384b8a938c2EdE4A7378D9875") => Some(&GALXE), + (1, addr) if addr == address!("0xd1d2Eb1B1e90B638588728b4130137D262C87cae") => Some(&GALA), + (1, addr) if addr == address!("0xdab396cCF3d84Cf2D07C4454e10C8A6F5b008D2b") => Some(&GOLDFINCH), + (1, addr) if addr == address!("0x3F382DbD960E3a9bbCeaE22651E88158d2791550") => Some(&AAVEGOTCHI), + (1, addr) if addr == address!("0x7DD9c5Cba05E151C895FDe1CF355C9A1D5DA6429") => Some(&GOLEM), + (1, addr) if addr == address!("0x6810e776880C02933D47DB1b9fc05908e5386b96") => Some(&GNOSIS_TOKEN), + (1, addr) if addr == address!("0xccC8cb5229B0ac8069C51fd58367Fd1e622aFD97") => Some(&GODS_UNCHAINED), + (1, addr) if addr == address!("0xc944E90C64B2c07662A292be6244BDf05Cda44a7") => Some(&THE_GRAPH), + (1, addr) if addr == address!("0xDe30da39c46104798bB5aA3fe8B9e0e1F348163F") => Some(&GITCOIN), + (1, addr) if addr == address!("0x056Fd409E1d7A124BD7017459dFEa2F387b6d5Cd") => Some(&GEMINI_DOLLAR), + (1, addr) if addr == address!("0x2798b1cC5A993085E8A9D46e80499F1B63f42204") => Some(ÐGAS), + (1, addr) if addr == address!("0xC08512927D12348F6620a698105e1BAac6EcD911") => Some(&GYEN), + (1, addr) if addr == address!("0xb3999F658C0391d94A37f7FF328F3feC942BcADC") => Some(&HASHFLOW), + (1, addr) if addr == address!("0x71Ab77b7dbB4fa7e017BC15090b2163221420282") => Some(&HIGHSTREET), + (1, addr) if addr == address!("0xF5581dFeFD8Fb0e4aeC526bE659CFaB1f8c781dA") => Some(&HOPR), + (1, addr) if addr == address!("0xB705268213D593B8FD88d3FDEFF93AFF5CbDcfAE") => Some(&IDEX), + (1, addr) if addr == address!("0x767FE9EDC9E0dF98E07454847909b5E959D7ca0E") => Some(&ILLUVIUM), + (1, addr) if addr == address!("0xb48c6B24f36307c7A1f2a9281E978a9ef2902BA5") => Some(&IMMUNEFI), + (1, addr) if addr == address!("0xF57e7e7C23978C3cAEC3C3548E3D615c346e79fF") => Some(&IMMUTABLE_X), + (1, addr) if addr == address!("0x0954906da0Bf32d5479e25f46056d22f08464cab") => Some(&INDEX_COOPERATIVE), + (1, addr) if addr == address!("0xe28b3B32B6c345A34Ff64674606124Dd5Aceca30") => Some(&INJECTIVE), + (1, addr) if addr == address!("0x41D5D79431A913C4aE7d69a668ecdfE5fF9DFB68") => Some(&INVERSE_FINANCE), + (1, addr) if addr == address!("0xdeF1b2D939EdC0E4d35806c59b3166F790175afe") => Some(&INFINEX), + (1, addr) if addr == address!("0x6fB3e0A217407EFFf7Ca062D46c26E5d60a14d69") => Some(&IOTEX), + (1, addr) if addr == address!("0x50f41F589aFACa2EF41FDF590FE7b90cD26DEe64") => Some(&IRYS), + (1, addr) if addr == address!("0x23894DC9da6c94ECb439911cAF7d337746575A72") => Some(&GEOJAM), + (1, addr) if addr == address!("0x7420B4b9a0110cdC71fB720908340C03F9Bc03EC") => Some(&JASMYCOIN), + (1, addr) if addr == address!("0x4B1E80cAC91e2216EEb63e29B957eB91Ae9C2Be8") => Some(&JUPITER), + (1, addr) if addr == address!("0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC") => Some(&KEEP_NETWORK), + (1, addr) if addr == address!("0x3f80B1c54Ae920Be41a77f8B902259D48cf24cCf") => Some(&KERNELDAO), + (1, addr) if addr == address!("0x4CC19356f2D37338b9802aa8E8fc58B0373296E7") => Some(&SELFKEY), + (1, addr) if addr == address!("0x904567252D8F48555b7447c67dCA23F0372E16be") => Some(&KITE), + (1, addr) if addr == address!("0xdd974D5C2e2928deA5F71b9825b8b646686BD200") => Some(&KYBER_NETWORK_CRYSTAL), + (1, addr) if addr == address!("0x1cEB5cB57C4D4E2b2433641b95Dd330A33185A44") => Some(&KEEP3RV1), + (1, addr) if addr == address!("0x464eBE77c293E473B48cFe96dDCf88fcF7bFDAC0") => Some(&KRYLL), + (1, addr) if addr == address!("0x96543ef8d2C75C26387c1a319ae69c0BEE6f3fe7") => Some(&KUJIRA), + (1, addr) if addr == address!("0x88909D489678dD17aA6D9609F89B0419Bf78FD9a") => Some(&LAYER3), + (1, addr) if addr == address!("0x0fc2a55d5BD13033f1ee0cdd11f60F7eFe66f467") => Some(&LAGRANGE), + (1, addr) if addr == address!("0x037A54AaB062628C9Bbae1FDB1583c195585fe41") => Some(&LCX), + (1, addr) if addr == address!("0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32") => Some(&LIDO_DAO), + (1, addr) if addr == address!("0x1789e0043623282D5DCc7F213d703C6D8BAfBB04") => Some(&LINEA), + (1, addr) if addr == address!("0x514910771AF9Ca656af840dff83E8264EcF986CA") => Some(&CHAINLINK_TOKEN), + (1, addr) if addr == address!("0xb59490aB09A0f526Cc7305822aC65f2Ab12f9723") => Some(&LITENTRY), + (1, addr) if addr == address!("0x232CE3bd40fCd6f80f3d55A522d03f25Df784Ee2") => Some(&LIGHTER), + (1, addr) if addr == address!("0x61E90A50137E1F645c9eF4a0d3A4f01477738406") => Some(&LEAGUE_OF_KINGDOMS), + (1, addr) if addr == address!("0xA4e8C3Ec456107eA67d3075bF9e3DF3A75823DB0") => Some(&LOOM_NETWORK), + (1, addr) if addr == address!("0x58b6A8A3302369DAEc383334672404Ee733aB239") => Some(&LIVEPEER), + (1, addr) if addr == address!("0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D") => Some(&LIQUITY), + (1, addr) if addr == address!("0xBBbbCA6A901c926F240b89EacB641d8Aec7AEafD") => Some(&LOOPRINGCOIN_V2), + (1, addr) if addr == address!("0xd0a6053f087E87a25dC60701ba6E663b1a548E85") => Some(&BLOCKLORDS), + (1, addr) if addr == address!("0x8c1BEd5b9a0928467c9B1341Da1D7BD5e10b6549") => Some(&LIQUID_STAKED_ETH), + (1, addr) if addr == address!("0x6033F7f88332B8db6ad452B7C6D5bB643990aE3f") => Some(&LISK), + (1, addr) if addr == address!("0x5f98805A4E8be255a32880FDeC7F6728C6568bA0") => Some(&LIQUITY_USD), + (1, addr) if addr == address!("0x0F5D2fB29fb7d3CFeE444a200298f468908cC942") => Some(&DECENTRALAND), + (1, addr) if addr == address!("0x69af81e73A73B40adF4f3d4223Cd9b1ECE623074") => Some(&MASK_NETWORK), + (1, addr) if addr == address!("0x08d967bb0134F2d07f7cfb6E246680c53927DD30") => Some(&MATH), + (1, addr) if addr == address!("0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0") => Some(&POLYGON), + (1, addr) if addr == address!("0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6") => Some(&MERIT_CIRCLE), + (1, addr) if addr == address!("0xfC98e825A2264D890F9a1e68ed50E1526abCcacD") => Some(&MOSS_CARBON_CREDIT), + (1, addr) if addr == address!("0x814e0908b12A99FeCf5BC101bB5d0b8B5cDf7d26") => Some(&MEASURABLE_DATA_TOKEN), + (1, addr) if addr == address!("0xb131f4A55907B10d1F0A50d8ab8FA09EC342cd74") => Some(&MEMECOIN), + (1, addr) if addr == address!("0x9E32b13ce7f2E80A01932B42553652E053D6ed8e") => Some(&METIS), + (1, addr) if addr == address!("0x99D8a9C45b2ecA8864373A26D1459e3Dff1e17F3") => Some(&MAGIC_INTERNET_MONEY), + (1, addr) if addr == address!("0x09a3EcAFa817268f77BE1283176B946C4ff2E608") => Some(&MIRROR_PROTOCOL), + (1, addr) if addr == address!("0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2") => Some(&MAKER), + (1, addr) if addr == address!("0xec67005c4E498Ec7f55E092bd1d35cbC47C91892") => Some(&MELON), + (1, addr) if addr == address!("0x3c3a81e81dc49A522A592e7622A7E711c06bf354") => Some(&MANTLE), + (1, addr) if addr == address!("0xaaeE1A9723aaDB7afA2810263653A34bA2C21C7a") => Some(&MOG_COIN), + (1, addr) if addr == address!("0x275f5Ad03be0Fa221B4C6649B8AeE09a42D9412A") => Some(&MONAVALE), + (1, addr) if addr == address!("0x58D97B57BB95320F9a05dC918Aef65434969c2B2") => Some(&MORPHO_TOKEN), + (1, addr) if addr == address!("0x3073f7aAA4DB83f95e9FFf17424F71D4751a3073") => Some(&MOVEMENT), + (1, addr) if addr == address!("0x33349B282065b0284d756F0577FB39c158F935e6") => Some(&MAPLE), + (1, addr) if addr == address!("0xF433089366899D83a9f26A773D59ec7eCF30355e") => Some(&METAL), + (1, addr) if addr == address!("0x65Ef703f5594D2573eb71Aaf55BC0CB548492df4") => Some(&MULTICHAIN), + (1, addr) if addr == address!("0xe2f2a5C287993345a840Db3B0845fbC70f5935a5") => Some(&MSTABLE_USD), + (1, addr) if addr == address!("0xB6Ca7399B4F9CA56FC27cBfF44F4d2e4Eef1fc81") => Some(&MUSE_DAO), + (1, addr) if addr == address!("0xAE788F80F2756A86aa2F410C651F2aF83639B95b") => Some(&GENSOKISHI_METAVERSE), + (1, addr) if addr == address!("0x5Ca381bBfb58f0092df149bD3D243b08B9a8386e") => Some(&MXC), + (1, addr) if addr == address!("0x9E46A38F5DaaBe8683E10793b06749EEF7D733d1") => Some(&POLYSWARM), + (1, addr) if addr == address!("0x812Ba41e071C7b7fA4EBcFB62dF5F45f6fA853Ee") => Some(&NEIRO), + (1, addr) if addr == address!("0xD0eC028a3D21533Fdd200838F39c85B03679285D") => Some(&NEWTON), + (1, addr) if addr == address!("0x5Cf04716BA20127F1E2297AdDCf4B5035000c9eb") => Some(&NKN), + (1, addr) if addr == address!("0x1776e1F26f98b1A5dF9cD347953a26dd3Cb46671") => Some(&NUMERAIRE), + (1, addr) if addr == address!("0x6e6F6d696e61decd6605bD4a57836c5DB6923340") => Some(&NOMINA), + (1, addr) if addr == address!("0x4fE83213D56308330EC302a8BD641f1d0113A4Cc") => Some(&NUCYPHER), + (1, addr) if addr == address!("0x967da4048cD07aB37855c090aAF366e4ce1b9F48") => Some(&OCEAN_PROTOCOL), + (1, addr) if addr == address!("0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26") => Some(&ORIGIN_PROTOCOL), + (1, addr) if addr == address!("0xd26114cd6EE289AccF82350c8d8487fedB8A0C07") => Some(&OMG_NETWORK), + (1, addr) if addr == address!("0x36E66fbBce51e4cD5bd3C62B637Eb411b18949D4") => Some(&OMNI_NETWORK), + (1, addr) if addr == address!("0xfAbA6f8e4a5E8Ab82F62fe7C39859FA577269BE3") => Some(&ONDO_FINANCE), + (1, addr) if addr == address!("0x6F59e0461Ae5E2799F1fB3847f05a63B16d0DbF8") => Some(&ORCA_ALLIANCE), + (1, addr) if addr == address!("0x0258F474786DdFd37ABCE6df6BBb1Dd5dfC4434a") => Some(&ORION_PROTOCOL), + (1, addr) if addr == address!("0x4575f41308EC1483f3d399aa9a2826d74Da13Deb") => Some(&ORCHID), + (1, addr) if addr == address!("0xc1D204d77861dEf49b6E769347a883B15EC397Ff") => Some(&PAYPEREX), + (1, addr) if addr == address!("0x45804880De22913dAFE09f4980848ECE6EcbAf78") => Some(&PAX_GOLD), + (1, addr) if addr == address!("0x0D3CbED3f69EE050668ADF3D9Ea57241cBa33A2B") => Some(&PLAYDAPP), + (1, addr) if addr == address!("0x808507121B80c02388fAd14726482e061B8da827") => Some(&PENDLE), + (1, addr) if addr == address!("0x6982508145454Ce325dDbE47a25d4ec3d2311933") => Some(&PEPE), + (1, addr) if addr == address!("0xbC396689893D065F41bc2C6EcbeE5e0085233447") => Some(&PERPETUAL_PROTOCOL), + (1, addr) if addr == address!("0x7613C48E0cd50E42dD9Bf0f6c235063145f6f8DC") => Some(&PIRATE_NATION), + (1, addr) if addr == address!("0xD8912C10681D8B21Fd3742244f44658dBA12264E") => Some(&PLUTON), + (1, addr) if addr == address!("0x4C1746A800D224393fE2470C70A35717eD4eA5F1") => Some(&PLUME), + (1, addr) if addr == address!("0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6") => Some(&POLYGON_ECOSYSTEM_TOKEN), + (1, addr) if addr == address!("0x83e6f1E41cdd28eAcEB20Cb649155049Fac3D5Aa") => Some(&POLKASTARTER), + (1, addr) if addr == address!("0x9992eC3cF6A55b00978cdDF2b27BC6882d88D1eC") => Some(&POLYMATH), + (1, addr) if addr == address!("0x57B946008913B82E4dF85f501cbAeD910e58D26C") => Some(&MARLIN), + (1, addr) if addr == address!("0x1Bbe973BeF3a977Fc51CbED703E8ffDEfE001Fed") => Some(&PORTAL), + (1, addr) if addr == address!("0x595832F8FC6BF59c85C527fEC3740A1b7a361269") => Some(&POWER_LEDGER), + (1, addr) if addr == address!("0xb23d80f5FefcDDaa212212F028021B41DEd428CF") => Some(&PRIME), + (1, addr) if addr == address!("0x226bb599a12C826476e3A771454697EA52E9E220") => Some(&PROPY), + (1, addr) if addr == address!("0x6BEF15D938d4E72056AC92Ea4bDD0D76B1C4ad29") => Some(&SUCCINCT), + (1, addr) if addr == address!("0x362bc847A3a9637d3af6624EeC853618a43ed7D2") => Some(&PARSIQ), + (1, addr) if addr == address!("0xfB5c6815cA3AC72Ce9F5006869AE67f18bF77006") => Some(&PSTAKE_FINANCE), + (1, addr) if addr == address!("0x4d1C297d39C5c1277964D0E3f8Aa901493664530") => Some(&PUFFER_FINANCE), + (1, addr) if addr == address!("0x6c3ea9036406852006290770BEdFcAbA0e23A0e8") => Some(&PAYPAL_USD), + (1, addr) if addr == address!("0x4a220E6096B25EADb88358cb44068A3248254675") => Some(&QUANT), + (1, addr) if addr == address!("0x4123a133ae3c521FD134D7b13A2dEC35b56c2463") => Some(&QREDO), + (1, addr) if addr == address!("0x99ea4dB9EE77ACD40B119BD1dC4E33e1C070b80d") => Some(&QUANTSTAMP), + (1, addr) if addr == address!("0x6c28AeF8977c9B773996d0e8376d2EE379446F2f") => Some(&QUICKSWAP), + (1, addr) if addr == address!("0x31c8EAcBFFdD875c74b94b077895Bd78CF1E64A3") => Some(&RADICLE), + (1, addr) if addr == address!("0x03ab458634910AaD20eF5f1C8ee96F1D6ac54919") => Some(&RAI_REFLEX_INDEX), + (1, addr) if addr == address!("0xba5BDe662c17e2aDFF1075610382B9B691296350") => Some(&SUPERRARE), + (1, addr) if addr == address!("0xFca59Cd816aB1eaD66534D82bc21E7515cE441CF") => Some(&RARIBLE), + (1, addr) if addr == address!("0xA4EED63db85311E22dF4473f87CcfC3DaDCFA3E3") => Some(&RUBIC), + (1, addr) if addr == address!("0x6123B0049F904d730dB3C36a31167D9d4121fA6B") => Some(&RIBBON_FINANCE), + (1, addr) if addr == address!("0xc43C6bfeDA065fE2c4c11765Bf838789bd0BB5dE") => Some(&REDSTONE), + (1, addr) if addr == address!("0x408e41876cCCDC0F92210600ef50372656052a38") => Some(&REPUBLIC_TOKEN), + (1, addr) if addr == address!("0x1985365e9f78359a9B6AD760e32412f4a445E862") => Some(&REPUTATION_AUGUR_V1), + (1, addr) if addr == address!("0x221657776846890989a759BA2973e427DfF5C9bB") => Some(&REPUTATION_AUGUR_V2), + (1, addr) if addr == address!("0x8f8221aFbB33998d8584A2B05749bA73c37a938a") => Some(&REQUEST), + (1, addr) if addr == address!("0x557B933a7C2c45672B610F8954A3deB39a51A8Ca") => Some(&REVV), + (1, addr) if addr == address!("0x3B50805453023a91a8bf641e279401a0b23FA6F9") => Some(&RENZO), + (1, addr) if addr == address!("0xD291E7a03283640FDc51b121aC401383A46cC623") => Some(&RARI_GOVERNANCE_TOKEN), + (1, addr) if addr == address!("0x607F4C5BB672230e8672085532f7e901544a7375") => Some(&IEXEC_RLC), + (1, addr) if addr == address!("0xB5F7b021a78f470d31D762C1DDA05ea549904fbd") => Some(&RAYLS), + (1, addr) if addr == address!("0x8292Bb45bf1Ee4d140127049757C2E0fF06317eD") => Some(&RLUSD), + (1, addr) if addr == address!("0xf1f955016EcbCd7321c7266BccFB96c68ea5E49b") => Some(&RALLY), + (1, addr) if addr == address!("0x6De037ef9aD2725EB40118Bb1702EBb27e4Aeb24") => Some(&RENDER_TOKEN), + (1, addr) if addr == address!("0x32b4d049fE4c888D2b92eEcaf729F44DF6B1F36E") => Some(&ROBO_TOKEN), + (1, addr) if addr == address!("0xfA5047c9c78B8877af97BDcb85Db743fD7313d4a") => Some(&ROOK), + (1, addr) if addr == address!("0xD33526068D116cE69F19A9ee46F0bd304F21A51f") => Some(&ROCKET_POOL_PROTOCOL), + (1, addr) if addr == address!("0x320623b8E4fF03373931769A31Fc52A4E78B5d70") => Some(&RESERVE_RIGHTS), + (1, addr) if addr == address!("0x5aFE3855358E112B5647B952709E6165e1c1eEEe") => Some(&SAFE), + (1, addr) if addr == address!("0x3845badAde8e6dFF049820680d1F14bD3903a5d0") => Some(&THE_SANDBOX), + (1, addr) if addr == address!("0x30D20208d987713f46DFD34EF128Bb16C404D10f") => Some(&STADER), + (1, addr) if addr == address!("0x56A3BA04E95d34268A19b2a4474DC979baBDaf76") => Some(&SENTIENT), + (1, addr) if addr == address!("0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE") => Some(&SHIBA_INU), + (1, addr) if addr == address!("0x7C84e62859D0715eb77d1b1C4154Ecd6aBB21BEC") => Some(&SHPING), + (1, addr) if addr == address!("0x00c83aeCC790e8a4453e5dD3B0B4b3680501a7A7") => Some(&SKALE), + (1, addr) if addr == address!("0x56072C95FAA701256059aa122697B133aDEd9279") => Some(&SKY_GOVERNANCE_TOKEN), + (1, addr) if addr == address!("0xCC8Fa225D80b9c7D42F96e9570156c65D6cAAa25") => Some(&SMOOTH_LOVE_POTION), + (1, addr) if addr == address!("0x744d70FDBE2Ba4CF95131626614a1763DF805B9E") => Some(&STATUS), + (1, addr) if addr == address!("0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F") => Some(&SYNTHETIX_NETWORK_TOKEN), + (1, addr) if addr == address!("0x23B608675a2B2fB1890d3ABBd85c5775c51691d5") => Some(&UNISOCKS), + (1, addr) if addr == address!("0xD31a59c85aE9D8edEFeC411D448f90841571b89c") => Some(&SOL_WORMHOLE), + (1, addr) if addr == address!("0x090185f2135308BaD17527004364eBcC2D37e5F6") => Some(&SPELL_TOKEN), + (1, addr) if addr == address!("0xc20059e0317DE91738d13af027DfC4a50781b066") => Some(&SPARK), + (1, addr) if addr == address!("0xE0f63A424a4439cBE457D80E4f4b51aD25b2c56C") => Some(&SPX6900), + (1, addr) if addr == address!("0xAf5191B0De278C7286d6C7CC6ab6BB8A73bA2Cd6") => Some(&STARGATE_FINANCE), + (1, addr) if addr == address!("0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC") => Some(&STORJ_TOKEN), + (1, addr) if addr == address!("0xCa14007Eff0dB1f8135f4C25B34De49AB0d42766") => Some(&STARKNET), + (1, addr) if addr == address!("0x006BeA43Baa3f7A6f765F14f10A1a1b08334EF45") => Some(&STOX), + (1, addr) if addr == address!("0x0763fdCCF1aE541A5961815C0872A8c5Bc6DE4d7") => Some(&SUKU), + (1, addr) if addr == address!("0xe53EC727dbDEB9E2d5456c3be40cFF031AB40A55") => Some(&SUPERFARM), + (1, addr) if addr == address!("0x57Ab1ec28D129707052df4dF418D58a2D46d5f51") => Some(&SYNTH_SUSD), + (1, addr) if addr == address!("0x6B3595068778DD592e39A122f4f5a5cF09C90fE2") => Some(&SUSHI), + (1, addr) if addr == address!("0x0a6E7Ba5042B38349e437ec6Db6214AEC7B35676") => Some(&SWELL), + (1, addr) if addr == address!("0x0bb217E40F8a5Cb79Adf04E1aAb60E5abd0dfC1e") => Some(&SWFTCOIN), + (1, addr) if addr == address!("0x8CE9137d39326AD0cD6491fb5CC0CbA0e089b6A9") => Some(&SWIPE), + (1, addr) if addr == address!("0xE6Bfd33F52d82Ccb5b37E16D3dD81f9FFDAbB195") => Some(&SPACE_AND_TIME), + (1, addr) if addr == address!("0xf293d23BF2CDc05411Ca0edDD588eb1977e8dcd4") => Some(&SYLO), + (1, addr) if addr == address!("0x0f2D719407FdBeFF09D87557AbB7232601FD9F29") => Some(&SYNAPSE), + (1, addr) if addr == address!("0x643C4E15d7d62Ad0aBeC4a9BD4b001aA3Ef52d66") => Some(&SYRUP_TOKEN), + (1, addr) if addr == address!("0xCdF7028ceAB81fA0C6971208e83fa7872994beE5") => Some(&THRESHOLD_NETWORK), + (1, addr) if addr == address!("0x18084fbA666a33d37592fA2633fD49a74DD93a88") => Some(&TBTC), + (1, addr) if addr == address!("0xC3d21f79C3120A4fFda7A535f8005a7c297799bF") => Some(&TERM_FINANCE), + (1, addr) if addr == address!("0xafFbe9a60F1F45E057FD9b6DC70004Bb0Ccc8b99") => Some(&THEORIQ), + (1, addr) if addr == address!("0x485d17A6f1B8780392d53D64751824253011A260") => Some(&CHRONOTECH), + (1, addr) if addr == address!("0x888888848B652B3E3a0f34c96E00EEC0F3a23F72") => Some(&ALIEN_WORLDS), + (1, addr) if addr == address!("0x2e9d63788249371f1DFC918a52f8d799F4a38C94") => Some(&TOKEMAK), + (1, addr) if addr == address!("0x4507cEf57C46789eF8d1a19EA45f4216bae2B528") => Some(&TOKENFI), + (1, addr) if addr == address!("0x2Ab6Bb8408ca3199B8Fa6C92d5b455F820Af03c4") => Some(&TE_FOOD), + (1, addr) if addr == address!("0xaA7a9CA87d3694B5755f213B5D04094b8d0F0A6F") => Some(&ORIGINTRAIL), + (1, addr) if addr == address!("0x88dF592F8eb5D7Bd38bFeF7dEb0fBc02cf3778a0") => Some(&TELLOR), + (1, addr) if addr == address!("0x77146784315Ba81904d654466968e3a7c196d1f3") => Some(&TREEHOUSE_TOKEN), + (1, addr) if addr == address!("0x228bEC415adE4b61D7CaF0adf8C91EAc587BA369") => Some(&TRIA), + (1, addr) if addr == address!("0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B") => Some(&TRIBE), + (1, addr) if addr == address!("0x4C19596f5aAfF459fA38B0f7eD92F11AE6543784") => Some(&TRUEFI), + (1, addr) if addr == address!("0xA35923162C49cF95e6BF26623385eb431ad920D3") => Some(&TURBO), + (1, addr) if addr == address!("0xd084B83C305daFD76AE3E1b4E1F1fe2eCcCb3988") => Some(&THE_VIRTUA_KOLECT), + (1, addr) if addr == address!("0x04Fa0d235C4abf4BcF4787aF4CF447DE572eF828") => Some(&UMA_VOTING_TOKEN_V1), + (1, addr) if addr == address!("0x441761326490cACF7aF299725B6292597EE822c2") => Some(&UNIFI_PROTOCOL_DAO), + (1, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP), + (1, addr) if addr == address!("0x70D2b7C19352bB76e4409858FF5746e500f2B67c") => Some(&PAWTOCOL), + (1, addr) if addr == address!("0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d") => Some(&WORLD_LIBERTY_FINANCIAL_USD), + (1, addr) if addr == address!("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") => Some(&USDCOIN), + (1, addr) if addr == address!("0xe343167631d89B6Ffc58B88d6b7fB0228795491D") => Some(&GLOBAL_DOLLAR), + (1, addr) if addr == address!("0x8E870D67F660D95d5be530380D0eC0bd388289E1") => Some(&PAX_DOLLAR), + (1, addr) if addr == address!("0xc83e27f270cce0A3A3A29521173a83F402c1768b") => Some(&QUANTOZ_USDQ), + (1, addr) if addr == address!("0x7B43E3875440B44613DC3bC08E7763e6Da63C8f8") => Some(&STABLR_USD), + (1, addr) if addr == address!("0xdC035D45d973E3EC169d2276DDab16f1e407384F") => Some(&USDS_STABLECOIN), + (1, addr) if addr == address!("0xdAC17F958D2ee523a2206206994597C13D831ec7") => Some(&TETHER_USD), + (1, addr) if addr == address!("0xC4441c2BE5d8fA8126822B9929CA0b81Ea0DE38E") => Some(&USUAL), + (1, addr) if addr == address!("0x8DE5B80a0C1B02Fe4976851D030B36122dbb8624") => Some(&VANRY), + (1, addr) if addr == address!("0x3C4B6E6e1eA3D4863700D7F76b36B7f3D3f13E3d") => Some(&VOYAGER_TOKEN), + (1, addr) if addr == address!("0xEDB171C18cE90B633DB442f2A6F72874093b49Ef") => Some(&WRAPPED_AMPLEFORTH), + (1, addr) if addr == address!("0xf983da3ca66964C02628189Ea8Ca99fa9E24f66c") => Some(&WRAPPED_ANALOG_ONE_TOKEN), + (1, addr) if addr == address!("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599") => Some(&WRAPPED_BTC), + (1, addr) if addr == address!("0xc221b7E65FfC80DE234bbB6667aBDd46593D34F0") => Some(&WRAPPED_CENTRIFUGE), + (1, addr) if addr == address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945") => Some(&WALLETCONNECT_TOKEN), + (1, addr) if addr == address!("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") => Some(&WRAPPED_ETHER), + (1, addr) if addr == address!("0xdA5e1988097297dCdc1f90D4dFE7909e847CBeF6") => Some(&WORLD_LIBERTY_FINANCIAL), + (1, addr) if addr == address!("0x4691937a7508860F876c9c0a2a617E7d9E945D4B") => Some(&WOO_NETWORK), + (1, addr) if addr == address!("0xCEDbEA37C8872c4171259Cdfd5255CB8923Cf8e7") => Some(&ANOMA), + (1, addr) if addr == address!("0x68749665FF8D2d112Fa859AA293F07A622782F38") => Some(&TETHER_GOLD), + (1, addr) if addr == address!("0xA2cd3D43c775978A96BdBf12d733D5A1ED94fb18") => Some(&CHAIN), + (1, addr) if addr == address!("0x70e8dE73cE538DA2bEEd35d14187F6959a8ecA96") => Some(&XSGD), + (1, addr) if addr == address!("0x55296f69f40Ea6d20E478533C15A6B08B654E758") => Some(&XYO_NETWORK), + (1, addr) if addr == address!("0x01791F726B4103694969820be083196cC7c045fF") => Some(&YIELD_BASIS), + (1, addr) if addr == address!("0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e") => Some(&YEARN_FINANCE), + (1, addr) if addr == address!("0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83") => Some(&DFI_MONEY), + (1, addr) if addr == address!("0x25f8087EAD173b73D6e8B84329989A8eEA16CF73") => Some(&YIELD_GUILD_GAMES), + (1, addr) if addr == address!("0xA12CC123ba206d4031D1c7f6223D1C2Ec249f4f3") => Some(&ZAMA), + (1, addr) if addr == address!("0xf091867EC603A6628eD83D274E835539D82e9cc8") => Some(&ZETACHAIN), + (1, addr) if addr == address!("0x000006c2A22ff4A44ff1f5d0F2ed65F781F55555") => Some(&BOUNDLESS), + (1, addr) if addr == address!("0xe1Be424F442D0687129128C6c38aAce44F8c8Dbc") => Some(&ZKPASS), + (1, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO), + (1, addr) if addr == address!("0xE41d2489571d322189246DaFA5ebDe1F4699F498") => Some(&TOKEN_0X_PROTOCOL_TOKEN), + (3, addr) if addr == address!("0xaD6D458402F60fD3Bd25163575031ACDce07538D") => Some(&DAI_STABLECOIN_3_CE07538D), + (3, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP_3_4201F984), + (3, addr) if addr == address!("0xc778417E063141139Fce010982780140Aa0cD5Ab") => Some(&WRAPPED_ETHER_3_AA0CD5AB), + (4, addr) if addr == address!("0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735") => Some(&DAI_STABLECOIN_4_A8FC4735), + (4, addr) if addr == address!("0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85") => Some(&MAKER_4_359AAD85), + (4, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP_4_4201F984), + (4, addr) if addr == address!("0xc778417E063141139Fce010982780140Aa0cD5Ab") => Some(&WRAPPED_ETHER_4_AA0CD5AB), + (5, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP_5_4201F984), + (5, addr) if addr == address!("0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6") => Some(&WRAPPED_ETHER_5_2B2208D6), + (10, addr) if addr == address!("0xAd42D013ac31486B73b6b059e748172994736426") => Some(&TOKEN_1INCH_10_94736426), + (10, addr) if addr == address!("0x76FB31fb4af56892A25e32cFC43De717950c9278") => Some(&AAVE_10_950C9278), + (10, addr) if addr == address!("0xFf733b2A3557a7ed6697007ab5D11B79FdD1b76B") => Some(&ACROSS_PROTOCOL_TOKEN_10_FDD1B76B), + (10, addr) if addr == address!("0x334cc734866E97D8452Ae6261d68Fd9bc9BFa31E") => Some(&ARPA_CHAIN_10_C9BFA31E), + (10, addr) if addr == address!("0xFE8B128bA8C78aabC59d4c64cEE7fF28e9379921") => Some(&BALANCER_10_E9379921), + (10, addr) if addr == address!("0xd6909e9e702024eb93312B989ee46794c0fB1C9D") => Some(&BICONOMY_10_C0FB1C9D), + (10, addr) if addr == address!("0x07ad578FF86B135bE19A12759064b802Cb88854D") => Some(&BOBA_NETWORK_10_CB88854D), + (10, addr) if addr == address!("0x3e7eF8f50246f725885102E8238CBba33F276747") => Some(&BARNBRIDGE_10_3F276747), + (10, addr) if addr == address!("0xEd50aCE88bd42B45cB0F49be15395021E141254e") => Some(&BRAINTRUST_10_E141254E), + (10, addr) if addr == address!("0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39") => Some(&BINANCE_USD_10_39D2DB39), + (10, addr) if addr == address!("0xadDb6A0412DE1BA0F936DCaeb8Aaa24578dcF3B2") => Some(&COINBASE_WRAPPED_STAKED_ETH_10_78DCF3B2), + (10, addr) if addr == address!("0x9b88D293b7a791E40d36A39765FFd5A1B9b5c349") => Some(&CELO_NATIVE_ASSET_WORMHOLE_10_B9B5C349), + (10, addr) if addr == address!("0x0994206dfE8De6Ec6920FF4D779B0d950605Fb53") => Some(&CURVE_DAO_TOKEN_10_0605FB53), + (10, addr) if addr == address!("0xEc6adef5E1006bb305bB1975333e8fc4071295bf") => Some(&CARTESI_10_071295BF), + (10, addr) if addr == address!("0x14778860E937f509e651192a90589dE711Fb88a9") => Some(&CYBER), + (10, addr) if addr == address!("0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1") => Some(&DAI_STABLECOIN_10_C9000DA1), + (10, addr) if addr == address!("0x33800De7E817A70A694F31476313A7c572BBa100") => Some(&DERIVE_10_72BBA100), + (10, addr) if addr == address!("0x65559aA14915a70190438eF90104769e5E890A00") => Some(ÐEREUM_NAME_SERVICE_10_5E890A00), + (10, addr) if addr == address!("0xD8737CA46aa6285dE7B8777a8e3db232911baD41") => Some(&STAFI_10_911BAD41), + (10, addr) if addr == address!("0xF1a0DA3367BC7aa04F8D94BA57B862ff37CeD174") => Some(&SHAPESHIFT_FOX_TOKEN_10_37CED174), + (10, addr) if addr == address!("0x2E3D870790dC77A83DD1d18184Acc7439A53f475") => Some(&FRAX_10_9A53F475), + (10, addr) if addr == address!("0x67CCEA5bb16181E7b4109c9c2143c24a1c2205Be") => Some(&FRAX_SHARE_10_1C2205BE), + (10, addr) if addr == address!("0x1EBA7a6a72c894026Cd654AC5CDCF83A46445B08") => Some(&GITCOIN_10_46445B08), + (10, addr) if addr == address!("0x589d35656641d6aB57A545F08cf473eCD9B6D5F7") => Some(&GYEN_10_D9B6D5F7), + (10, addr) if addr == address!("0x2ed6222CB75E353b8789bec7Bb443b7eC9022021") => Some(&KRYLL_10_C9022021), + (10, addr) if addr == address!("0x3A18dcC9745eDcD1Ef33ecB93b0b6eBA5671e7Ca") => Some(&KUJIRA_10_5671E7CA), + (10, addr) if addr == address!("0xFdb794692724153d1488CcdBE0C56c252596735F") => Some(&LIDO_DAO_10_2596735F), + (10, addr) if addr == address!("0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6") => Some(&CHAINLINK_TOKEN_10_38FFA7F6), + (10, addr) if addr == address!("0xFEaA9194F9F8c1B65429E31341a103071464907E") => Some(&LOOPRINGCOIN_V2_10_1464907E), + (10, addr) if addr == address!("0xc40F949F8a4e094D1b49a23ea9241D289B7b2819") => Some(&LIQUITY_USD_10_9B7B2819), + (10, addr) if addr == address!("0x3390108E913824B8eaD638444cc52B9aBdF63798") => Some(&MASK_NETWORK_10_BDF63798), + (10, addr) if addr == address!("0xab7bAdEF82E9Fe11f6f33f87BC9bC2AA27F2fCB5") => Some(&MAKER_10_27F2FCB5), + (10, addr) if addr == address!("0x2561aa2bB1d2Eb6629EDd7b0938d7679B8b49f9E") => Some(&OCEAN_PROTOCOL_10_B8B49F9E), + (10, addr) if addr == address!("0x4200000000000000000000000000000000000042") => Some(&OPTIMISM), + (10, addr) if addr == address!("0xBC7B1Ff1c6989f006a1185318eD4E7b5796e66E1") => Some(&PENDLE_10_796E66E1), + (10, addr) if addr == address!("0xC1c167CC44f7923cd0062c4370Df962f9DDB16f5") => Some(&PEPE_10_9DDB16F5), + (10, addr) if addr == address!("0x9e1028F5F1D5eDE59748FFceE5532509976840E0") => Some(&PERPETUAL_PROTOCOL_10_976840E0), + (10, addr) if addr == address!("0x7FB688CCf682d58f86D7e38e03f9D22e7705448B") => Some(&RAI_REFLEX_INDEX_10_7705448B), + (10, addr) if addr == address!("0xB548f63D4405466B36C0c0aC3318a22fDcec711a") => Some(&RARI_GOVERNANCE_TOKEN_10_DCEC711A), + (10, addr) if addr == address!("0xC81D1F0EB955B0c020E5d5b264E1FF72c14d1401") => Some(&ROCKET_POOL_PROTOCOL_10_C14D1401), + (10, addr) if addr == address!("0x650AF3C15AF43dcB218406d30784416D64Cfb6B2") => Some(&STATUS_10_64CFB6B2), + (10, addr) if addr == address!("0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4") => Some(&SYNTHETIX_NETWORK_TOKEN_10_3D7599B4), + (10, addr) if addr == address!("0xba1Cf949c382A32a09A17B2AdF3587fc7fA664f1") => Some(&SOL_WORMHOLE_10_7FA664F1), + (10, addr) if addr == address!("0xEf6301DA234fC7b0545c6E877D3359FE0B9E50a4") => Some(&SUKU_10_0B9E50A4), + (10, addr) if addr == address!("0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9") => Some(&SYNTH_SUSD_10_751EC8D9), + (10, addr) if addr == address!("0x3eaEb77b03dBc0F6321AE1b72b2E9aDb0F60112B") => Some(&SUSHI_10_0F60112B), + (10, addr) if addr == address!("0x747e42Eb0591547a0ab429B3627816208c734EA7") => Some(&THRESHOLD_NETWORK_10_8C734EA7), + (10, addr) if addr == address!("0xaf8cA653Fa2772d58f4368B0a71980e9E3cEB888") => Some(&TELLOR_10_E3CEB888), + (10, addr) if addr == address!("0xE7798f023fC62146e8Aa1b36Da45fb70855a77Ea") => Some(&UMA_VOTING_TOKEN_V1_10_855A77EA), + (10, addr) if addr == address!("0x6fd9d7AD17242c41f7131d257212c54A0e816691") => Some(&UNISWAP_10_0E816691), + (10, addr) if addr == address!("0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85") => Some(&USDCOIN_10_D097FF85), + (10, addr) if addr == address!("0x7F5c764cBc14f9669B88837ca1490cCa17c31607") => Some(&USDCOIN_BRIDGED_FROM_ETHEREUM), + (10, addr) if addr == address!("0x94b008aA00579c1307B0EF2c499aD98a8ce58e58") => Some(&TETHER_USD_10_8CE58E58), + (10, addr) if addr == address!("0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db") => Some(&VELODROME_FINANCE), + (10, addr) if addr == address!("0x68f180fcCe6836688e9084f035309E29Bf0A2095") => Some(&WRAPPED_BTC_10_BF0A2095), + (10, addr) if addr == address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945") => Some(&WALLETCONNECT_TOKEN_10_DD927945), + (10, addr) if addr == address!("0x4200000000000000000000000000000000000006") => Some(&WRAPPED_ETHER_10_00000006), + (10, addr) if addr == address!("0xdC6fF44d5d932Cbd77B52E5612Ba0529DC6226F1") => Some(&WORLDCOIN), + (10, addr) if addr == address!("0x871f2F2ff935FD1eD867842FF2a7bfD051A5E527") => Some(&WOO_NETWORK_10_51A5E527), + (10, addr) if addr == address!("0x9db118D43069B73B8a252bF0be49d50Edbd81fc8") => Some(&XYO_NETWORK_10_DBD81FC8), + (10, addr) if addr == address!("0x9046D36440290FfDE54FE0DD84Db8b1CfEE9107B") => Some(&YEARN_FINANCE_10_FEE9107B), + (10, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_10_F13271CD), + (10, addr) if addr == address!("0xD1917629B3E6A72E6772Aab5dBe58Eb7FA3C2F33") => Some(&TOKEN_0X_PROTOCOL_TOKEN_10_FA3C2F33), + (42, addr) if addr == address!("0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa") => Some(&DAI_STABLECOIN_42_B64CA6AA), + (42, addr) if addr == address!("0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD") => Some(&MAKER_42_71A4FFCD), + (42, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP_42_4201F984), + (42, addr) if addr == address!("0xd0A1E359811322d97991E03f863a0C30C2cF029C") => Some(&WRAPPED_ETHER_42_C2CF029C), + (56, addr) if addr == address!("0x111111111117dC0aa78b770fA6A738034120C302") => Some(&TOKEN_1INCH_56_4120C302), + (56, addr) if addr == address!("0xfb6115445Bff7b52FeB98650C87f44907E58f802") => Some(&AAVE_56_7E58F802), + (56, addr) if addr == address!("0xBc7d6B50616989655AfD682fb42743507003056D") => Some(&ALCHEMY_PAY_56_7003056D), + (56, addr) if addr == address!("0x6bfF4Fb161347ad7de4A625AE5aa3A1CA7077819") => Some(&AMBIRE_ADEX_56_A7077819), + (56, addr) if addr == address!("0x12f31B73D812C6Bb0d735a218c086d44D5fe5f89") => Some(&AGEUR_56_D5FE5F89), + (56, addr) if addr == address!("0x33d08D8C7a168333a85285a68C0042b39fC3741D") => Some(&AIOZ_NETWORK_56_9FC3741D), + (56, addr) if addr == address!("0x82D2f8E02Afb160Dd5A480a617692e62de9038C4") => Some(&ALEPH_IM_56_DE9038C4), + (56, addr) if addr == address!("0xAC51066d7bEC65Dc4589368da368b212745d63E8") => Some(&MY_NEIGHBOR_ALICE_56_745D63E8), + (56, addr) if addr == address!("0xa1faa113cbE53436Df28FF0aEe54275c13B40975") => Some(&ALPHA_VENTURE_DAO_56_13B40975), + (56, addr) if addr == address!("0xf307910A4c7bbc79691fD374889b36d8531B08e3") => Some(&ANKR_56_531B08E3), + (56, addr) if addr == address!("0x6F769E65c14Ebd1f68817F5f1DcDb61Cfa2D6f7e") => Some(&ARPA_CHAIN_56_FA2D6F7E), + (56, addr) if addr == address!("0x000Ae314E2A2172a039B26378814C252734f556A") => Some(&ASTER), + (56, addr) if addr == address!("0xA2120b9e674d3fC3875f415A7DF52e382F141225") => Some(&AUTOMATA_56_2F141225), + (56, addr) if addr == address!("0x8b1f4432F943c465A973FeDC6d7aa50Fc96f1f65") => Some(&AXELAR_56_C96F1F65), + (56, addr) if addr == address!("0x715D400F88C167884bbCc41C5FeA407ed4D2f8A0") => Some(&AXIE_INFINITY_56_D4D2F8A0), + (56, addr) if addr == address!("0x935a544Bf5816E3A7C13DB2EFe3009Ffda0aCdA2") => Some(&BLUZELLE_56_DA0ACDA2), + (56, addr) if addr == address!("0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56") => Some(&BINANCE_USD_56_DD087D56), + (56, addr) if addr == address!("0xaEC945e04baF28b135Fa7c640f624f8D90F1C3a6") => Some(&COIN98_56_90F1C3A6), + (56, addr) if addr == address!("0xf9CeC8d50f6c8ad3Fb6dcCEC577e05aA32B224FE") => Some(&CHROMIA_56_32B224FE), + (56, addr) if addr == address!("0x09E889BB4D5b474f561db0491C38702F367A4e4d") => Some(&CLOVER_FINANCE_56_367A4E4D), + (56, addr) if addr == address!("0x52CE071Bd9b1C4B00A0b92D298c512478CaD67e8") => Some(&COMPOUND_56_8CAD67E8), + (56, addr) if addr == address!("0xd15CeE1DEaFBad6C0B3Fd7489677Cc102B141464") => Some(&CIRCUITS_OF_VALUE_56_2B141464), + (56, addr) if addr == address!("0x8dA443F84fEA710266C8eB6bC34B71702d033EF2") => Some(&CARTESI_56_2D033EF2), + (56, addr) if addr == address!("0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3") => Some(&DAI_STABLECOIN_56_58B1DBC3), + (56, addr) if addr == address!("0x23CE9e926048273eF83be0A3A8Ba9Cb6D45cd978") => Some(&MINES_OF_DALARNIA_56_D45CD978), + (56, addr) if addr == address!("0xe91a8D2c584Ca93C7405F15c22CdFE53C29896E3") => Some(&DEXTOOLS_56_C29896E3), + (56, addr) if addr == address!("0x99956D38059cf7bEDA96Ec91Aa7BB2477E0901DD") => Some(&DIA_56_7E0901DD), + (56, addr) if addr == address!("0xEC583f25A049CC145dA9A256CDbE9B6201a705Ff") => Some(&DREP_56_01A705FF), + (56, addr) if addr == address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17") => Some(&DEFI_YIELD_PROTOCOL_56_91BCEF17), + (56, addr) if addr == address!("0x7bd6FaBD64813c48545C9c0e312A0099d9be2540") => Some(&DOGELON_MARS_56_D9BE2540), + (56, addr) if addr == address!("0x4B5C23cac08a567ecf0c1fFcA8372A45a5D33743") => Some(&HARVEST_FINANCE_56_A5D33743), + (56, addr) if addr == address!("0x031b41e504677879370e9DBcF937283A8691Fa7f") => Some(&FETCH_AI_56_8691FA7F), + (56, addr) if addr == address!("0xfb5B838b6cfEEdC2873aB27866079AC55363D37E") => Some(&FLOKI_56_5363D37E), + (56, addr) if addr == address!("0x90C97F71E18723b0Cf0dfa30ee176Ab653E89F40") => Some(&FRAX_56_53E89F40), + (56, addr) if addr == address!("0xAD29AbB318791D579433D831ed122aFeAf29dcfe") => Some(&FANTOM_56_AF29DCFE), + (56, addr) if addr == address!("0xe48A3d7d0Bc88d552f730B62c006bC925eadB9eE") => Some(&FRAX_SHARE_56_5EADB9EE), + (56, addr) if addr == address!("0xe4Cc45Bb5DBDA06dB6183E8bf016569f40497Aa5") => Some(&GALXE_56_40497AA5), + (56, addr) if addr == address!("0x30117E4bC17d7B044194b76A38365C53b72F7D49") => Some(ÐGAS_56_B72F7D49), + (56, addr) if addr == address!("0x44Ec807ce2F4a6F2737A92e985f318d035883e47") => Some(&HASHFLOW_56_35883E47), + (56, addr) if addr == address!("0x5f4Bde007Dc06b867f86EBFE4802e34A1fFEEd63") => Some(&HIGHSTREET_56_1FFEED63), + (56, addr) if addr == address!("0xa2B726B1145A4773F68593CF171187d8EBe4d495") => Some(&INJECTIVE_56_EBE4D495), + (56, addr) if addr == address!("0x0231f91e02DebD20345Ae8AB7D71A41f8E140cE7") => Some(&JUPITER_56_8E140CE7), + (56, addr) if addr == address!("0x073690e6CE25bE816E68F32dCA3e11067c9FB5Cc") => Some(&KUJIRA_56_7C9FB5CC), + (56, addr) if addr == address!("0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD") => Some(&CHAINLINK_TOKEN_56_111A51BD), + (56, addr) if addr == address!("0x2eD9a5C8C13b93955103B9a7C167B67Ef4d568a3") => Some(&MASK_NETWORK_56_F4D568A3), + (56, addr) if addr == address!("0xF218184Af829Cf2b0019F8E6F0b2423498a36983") => Some(&MATH_56_98A36983), + (56, addr) if addr == address!("0xCC42724C6683B7E57334c4E856f4c9965ED682bD") => Some(&POLYGON_56_5ED682BD), + (56, addr) if addr == address!("0x949D48EcA67b17269629c7194F4b727d4Ef9E5d6") => Some(&MERIT_CIRCLE_56_4EF9E5D6), + (56, addr) if addr == address!("0xe552Fb52a4F19e44ef5A967632DBc320B0820639") => Some(&METIS_56_B0820639), + (56, addr) if addr == address!("0xfE19F0B51438fd612f6FD59C1dbB3eA319f433Ba") => Some(&MAGIC_INTERNET_MONEY_56_19F433BA), + (56, addr) if addr == address!("0x5B6DcF557E2aBE2323c48445E8CC948910d8c2c9") => Some(&MIRROR_PROTOCOL_56_10D8C2C9), + (56, addr) if addr == address!("0x9Fb9a33956351cf4fa040f65A13b835A3C8764E3") => Some(&MULTICHAIN_56_3C8764E3), + (56, addr) if addr == address!("0x4e7f408be2d4E9D60F49A64B89Bb619c84C7c6F5") => Some(&PERPETUAL_PROTOCOL_56_84C7C6F5), + (56, addr) if addr == address!("0x7e624FA0E1c4AbFD309cC15719b7E2580887f570") => Some(&POLKASTARTER_56_0887F570), + (56, addr) if addr == address!("0xd21d29B38374528675C34936bf7d5Dd693D2a577") => Some(&PARSIQ_56_93D2A577), + (56, addr) if addr == address!("0x4C882ec256823eE773B25b414d36F92ef58a7c0C") => Some(&PSTAKE_FINANCE_56_F58A7C0C), + (56, addr) if addr == address!("0x833F307aC507D47309fD8CDD1F835BeF8D702a93") => Some(&REVV_56_8D702A93), + (56, addr) if addr == address!("0x3BC5AC0dFdC871B365d159f728dd1B9A0B5481E8") => Some(&STADER_56_0B5481E8), + (56, addr) if addr == address!("0xfA54fF1a158B5189Ebba6ae130CEd6bbd3aEA76e") => Some(&SOL_WORMHOLE_56_D3AEA76E), + (56, addr) if addr == address!("0xB0D502E938ed5f4df2E681fE6E419ff29631d62b") => Some(&STARGATE_FINANCE_56_9631D62B), + (56, addr) if addr == address!("0x51BA0b044d96C3aBfcA52B64D733603CCC4F0d4D") => Some(&SUPERFARM_56_CC4F0D4D), + (56, addr) if addr == address!("0x947950BcC74888a40Ffa2593C5798F11Fc9124C4") => Some(&SUSHI_56_FC9124C4), + (56, addr) if addr == address!("0xE64E30276C2F826FEbd3784958d6Da7B55DfbaD3") => Some(&SWFTCOIN_56_55DFBAD3), + (56, addr) if addr == address!("0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A") => Some(&SWIPE_56_FABA485A), + (56, addr) if addr == address!("0xa4080f1778e69467E905B8d6F72f6e441f9e9484") => Some(&SYNAPSE_56_1F9E9484), + (56, addr) if addr == address!("0x3b198e26E473b8faB2085b37978e36c9DE5D7f68") => Some(&CHRONOTECH_56_DE5D7F68), + (56, addr) if addr == address!("0x2222227E22102Fe3322098e4CBfE18cFebD57c95") => Some(&ALIEN_WORLDS_56_EBD57C95), + (56, addr) if addr == address!("0x728C5baC3C3e370E372Fc4671f9ef6916b814d8B") => Some(&UNIFI_PROTOCOL_DAO_56_6B814D8B), + (56, addr) if addr == address!("0xBf5140A22578168FD562DCcF235E5D43A02ce9B1") => Some(&UNISWAP_56_A02CE9B1), + (56, addr) if addr == address!("0x0D35A2B85c5A63188d566D104bEbf7C694334Ee4") => Some(&PAWTOCOL_56_94334EE4), + (56, addr) if addr == address!("0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d") => Some(&USDCOIN_56_32CD580D), + (56, addr) if addr == address!("0x55d398326f99059fF775485246999027B3197955") => Some(&TETHER_USD_56_B3197955), + (56, addr) if addr == address!("0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c") => Some(&WRAPPED_BNB), + (56, addr) if addr == address!("0x2170Ed0880ac9A755fd29B2688956BD959F933F8") => Some(&WRAPPED_ETHER_56_59F933F8), + (56, addr) if addr == address!("0x4691937a7508860F876c9c0a2a617E7d9E945D4B") => Some(&WOO_NETWORK_56_9E945D4B), + (56, addr) if addr == address!("0x7324c7C0d95CEBC73eEa7E85CbAac0dBdf88a05b") => Some(&CHAIN_56_DF88A05B), + (56, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_56_F13271CD), + (130, addr) if addr == address!("0xbe41cde1C5e75a7b6c2c70466629878aa9ACd06E") => Some(&TOKEN_1INCH_130_A9ACD06E), + (130, addr) if addr == address!("0x44D618C366D7bC85945Bfc922ACad5B1feF7759A") => Some(&ANCIENT8_130_FEF7759A), + (130, addr) if addr == address!("0x02a24C380dA560E4032Dc6671d8164cfbEEAAE1e") => Some(&AAVE_130_BEEAAE1E), + (130, addr) if addr == address!("0xDDCe42b89215548beCaA160048460747Fe5675bC") => Some(&ARCBLOCK_130_FE5675BC), + (130, addr) if addr == address!("0xb8A8e137A2dAa25EF1B3577b6598fE8Be66Ecf77") => Some(&ALCHEMY_PAY_130_E66ECF77), + (130, addr) if addr == address!("0x34424B3352af905e41078a4029b61EDe62BbB32C") => Some(&ACROSS_PROTOCOL_TOKEN_130_62BBB32C), + (130, addr) if addr == address!("0x3e1C572d8b069fc2f14ac4f8bdCE6e8eA299A500") => Some(&AMBIRE_ADEX_130_A299A500), + (130, addr) if addr == address!("0xfd38ac2316f6d3631a86065aDb3292f6f15873B5") => Some(&AERGO_130_F15873B5), + (130, addr) if addr == address!("0x54FA9210cCB765639b7Fd532f25bCb1060D60F8B") => Some(&AEVO_130_60D60F8B), + (130, addr) if addr == address!("0xA4eeF95995F40aD0b3D63a474293Fc7CC681A118") => Some(&AGEUR_130_C681A118), + (130, addr) if addr == address!("0x14421614587A2A3e9C3Aa3131Fc396aF412721CF") => Some(&ADVENTURE_GOLD_130_412721CF), + (130, addr) if addr == address!("0x5F891E74947b0FC400128E5E85333d7a6cF99b1A") => Some(&AIOZ_NETWORK_130_6CF99B1A), + (130, addr) if addr == address!("0xbf194C82A5Bb9180f9280c1832f886a65Aebdcd6") => Some(&ALCHEMIX_130_5AEBDCD6), + (130, addr) if addr == address!("0xa3E646211a456e08829C33fcE21cC3DC4c15Bb5c") => Some(&ALEPH_IM_130_4C15BB5C), + (130, addr) if addr == address!("0x2a87dd1e1F849ed88C18565AFDa98e2EEEc73780") => Some(&ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_130_EEC73780), + (130, addr) if addr == address!("0xBb72B8031F590748d8910Aad7e25F8B18860960a") => Some(&MY_NEIGHBOR_ALICE_130_8860960A), + (130, addr) if addr == address!("0x44c3E7c49C4Bb6f4f5eCD87E035176dFceBD78d3") => Some(&ALPHA_VENTURE_DAO_130_CEBD78D3), + (130, addr) if addr == address!("0x6D5De04F1a3E0e554B9A15059d03e20cb3589153") => Some(&ALTLAYER_130_B3589153), + (130, addr) if addr == address!("0x4D6B8ecb576dF9BB4bF6E6764A469a762bBc967F") => Some(&_130_2BBC967F), + (130, addr) if addr == address!("0xf081Fc8E0878D7eBe6ec381E5d7279d6EFf97622") => Some(&ANKR_130_EFF97622), + (130, addr) if addr == address!("0x865d184885200B8e86eb2a3Da8b3B4a7d4A31308") => Some(&ARAGON_130_D4A31308), + (130, addr) if addr == address!("0xD1b8423FdE5F37464FadE603f80903cB314046cf") => Some(&APECOIN_130_314046CF), + (130, addr) if addr == address!("0xA63122b27308EED0C1D83DD355ADdaA7f678961b") => Some(&API3_130_F678961B), + (130, addr) if addr == address!("0xcDfcE5eb357E8976A80Be84E94a03BA963b9e379") => Some(&APU_APUSTAJA_130_63B9E379), + (130, addr) if addr == address!("0x5cC70a9DF8E293aFFb14DFCa1e7F851418a4b40d") => Some(&ARBITRUM_130_18A4B40D), + (130, addr) if addr == address!("0x59F16BaA7A22f49c32680661e0041A53442Ef089") => Some(&ARKHAM_130_442EF089), + (130, addr) if addr == address!("0xE911A809F87490406AB34fad701aabCA88e30b45") => Some(&ARPA_CHAIN_130_88E30B45), + (130, addr) if addr == address!("0x4b355De6Ea44711f0353Ed89545705395a30d7Fb") => Some(&ASH_130_5A30D7FB), + (130, addr) if addr == address!("0x1e196D83e2c562de0b1f270Eb72220335bA0ADa7") => Some(&ASSEMBLE_PROTOCOL_130_5BA0ADA7), + (130, addr) if addr == address!("0x7F3F14A49FE5D5009E4e0a09e76cB8468C09Ae56") => Some(&AIRSWAP_130_8C09AE56), + (130, addr) if addr == address!("0xBAAa314d2f5Af29B00867a612F24F816d890C4B2") => Some(&AUTOMATA_130_D890C4B2), + (130, addr) if addr == address!("0xa249732271cbA6E06Be4ac8B20f0D465FeE183Ab") => Some(&AETHIR_TOKEN_130_FEE183AB), + (130, addr) if addr == address!("0x82F90996a4F67Eb388116B3C6F35B6Ea91BeF68E") => Some(&BOUNCE_130_91BEF68E), + (130, addr) if addr == address!("0x48b8441dE79cEE3604b805093B41028d3c81684B") => Some(&AUDIUS_130_3C81684B), + (130, addr) if addr == address!("0x38DBf47e2a012a4b83823f15E3F3352A00939999") => Some(&ARTVERSE_TOKEN_130_00939999), + (130, addr) if addr == address!("0xbF678793522638F7439aFE3B94d2D2A3a4cBF2C9") => Some(&AXELAR_130_A4CBF2C9), + (130, addr) if addr == address!("0xDA63AdA216d2079B54F2047B2FdC2576D188f927") => Some(&AXIE_INFINITY_130_D188F927), + (130, addr) if addr == address!("0xc2a564b44b441D03f09f5B6B2b358B4a17388406") => Some(&BADGER_DAO_130_17388406), + (130, addr) if addr == address!("0x01625E26274Ed828Ac1d47694c97221b34a8ADdF") => Some(&BALANCER_130_34A8ADDF), + (130, addr) if addr == address!("0xa264F2b88C630f260AbDcAb577eAB7266A8857d5") => Some(&BAND_PROTOCOL_130_6A8857D5), + (130, addr) if addr == address!("0x4e373C99199773f9D92d32B8c8Bc0C81508ea589") => Some(&BASIC_ATTENTION_TOKEN_130_508EA589), + (130, addr) if addr == address!("0xe5ECB192f1aE5839eD49886F36dFA670f9500824") => Some(&BEAM_130_F9500824), + (130, addr) if addr == address!("0x604Ff88ADC02325EFb7f93DB3E442dc81D0588E7") => Some(&BICONOMY_130_1D0588E7), + (130, addr) if addr == address!("0x17f3AfE72cAa6b9090801b60607918b6D2Fa7cdc") => Some(&BIG_TIME_130_D2FA7CDC), + (130, addr) if addr == address!("0xA4Cb2aaf7503641B441e80fC353e6748fb523A5C") => Some(&BITDAO_130_FB523A5C), + (130, addr) if addr == address!("0x41f6e69166e81A9583DBc96604B01D2E9B3D706f") => Some(&HARRYPOTTEROBAMASONIC10INU_130_9B3D706F), + (130, addr) if addr == address!("0x942fC6b61686e06fB411cB1bCf5d16DC2b9255eA") => Some(&BLUR_130_2B9255EA), + (130, addr) if addr == address!("0xe7b3Ca9d9Db06E1867781fd1C5F02E6c8eF471ee") => Some(&BLUZELLE_130_8EF471EE), + (130, addr) if addr == address!("0xf2Cc2D274dA528AB64DA86bE3f8416E5472c5a62") => Some(&BANCOR_NETWORK_TOKEN_130_472C5A62), + (130, addr) if addr == address!("0xBE8E46422fB7F9Ca9D639B3109492D64BbB41b05") => Some(&BOBA_NETWORK_130_BBB41B05), + (130, addr) if addr == address!("0x4d5b7e9CCE3Ab81298dA7E1F52b48c9a61Df8972") => Some(&BARNBRIDGE_130_61DF8972), + (130, addr) if addr == address!("0xBbE97f3522101e5B6976cBf77376047097BA837F") => Some(&BONK), + (130, addr) if addr == address!("0x6A4a359C7453F5892392FCb8eAB7A9A100986B71") => Some(&BRAINTRUST_130_00986B71), + (130, addr) if addr == address!("0xa4da5c92F44422dFA3E2E309b53d93bbbDa9f9c6") => Some(&BINANCE_USD_130_BDA9F9C6), + (130, addr) if addr == address!("0x29129fa2e0F35594ca7b362fFA8c80f5f8e4f8E1") => Some(&COIN98_130_F8E4F8E1), + (130, addr) if addr == address!("0xb6A3E8e5715fd4c99EcEDaaAe121bDe4Ab6a1Ef1") => Some(&COINBASE_WRAPPED_BTC_130_AB6A1EF1), + (130, addr) if addr == address!("0xEb64b50FeF2A363940369285F86Ae9a68211db59") => Some(&COINBASE_WRAPPED_STAKED_ETH_130_8211DB59), + (130, addr) if addr == address!("0x6008F5BaD83742fDbFf5AAc55e3c51b65A8A8D9C") => Some(&CELO_NATIVE_ASSET_WORMHOLE_130_5A8A8D9C), + (130, addr) if addr == address!("0x5AD5d6B1AE6761Aab12066b51D21729248035703") => Some(&CELER_NETWORK_130_48035703), + (130, addr) if addr == address!("0xAC930Be88cFAc775A937E9291c4234Bf210a4e5b") => Some(&CHROMIA_130_210A4E5B), + (130, addr) if addr == address!("0xb0C69e24450e29afa8008962052007E08b2396b0") => Some(&CHILIZ_130_8B2396B0), + (130, addr) if addr == address!("0xD7212097f6d6B195a9Bc350b8dCE28a7fA41404C") => Some(&CLOVER_FINANCE_130_FA41404C), + (130, addr) if addr == address!("0xdf78e4F0A8279942ca68046476919A90f2288656") => Some(&COMPOUND_130_F2288656), + (130, addr) if addr == address!("0xc63612B3e697AEeC61C3Ce9baEc0f9Db32F499C3") => Some(&COTI_130_32F499C3), + (130, addr) if addr == address!("0x2562DC34c21371613CEF236b321EE63fCC295beC") => Some(&CIRCUITS_OF_VALUE_130_CC295BEC), + (130, addr) if addr == address!("0xC3a97c76AA194711E05Ff1d181534090B26D3996") => Some(&COW_PROTOCOL_130_B26D3996), + (130, addr) if addr == address!("0xF8E7B485CE10D3C7Ac30B8444B98a0cC423dFb57") => Some(&CLEARPOOL_130_423DFB57), + (130, addr) if addr == address!("0x6C28eeB9E018011d3841f42c5b458713621F90C1") => Some(&COVALENT_130_621F90C1), + (130, addr) if addr == address!("0x73c63A80Ec77BFe31eEc6663828C4beaA30dE818") => Some(&CRONOS_130_A30DE818), + (130, addr) if addr == address!("0x7e7784f13029c7C4BF4746112B1A503818B0D066") => Some(&CRYPTERIUM_130_18B0D066), + (130, addr) if addr == address!("0xAC73671a1762FE835208Fb93b7aE7490d1c2cCb3") => Some(&CURVE_DAO_TOKEN_130_D1C2CCB3), + (130, addr) if addr == address!("0xa7073F530856cD32c2037150dd9763B9BAaED2C5") => Some(&CARTESI_130_BAAED2C5), + (130, addr) if addr == address!("0x36fA435F6def83cbB7a0706d035C9eA062fCb619") => Some(&CRYPTEX_FINANCE_130_62FCB619), + (130, addr) if addr == address!("0xE60e9b2E68297d5DF6B383fEe787B7fB92c2F8aF") => Some(&SOMNIUM_SPACE_CUBES_130_92C2F8AF), + (130, addr) if addr == address!("0x35C458aD1e3e68d2717C8349b985384Be85a01Ed") => Some(&CIVIC_130_E85A01ED), + (130, addr) if addr == address!("0x1C6789F30e7E335c2Eca2c75EC193aDBF0087Ea5") => Some(&CONVEX_FINANCE_130_F0087EA5), + (130, addr) if addr == address!("0x8E29E12B46FeE20E034fE1e812bc12EFf14E5A09") => Some(&COVALENT_X_TOKEN_130_F14E5A09), + (130, addr) if addr == address!("0x20CAb320A855b39F724131C69424240519573f81") => Some(&DAI_STABLECOIN_130_19573F81), + (130, addr) if addr == address!("0x2ef0775A19d1bc2258653fc5529F8f8490288086") => Some(&MINES_OF_DALARNIA_130_90288086), + (130, addr) if addr == address!("0x91ED4bb192e3461E45575730508525083A270265") => Some(&DERIVADAO_130_3A270265), + (130, addr) if addr == address!("0x45a4f750d806498A4c7f7B5267815aaC328e874C") => Some(&DENT_130_328E874C), + (130, addr) if addr == address!("0x17C38207334011a131b0Acf200E35Cd81723cddd") => Some(&DEXTOOLS_130_1723CDDD), + (130, addr) if addr == address!("0x4bdc8553cf14EEBCD489cD1d75b7FF463f9543c2") => Some(&DIA_130_3F9543C2), + (130, addr) if addr == address!("0x0eb07cE7a28FF84DF132fb5ee5F56Aabc1b9E545") => Some(&DISTRICT0X_130_C1B9E545), + (130, addr) if addr == address!("0x12E96C2BFEA6E835CF8Dd38a5834fa61Cf723736") => Some(&DOGECOIN), + (130, addr) if addr == address!("0xE274f564c37aE15fd2570D544102eD4ACd2f84f1") => Some(&DEFI_PULSE_INDEX_130_CD2F84F1), + (130, addr) if addr == address!("0x56aF109D597eb0a0F79ebCD0786Dd88C38EA9Ee7") => Some(&DREP_130_38EA9EE7), + (130, addr) if addr == address!("0x601b11907EAa8d3785C0b10b41C3a7315faeB82c") => Some(&DYDX_130_5FAEB82C), + (130, addr) if addr == address!("0xBdaD8E37a9600F0A35976fE61608a4C89D598610") => Some(&DEFI_YIELD_PROTOCOL_130_9D598610), + (130, addr) if addr == address!("0xc89ab9B82610BB9b748F6757b8F3ac59d016C47D") => Some(&EIGENLAYER_130_D016C47D), + (130, addr) if addr == address!("0x24aBc32215354Ba3eD224bfa6312E31dD8E8c1ab") => Some(&ELASTOS_130_D8E8C1AB), + (130, addr) if addr == address!("0x91441fE1415B00bEA8930A4354Fe00c426C1DE05") => Some(&DOGELON_MARS_130_26C1DE05), + (130, addr) if addr == address!("0x9116E70d613860D349495d9Ef8e2AE1cA6cBD2dd") => Some(ÐENA_130_A6CBD2DD), + (130, addr) if addr == address!("0x9A0D1b7594CAAF0A9e4687cAc9fF4E0B84a6d0A6") => Some(&ENJIN_COIN_130_84A6D0A6), + (130, addr) if addr == address!("0x80756FAf1e7Fec5678bf505670eF176AB5F0383a") => Some(ÐEREUM_NAME_SERVICE_130_B5F0383A), + (130, addr) if addr == address!("0x5E5903C236E6873EB8400C3d1979271Fa93cdB03") => Some(ÐERNITY_CHAIN_130_A93CDB03), + (130, addr) if addr == address!("0xF8740269F121327D03ff77BeD03a9A3258880821") => Some(ÐER_FI_130_58880821), + (130, addr) if addr == address!("0x6319F47719b6713b1624C1b3A8e2DBf15b5D03FE") => Some(&EULER_130_5B5D03FE), + (130, addr) if addr == address!("0x72f34BC403a005A9Be390762EAa46ED42813B0a8") => Some(&EURO_COIN_130_2813B0A8), + (130, addr) if addr == address!("0xEc42461D9BbDF4eFB6481099253bBB7324D7d72d") => Some(&QUANTOZ_EURQ_130_24D7D72D), + (130, addr) if addr == address!("0x7A1ef7fD6E0d708295D8FD0C30Fd437d9C36FB5f") => Some(&STABLR_EURO_130_9C36FB5F), + (130, addr) if addr == address!("0x472E8be16Cc9823b9f6a73A34EA55c0c31ee825F") => Some(&HARVEST_FINANCE_130_31EE825F), + (130, addr) if addr == address!("0x45343279DefDAd803d81C06fBCf87936DDD7DFE7") => Some(&FETCH_AI_130_DDD7DFE7), + (130, addr) if addr == address!("0xec9Be303f204864145CCC193aEb21B5fa10764A6") => Some(&STAFI_130_A10764A6), + (130, addr) if addr == address!("0x1b3EC249dc44a64bF5Cb8Afdd70e30c26c51fA81") => Some(&FLOKI_130_6C51FA81), + (130, addr) if addr == address!("0xB20fD6fD28e1430f98a8C1e9A83C88E5D87D94e5") => Some(&FORTA_130_D87D94E5), + (130, addr) if addr == address!("0xFa004fa2ad8Ef993C2B0412baB776b182220F12e") => Some(&LEFORTH_GOVERNANCE_TOKEN_130_2220F12E), + (130, addr) if addr == address!("0xe0BB1924C17b39B71758F49a00D7c0363B7a318E") => Some(&SHAPESHIFT_FOX_TOKEN_130_3B7A318E), + (130, addr) if addr == address!("0x8c7879bf25D678D9949F305857bD4437d74132B9") => Some(&FRAX_130_D74132B9), + (130, addr) if addr == address!("0xe99235A02958637a5e01575297fBBa3790dC7F0e") => Some(&FANTOM_130_90DC7F0E), + (130, addr) if addr == address!("0x6F32725F82Bbb06FFdC04974db437fec1d7af1Af") => Some(&FUNCTION_X_130_1D7AF1AF), + (130, addr) if addr == address!("0x79301DF2117C7F56859fD01b28bBAA61062021D6") => Some(&FRAX_SHARE_130_062021D6), + (130, addr) if addr == address!("0x481cB2C560fc3351833b582b92b965626fd8803C") => Some(&GRAVITY_130_6FD8803C), + (130, addr) if addr == address!("0x70b2b785061d4c91C76CF87692f85B5c443d8675") => Some(&GALXE_130_443D8675), + (130, addr) if addr == address!("0x31A71801291774d267615f74b3a44FCEB560FAc9") => Some(&GALA_130_B560FAC9), + (130, addr) if addr == address!("0x0328A0255866706547B79072DEE54976b157d3D0") => Some(&GOLDFINCH_130_B157D3D0), + (130, addr) if addr == address!("0x4aE5712A153fDfDE81C305fF7f2E4e59840aD24B") => Some(&AAVEGOTCHI_130_840AD24B), + (130, addr) if addr == address!("0x04b747f478AE09AC797d026C8402f409E2C9f2b9") => Some(&GOLEM_130_E2C9F2B9), + (130, addr) if addr == address!("0xC4c6c3A3043Ad5ECe5c91290630A7735e125a938") => Some(&GNOSIS_TOKEN_130_E125A938), + (130, addr) if addr == address!("0x6E74EA6546e1f21Abf581b59114f2Bf5d3683f48") => Some(&GODS_UNCHAINED_130_D3683F48), + (130, addr) if addr == address!("0xBb2272Ffc0Ef8F439373aDffD45c3591B3204D71") => Some(&THE_GRAPH_130_B3204D71), + (130, addr) if addr == address!("0x592620d454a10c47274dBfe3BD922b9a8fE5cf48") => Some(&GITCOIN_130_8FE5CF48), + (130, addr) if addr == address!("0xEbA12eC786Cdc21b4bd5ba601B595b6A5C0920a9") => Some(&GEMINI_DOLLAR_130_5C0920A9), + (130, addr) if addr == address!("0xad173F5B5FE39DD1183a0d3C49C57629A574c36F") => Some(&GYEN_130_A574C36F), + (130, addr) if addr == address!("0x656104f2028BbFD7144C8f71Fa15daaA8c34A28b") => Some(&HASHFLOW_130_8C34A28B), + (130, addr) if addr == address!("0x99F64C3Db98a4870eFf637315d5C86dcb1374879") => Some(&HIGHSTREET_130_B1374879), + (130, addr) if addr == address!("0xc32C0c5a52F36D244C552E45C485cBceaf385B36") => Some(&HOPR_130_AF385B36), + (130, addr) if addr == address!("0x15D0e0c55a3E7eE67152aD7E89acf164253Ff68d") => Some(&HYPERLIQUID), + (130, addr) if addr == address!("0x4eA052BcAeE7d7ef2E3D61D601e878A560eaBe8e") => Some(&IDEX_130_60EABE8E), + (130, addr) if addr == address!("0xa76195FA77304Bba4cD8946198f5a90E42F3E51F") => Some(&ILLUVIUM_130_42F3E51F), + (130, addr) if addr == address!("0xc4Fc8cF76883094404DDb875d2AF15D1F5AA8053") => Some(&IMMUTABLE_X_130_F5AA8053), + (130, addr) if addr == address!("0xa5Afe7646f07d2C41AA82Bb6AE09e99E121e39B7") => Some(&INDEX_COOPERATIVE_130_121E39B7), + (130, addr) if addr == address!("0x9361cA28625E12C7f088523B274A25059A89f9F8") => Some(&INJECTIVE_130_9A89F9F8), + (130, addr) if addr == address!("0xD326ACaB8799fb44C3A5B7f7eFbAaB5f9F7b54fb") => Some(&INVERSE_FINANCE_130_9F7B54FB), + (130, addr) if addr == address!("0xD749094Bc62615f0c8645467e241b71Ae2B6843F") => Some(&IOTEX_130_E2B6843F), + (130, addr) if addr == address!("0x428c2B7Fa7a7821891fb529BAE4d80a71d5c61A8") => Some(&GEOJAM_130_1D5C61A8), + (130, addr) if addr == address!("0x8EF0686F380dD07f3e2121831839371922720708") => Some(&JASMYCOIN_130_22720708), + (130, addr) if addr == address!("0x781CC305fCBFe7cde376C9Ef5469d5a7E5CaB8b2") => Some(&JUPITER_130_E5CAB8B2), + (130, addr) if addr == address!("0xbe51A5e8FA434F09663e8fB4CCe79d0B2381Afad") => Some(&JUPITER_130_2381AFAD), + (130, addr) if addr == address!("0x05DBd720fc26F732c8d42Ea89BD7F442EA6AFE80") => Some(&KEEP_NETWORK_130_EA6AFE80), + (130, addr) if addr == address!("0x68Cea24F675e4F25584607F6c9feFb353f1bBfDc") => Some(&SELFKEY_130_3F1BBFDC), + (130, addr) if addr == address!("0xB0E4Ad2dFe3754e4a2443A7a828Eda5bB7Cd2284") => Some(&KYBER_NETWORK_CRYSTAL_130_B7CD2284), + (130, addr) if addr == address!("0x9C41547e404942C173E28bB2B6abE4cf5fad6A74") => Some(&KEEP3RV1_130_5FAD6A74), + (130, addr) if addr == address!("0x14CFFAD448AeB0876c56B7aa28999C9a4f002943") => Some(&KRYLL_130_4F002943), + (130, addr) if addr == address!("0x2206cdcC9B94fF7dB7A9eAbeC77b5cE430258681") => Some(&KUJIRA_130_30258681), + (130, addr) if addr == address!("0x1201209f55634bdDb67034efE4e8aA4D1B7B482C") => Some(&LAYER3_130_1B7B482C), + (130, addr) if addr == address!("0xb34b3DE63D22ffC90419c1a439de6C7d46687782") => Some(&LCX_130_46687782), + (130, addr) if addr == address!("0x68A6dbc7214a0F2b0d875963663F1613814E8829") => Some(&LIDO_DAO_130_814E8829), + (130, addr) if addr == address!("0x5a53B6D19D8EDCb7923F0D840EeBB3f09BBeEfB7") => Some(&CHAINLINK_TOKEN_130_9BBEEFB7), + (130, addr) if addr == address!("0x68648F52B85407806bC1d349B745D13C91be0fDf") => Some(&LITENTRY_130_91BE0FDF), + (130, addr) if addr == address!("0x1D1BFCFC6ae6FE045f151C7e589fB241AAC89733") => Some(&LEAGUE_OF_KINGDOMS_130_AAC89733), + (130, addr) if addr == address!("0xc68992e0514968BfbA3Dad201fef91f6009f523c") => Some(&LOOM_NETWORK_130_009F523C), + (130, addr) if addr == address!("0x11c6B34caDC550B65A9666497d7FCb39f35B73E3") => Some(&LIVEPEER_130_F35B73E3), + (130, addr) if addr == address!("0x0176B38b7767451b1B682236eCe2fae853C71a60") => Some(&LIQUITY_130_53C71A60), + (130, addr) if addr == address!("0xA2af802b95D7e20167e5aeaC7Fe8fDf4a8aB158A") => Some(&LOOPRINGCOIN_V2_130_A8AB158A), + (130, addr) if addr == address!("0xD7eb7348Ba44c5A2f9f1D1d3534623230c7bee3F") => Some(&BLOCKLORDS_130_0C7BEE3F), + (130, addr) if addr == address!("0xf81B7485B4cB59645F74528D702c7f8CD72577FB") => Some(&LIQUITY_USD_130_D72577FB), + (130, addr) if addr == address!("0x276361c863903751771e9DabA6dDfaAf00FE358b") => Some(&DECENTRALAND_130_00FE358B), + (130, addr) if addr == address!("0xC42B642F5010a2A3bD3CA2396Fe6f2e21B9512C4") => Some(&MASK_NETWORK_130_1B9512C4), + (130, addr) if addr == address!("0xB999b66186d7a48BF0Eb5d22f4E7053A99eD2C97") => Some(&MATH_130_99ED2C97), + (130, addr) if addr == address!("0xF6AC97B05B3bC92f829c7584b25839906507176b") => Some(&POLYGON_130_6507176B), + (130, addr) if addr == address!("0x460ec1C67e1614Bf1feAb84b98795BAE2d657399") => Some(&MERIT_CIRCLE_130_2D657399), + (130, addr) if addr == address!("0x68619Bc0C709FB63555Fe988ed14e78f7E6ACc40") => Some(&MOSS_CARBON_CREDIT_130_7E6ACC40), + (130, addr) if addr == address!("0xB29FddC20D5e4bacE9F54c1d9237953331BFeFF4") => Some(&MEASURABLE_DATA_TOKEN_130_31BFEFF4), + (130, addr) if addr == address!("0x397E34AFF8bFc8Ec14aa78F378074F6d8E3E7d06") => Some(&MEMECOIN_130_8E3E7D06), + (130, addr) if addr == address!("0xBfBa2A8745e5C85544DB7C8824C6962aB3A8f102") => Some(&METIS_130_B3A8F102), + (130, addr) if addr == address!("0x397C1f55FefF63C8947624b0d457a2CA3e3602ab") => Some(&MAGIC_INTERNET_MONEY_130_3E3602AB), + (130, addr) if addr == address!("0x5FE989EaB3021d7e742099d05a7937bA4A72D717") => Some(&MIRROR_PROTOCOL_130_4A72D717), + (130, addr) if addr == address!("0xf7A581f6e26EEa790225d76Af8821EA34Dc3c117") => Some(&MELON_130_4DC3C117), + (130, addr) if addr == address!("0x58d68e179864605fEA06EAADF1185c6e78921Ebd") => Some(&MOG_COIN_130_78921EBD), + (130, addr) if addr == address!("0xAe6065FB0244A68036C82deC9a8dE5501c7A1087") => Some(&MONAVALE_130_1C7A1087), + (130, addr) if addr == address!("0xaa2109f14Bb155766cBA9E7fa8B8D4bF0ff19949") => Some(&MOVEMENT_130_0FF19949), + (130, addr) if addr == address!("0x587e0E022b074015F4e81eCa489c0C41d752A219") => Some(&MAPLE_130_D752A219), + (130, addr) if addr == address!("0x71d69d07914d087f1C3536F7A5006a256CfAd9Ea") => Some(&METAL_130_6CFAD9EA), + (130, addr) if addr == address!("0x1C3a8fB65Ab82D73e26B6403bf505B99d82b4701") => Some(&MULTICHAIN_130_D82B4701), + (130, addr) if addr == address!("0x10F109379E231d5c294ee6A5f9Abb2F8b40A8Dd1") => Some(&MSTABLE_USD_130_B40A8DD1), + (130, addr) if addr == address!("0xe3d92FB06a4EEbaC5879D3C1073e0eAB81D5f345") => Some(&MUSE_DAO_130_81D5F345), + (130, addr) if addr == address!("0xD6ec6A24d5365A1811B05099f8D353c0Ff182974") => Some(&GENSOKISHI_METAVERSE_130_FF182974), + (130, addr) if addr == address!("0xCF7c45Ccc1327ac1E9Cb9E098898c59402727794") => Some(&MXC_130_02727794), + (130, addr) if addr == address!("0x328Ed7736871F863C8216Ca6CbB6f29B795032Df") => Some(&POLYSWARM_130_795032DF), + (130, addr) if addr == address!("0xc1C06527E810C4A198D8C5d35e1dDBc987696276") => Some(&NEIRO_130_87696276), + (130, addr) if addr == address!("0x75b93cED9627Cd172912304Fb79Cd3e7336BaF62") => Some(&NKN_130_336BAF62), + (130, addr) if addr == address!("0x931e587542b8603EA3C6420dD8d3b22eDbdA20FC") => Some(&NUMERAIRE_130_DBDA20FC), + (130, addr) if addr == address!("0x2AEB5256de25ECed47797b82d2F5C404AACEA6b9") => Some(&NUCYPHER_130_AACEA6B9), + (130, addr) if addr == address!("0x652293F4e9b0ef61C52a78D6615D9f5f3cD79208") => Some(&OCEAN_PROTOCOL_130_3CD79208), + (130, addr) if addr == address!("0xa60CE8f7ec6A091535b4708569B39DF5eE18c880") => Some(&ORIGIN_PROTOCOL_130_EE18C880), + (130, addr) if addr == address!("0x5949b9200dF1e77878dB3D061e43cF878Ee37383") => Some(&OMG_NETWORK_130_8EE37383), + (130, addr) if addr == address!("0xf5614D20c13D5BF2F9e640f00B7B2B76959Eb0E3") => Some(&OMNI_NETWORK_130_959EB0E3), + (130, addr) if addr == address!("0xaD0bae21db0b471dFfC6f8F9EEacFe9A85321557") => Some(&ONDO_FINANCE_130_85321557), + (130, addr) if addr == address!("0xCF2050ebC80B74370C1C2B71bDB635d11be3E8c0") => Some(&ORCA_ALLIANCE_130_1BE3E8C0), + (130, addr) if addr == address!("0x3C5319013FD75976F0f13b0bc0852537B6eaF396") => Some(&ORION_PROTOCOL_130_B6EAF396), + (130, addr) if addr == address!("0x9775C2b4f245248dE5596252Ac69311152B98042") => Some(&ORCHID_130_52B98042), + (130, addr) if addr == address!("0x3614c8d98Bf905AbE075BfA289231bbc0D292327") => Some(&PAYPEREX_130_0D292327), + (130, addr) if addr == address!("0xeC37cdfC9a692b3cCd5c85696D14aaA31E75d6aC") => Some(&PLAYDAPP_130_1E75D6AC), + (130, addr) if addr == address!("0xD9b5DA95B3D97c3E9872102fDb47d4c09074952B") => Some(&PEPE_130_9074952B), + (130, addr) if addr == address!("0x5944D2728d5fea7D1F4AA4958E3aEbb3CCFEc7D5") => Some(&PERPETUAL_PROTOCOL_130_CCFEC7D5), + (130, addr) if addr == address!("0xd0F77df9a8f0e855F910361f5f59958118d064c6") => Some(&PIRATE_NATION_130_18D064C6), + (130, addr) if addr == address!("0x5441619a9754Aee0665c939743cf7611abB6F6C7") => Some(&PLUTON_130_ABB6F6C7), + (130, addr) if addr == address!("0xF6A49aEdbD7861DeD0DA2BE1f21C6954E5682E95") => Some(&POLYGON_ECOSYSTEM_TOKEN_130_E5682E95), + (130, addr) if addr == address!("0x82a98121eaf30b0E135b08d4208c837Cdc306503") => Some(&POLKASTARTER_130_DC306503), + (130, addr) if addr == address!("0x2f5cfdC89fb96f2cf6c0FB1Ca6e3501Dd538D863") => Some(&POLYMATH_130_D538D863), + (130, addr) if addr == address!("0xA2a36541c5a54bd2815985418105091B4D4782d5") => Some(&MARLIN_130_4D4782D5), + (130, addr) if addr == address!("0x562E588471cA0e710b2b1217867FFb2E0F2a5642") => Some(&PORTAL_130_0F2A5642), + (130, addr) if addr == address!("0xf265af514762286A63d015FeE382B90edfFa6bff") => Some(&POWER_LEDGER_130_DFFA6BFF), + (130, addr) if addr == address!("0xD17D5f0DA4200bBfd3D6626AC6aEA2eccbf9fEE0") => Some(&PRIME_130_CBF9FEE0), + (130, addr) if addr == address!("0xC6Fbf362a12804FEca22000f37DB5EFC1F41A7c9") => Some(&PROPY_130_1F41A7C9), + (130, addr) if addr == address!("0xc7B7dcF3c6CAcAAc13F92c9173f9A0060ABf3def") => Some(&PARSIQ_130_0ABF3DEF), + (130, addr) if addr == address!("0x13FE2c4504f3AA18708561250e2F20E4E7D7CAa2") => Some(&PSTAKE_FINANCE_130_E7D7CAA2), + (130, addr) if addr == address!("0xAdf70dc4AaeFbC6D1E7A6cF0B02b0F2138b560d2") => Some(&PUFFER_FINANCE_130_38B560D2), + (130, addr) if addr == address!("0x0D2f98904D88909072eA6e61105CBBf78e6207c5") => Some(&PAYPAL_USD_130_8E6207C5), + (130, addr) if addr == address!("0x3a8723f2929F370c61EaC583d6652e5C98C360d4") => Some(&QUANT_130_98C360D4), + (130, addr) if addr == address!("0x006254C4664C678e64c3265da28304cc8c1068b8") => Some(&QREDO_130_8C1068B8), + (130, addr) if addr == address!("0xb019a038eaDCB2F96321D236F6633C8d6Bb5eAbB") => Some(&QUANTSTAMP_130_6BB5EABB), + (130, addr) if addr == address!("0xD815958F92E6aBe63437BCe166E97027f8E6caC2") => Some(&QUICKSWAP_130_F8E6CAC2), + (130, addr) if addr == address!("0x3F9A30c86DC7F0c657eA17d52Efe09Eff08a1a45") => Some(&RADICLE_130_F08A1A45), + (130, addr) if addr == address!("0x6164A78F7B2aC49cf9b76c49e5B6909e89f34a66") => Some(&RAI_REFLEX_INDEX_130_89F34A66), + (130, addr) if addr == address!("0xe8a0078aA52ac7e93aE43818DdD64591E025BB6F") => Some(&SUPERRARE_130_E025BB6F), + (130, addr) if addr == address!("0x16F01392Ed7fC6F3C345CF544cf1172103C8561C") => Some(&RARIBLE_130_03C8561C), + (130, addr) if addr == address!("0x29EA5682024c8C62Cd8BDf691C4f0c5D66B403E3") => Some(&RUBIC_130_66B403E3), + (130, addr) if addr == address!("0x75B2dBb2a7C70073133E42F64366a986c841cd3e") => Some(&RIBBON_FINANCE_130_C841CD3E), + (130, addr) if addr == address!("0x560603E0bFC941063D1375Ec4E3f9FE38261617E") => Some(&REPUBLIC_TOKEN_130_8261617E), + (130, addr) if addr == address!("0x097ca3FC389697080C84148C455Ca839b2816Fc4") => Some(&REPUTATION_AUGUR_V1_130_B2816FC4), + (130, addr) if addr == address!("0xE86B1E5613a5761D005a2D00D8a1B4ad1e72A8c4") => Some(&REPUTATION_AUGUR_V2_130_1E72A8C4), + (130, addr) if addr == address!("0x9FcC3133779F2039c29908c915b6EFaE9d8663Cd") => Some(&REQUEST_130_9D8663CD), + (130, addr) if addr == address!("0xc14a68015fA6396eF97B57839da544910f9Ca657") => Some(&REVV_130_0F9CA657), + (130, addr) if addr == address!("0x2178f07c1d585C39272CAf69A72beF08aAD6c9AB") => Some(&RENZO_130_AAD6C9AB), + (130, addr) if addr == address!("0x8c9606001CF1787CEb80E03DEF3F9BaF946CF284") => Some(&RARI_GOVERNANCE_TOKEN_130_946CF284), + (130, addr) if addr == address!("0x538fB2719135740b8877607217Dc391FB3347ACb") => Some(&IEXEC_RLC_130_B3347ACB), + (130, addr) if addr == address!("0x7Ad899b7C793743fDE692d982F190f443F88c889") => Some(&RALLY_130_3F88C889), + (130, addr) if addr == address!("0x965C6DeBFa700F53a38d42DbaeD922c58d649868") => Some(&RENDER_TOKEN_130_8D649868), + (130, addr) if addr == address!("0x682B2f07e61022A80Ac2753448f7D95E9de41D99") => Some(&ROOK_130_9DE41D99), + (130, addr) if addr == address!("0x993A565A1E6219951323cA3c34Cee0A3b1889066") => Some(&RESERVE_RIGHTS_130_B1889066), + (130, addr) if addr == address!("0x47B72717E48Da346C3F1ED1311c8DCDe10EfD888") => Some(&SAFE_130_10EFD888), + (130, addr) if addr == address!("0x6A654A2ec95fB988Ea37746dBCca10772CAf25CA") => Some(&THE_SANDBOX_130_2CAF25CA), + (130, addr) if addr == address!("0x7ccc67C7b232aa6417d9422e90D91ec4b32d72E5") => Some(&STADER_130_B32D72E5), + (130, addr) if addr == address!("0xaa571d01057cdF477D73433D36D86fCb5664158e") => Some(&SHIBA_INU_130_5664158E), + (130, addr) if addr == address!("0x45Bda7bA10DaC525a86DBEaB3135701A66024F2F") => Some(&SHPING_130_66024F2F), + (130, addr) if addr == address!("0x486Bbb6f250343AdB4782F50Dd09766f8aD20c01") => Some(&SKALE_130_8AD20C01), + (130, addr) if addr == address!("0x5A6058002d0d336e5E8860652e7054a6d07074E4") => Some(&SKY_GOVERNANCE_TOKEN_130_D07074E4), + (130, addr) if addr == address!("0xbD2DD310FECBFb1111fC3262F3a97bA696cb03B3") => Some(&SMOOTH_LOVE_POTION_130_96CB03B3), + (130, addr) if addr == address!("0x914f7CE2B080B2186159C2213B1e193E265aBF5F") => Some(&STATUS_130_265ABF5F), + (130, addr) if addr == address!("0x022D952aBCc6C8271F26e59e37A65dC359E6bc88") => Some(&SYNTHETIX_NETWORK_TOKEN_130_59E6BC88), + (130, addr) if addr == address!("0x5e03C123D829505F4DEa87cf679F77c9dC4627ab") => Some(&UNISOCKS_130_DC4627AB), + (130, addr) if addr == address!("0x4Ff3E944D5Cb54f6f4A1dd035782BE59c3d054FE") => Some(&SOL_WORMHOLE_130_C3D054FE), + (130, addr) if addr == address!("0xbdE8A5331E8Ac4831cf8ea9e42e229219EafaB97") => Some(&SOLANA), + (130, addr) if addr == address!("0x739316C7bc4A39Eb39dcFa1b181b64abc17fEF7F") => Some(&SPELL_TOKEN_130_C17FEF7F), + (130, addr) if addr == address!("0x51A7b9a11f10D04C16306D90dc4EC22b036DD629") => Some(&SPX6900_130_036DD629), + (130, addr) if addr == address!("0x77c8A8E1dd3b5270d3Ab589543e9A83319373135") => Some(&STARGATE_FINANCE_130_19373135), + (130, addr) if addr == address!("0xf13B5B21555092882e69b22282DAf891c9951835") => Some(&STORJ_TOKEN_130_C9951835), + (130, addr) if addr == address!("0x09f705405677970E509d606348D4635D2332c72e") => Some(&STARKNET_130_2332C72E), + (130, addr) if addr == address!("0xEf86E70E534E02AADEAE95b843973d4AcacCeA22") => Some(&STOX_130_CACCEA22), + (130, addr) if addr == address!("0xc05B416738DDEBd14D5A9B790a6e1ce782176525") => Some(&SUKU_130_82176525), + (130, addr) if addr == address!("0x0c288302629Fc22504D59Ddf8fbf8AA92bD86D3D") => Some(&SUPERFARM_130_2BD86D3D), + (130, addr) if addr == address!("0x7251d204c2e867b31096D5c7091298239B3A6a0F") => Some(&SYNTH_SUSD_130_9B3A6A0F), + (130, addr) if addr == address!("0x2982Be2D0c6ae4A7D5BC1c8fe7B630E3BDfb3ce5") => Some(&SUSHI_130_BDFB3CE5), + (130, addr) if addr == address!("0xa8015cbc9f7c58788BA00854c330F027028A5870") => Some(&SWELL_130_028A5870), + (130, addr) if addr == address!("0x0610cDF9856b8825213672981056CD4945Af1616") => Some(&SWFTCOIN_130_45AF1616), + (130, addr) if addr == address!("0xDcA295E850666753c6332D6B0E0445B09785c2E1") => Some(&SWIPE_130_9785C2E1), + (130, addr) if addr == address!("0x1BAAc1979527A38F367c6f89bE081aBfcFFCF85E") => Some(&SYLO_130_CFFCF85E), + (130, addr) if addr == address!("0xCeb1F5671C47cee096C3B40353863b6781888A48") => Some(&SYNAPSE_130_81888A48), + (130, addr) if addr == address!("0x8f7F997ba304f426E3138999919c23f68cD6FA96") => Some(&SYRUP_TOKEN_130_8CD6FA96), + (130, addr) if addr == address!("0x8F43Ab8648F1a3BAEea3782Ba5f562a148f2Ad54") => Some(&THRESHOLD_NETWORK_130_48F2AD54), + (130, addr) if addr == address!("0xFdCa15bd55F350a36E63C47661914d80411d2C22") => Some(&BITTENSOR), + (130, addr) if addr == address!("0xAd497996Dc33DC8E8e552824CcEe199420BC7814") => Some(&TBTC_130_20BC7814), + (130, addr) if addr == address!("0xD9Cbd701bbEA8e9Aaee7d82aa60748451eDa749c") => Some(&CHRONOTECH_130_1EDA749C), + (130, addr) if addr == address!("0xd649b9AD2104418B5b032a5899fBcd54a9a46c68") => Some(&ALIEN_WORLDS_130_A9A46C68), + (130, addr) if addr == address!("0x5eD5DA180bB125f229AB7b825E34D2b936213e0B") => Some(&TOKEMAK_130_36213E0B), + (130, addr) if addr == address!("0x502865ECDd2a2929Aa9418297bE7d3C4a7BD5Ac6") => Some(&TE_FOOD_130_A7BD5AC6), + (130, addr) if addr == address!("0x1ac70C9e29bC19640E64D938DD8D6A46dbAe6f2e") => Some(&ORIGINTRAIL_130_DBAE6F2E), + (130, addr) if addr == address!("0x8e902FDeA73e5CF9621D2Bee82cD79196d8ec63b") => Some(&TELLOR_130_6D8EC63B), + (130, addr) if addr == address!("0x437dD6360Bd17FB353c67376371133Cd33dacdBD") => Some(&TRIBE_130_33DACDBD), + (130, addr) if addr == address!("0x55C65102C26b173696e935B1325e5AaeF30cFE0e") => Some(&TRUEFI_130_F30CFE0E), + (130, addr) if addr == address!("0x1E4339318EcE1d6D9d2Fb129b31C06b9F2d202A1") => Some(&TURBO_130_F2D202A1), + (130, addr) if addr == address!("0x756fb781389DCaF9D3BC5468927F06A913bD9D5D") => Some(&THE_VIRTUA_KOLECT_130_13BD9D5D), + (130, addr) if addr == address!("0x478923278640a10A60951E379aFFb60772435f8C") => Some(&UMA_VOTING_TOKEN_V1_130_72435F8C), + (130, addr) if addr == address!("0xe9225a870b54f8FBA42c8188D211271f0408a30B") => Some(&UNIFI_PROTOCOL_DAO_130_0408A30B), + (130, addr) if addr == address!("0x8f187aA05619a017077f5308904739877ce9eA21") => Some(&UNISWAP_130_7CE9EA21), + (130, addr) if addr == address!("0x5EAFF8Fa6f3831Bb86FeEB701E6f98293E264D36") => Some(&PAWTOCOL_130_3E264D36), + (130, addr) if addr == address!("0x078D782b760474a361dDA0AF3839290b0EF57AD6") => Some(&USDCOIN_130_0EF57AD6), + (130, addr) if addr == address!("0x2A22868610610199D43fE93A16661473A9f86f1E") => Some(&GLOBAL_DOLLAR_130_A9F86F1E), + (130, addr) if addr == address!("0xF7E6430137eF8087E0D472343f358e986De0FEFF") => Some(&PAX_DOLLAR_130_6DE0FEFF), + (130, addr) if addr == address!("0xf37748D2Cc6E6d5D05945Ce130C03c147b2F3a5F") => Some(&QUANTOZ_USDQ_130_7B2F3A5F), + (130, addr) if addr == address!("0xaC025d055a6B633992dE1F796b97B97F004c06a7") => Some(&STABLR_USD_130_004C06A7), + (130, addr) if addr == address!("0x116EE4d63847fb295dD919aE57B768EA3B2f7Bb4") => Some(&USDS_STABLECOIN_130_3B2F7BB4), + (130, addr) if addr == address!("0x588CE4F028D8e7B53B687865d6A67b3A54C75518") => Some(&TETHER_USD_130_54C75518), + (130, addr) if addr == address!("0xc7bA59c95ba747a7c374DC7208a0513798BC5950") => Some(&USUAL_130_98BC5950), + (130, addr) if addr == address!("0x286b5Ecea3749c7c7047104aa3C5749901564A0b") => Some(&VANRY_130_01564A0B), + (130, addr) if addr == address!("0x4afd08AC2416450d9c8b84D287dbfFb68FFe537f") => Some(&VOYAGER_TOKEN_130_8FFE537F), + (130, addr) if addr == address!("0xb86a08ec917EeF9f835aC2B26c3a506c06364A49") => Some(&WRAPPED_AMPLEFORTH_130_06364A49), + (130, addr) if addr == address!("0x927B51f251480a681271180DA4de28D44EC4AfB8") => Some(&WRAPPED_BTC_130_4EC4AFB8), + (130, addr) if addr == address!("0xaE87B8eb5E313AC72B306CbA7c1E3f23D72e82C4") => Some(&WRAPPED_CENTRIFUGE_130_D72E82C4), + (130, addr) if addr == address!("0x4200000000000000000000000000000000000006") => Some(&WRAPPED_ETHER_130_00000006), + (130, addr) if addr == address!("0x97Fadb3D000b953360FD011e173F12cDDB5d70Fa") => Some(&DOGWIFHAT), + (130, addr) if addr == address!("0xef22b9df2dDf4246A827575C4Aa46BDaeFd89E62") => Some(&WOO_NETWORK_130_EFD89E62), + (130, addr) if addr == address!("0x15261eEb999eD3C3ae3c5319E0035940dc06a12f") => Some(&CHAIN_130_DC06A12F), + (130, addr) if addr == address!("0x139451953Ef1865c096F89C5e522C081DC3b5f11") => Some(&PLASMA), + (130, addr) if addr == address!("0x2615a94df961278DcbC41Fb0a54fEc5f10a693aE") => Some(&XRP), + (130, addr) if addr == address!("0xb1A9385B500Fe81B58c4d0e3AaCC39d8021265c3") => Some(&XSGD_130_021265C3), + (130, addr) if addr == address!("0x43D5EA0f30Bce3907aAD6783e61D56592AEbE4eA") => Some(&XYO_NETWORK_130_2AEBE4EA), + (130, addr) if addr == address!("0x52Bf54Eb4210F588320f3e4c151Bca81f84a3201") => Some(&YEARN_FINANCE_130_F84A3201), + (130, addr) if addr == address!("0x62ffD4229bb9a327412D1BE518A1dbAe6c18A07E") => Some(&DFI_MONEY_130_6C18A07E), + (130, addr) if addr == address!("0xeA20C2Cf22acBbF3d8311D15bC73FD7076E36f4B") => Some(&YIELD_GUILD_GAMES_130_76E36F4B), + (130, addr) if addr == address!("0x83f31af747189c2FA9E5DeB253200c505eff6ed2") => Some(&ZCASH), + (130, addr) if addr == address!("0x757dCF360f2FE999FAEEBcc6E80f5Eceb3cb3CA4") => Some(&ZETACHAIN_130_B3CB3CA4), + (130, addr) if addr == address!("0x00ad3704d1e101DF76f87738bEfE67737eD29cFb") => Some(&LAYERZERO_130_7ED29CFB), + (130, addr) if addr == address!("0x7e7e8e5f0eDd7ca2ed3D9609cea1FF37a6E7Edf5") => Some(&TOKEN_0X_PROTOCOL_TOKEN_130_A6E7EDF5), + (137, addr) if addr == address!("0xD6DF932A45C0f255f85145f286eA0b292B21C90B") => Some(&AAVE_137_2B21C90B), + (137, addr) if addr == address!("0xE0B52e49357Fd4DAf2c15e02058DCE6BC0057db4") => Some(&AGEUR_137_C0057DB4), + (137, addr) if addr == address!("0x0621d647cecbFb64b79E44302c1933cB4f27054d") => Some(&_137_4F27054D), + (137, addr) if addr == address!("0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3") => Some(&BALANCER_137_3B0E76A3), + (137, addr) if addr == address!("0xA8b1E0764f85f53dfe21760e8AfE5446D82606ac") => Some(&BAND_PROTOCOL_137_D82606AC), + (137, addr) if addr == address!("0xc26D47d5c33aC71AC5CF9F776D63Ba292a4F7842") => Some(&BANCOR_NETWORK_TOKEN_137_2A4F7842), + (137, addr) if addr == address!("0x8505b9d2254A7Ae468c0E9dd10Ccea3A837aef5c") => Some(&COMPOUND_137_837AEF5C), + (137, addr) if addr == address!("0x172370d5Cd63279eFa6d502DAB29171933a610AF") => Some(&CURVE_DAO_TOKEN_137_33A610AF), + (137, addr) if addr == address!("0x66Dc5A08091d1968e08C16aA5b27BAC8398b02Be") => Some(&CIVIC_137_398B02BE), + (137, addr) if addr == address!("0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063") => Some(&DAI_STABLECOIN_137_39C6A063), + (137, addr) if addr == address!("0xbD7A5Cf51d22930B8B3Df6d834F9BCEf90EE7c4f") => Some(ÐEREUM_NAME_SERVICE_137_90EE7C4F), + (137, addr) if addr == address!("0x5FFD62D3C3eE2E81C00A7b9079FB248e7dF024A8") => Some(&GNOSIS_TOKEN_137_7DF024A8), + (137, addr) if addr == address!("0x5fe2B58c013d7601147DcdD68C143A77499f5531") => Some(&THE_GRAPH_137_499F5531), + (137, addr) if addr == address!("0x42f37A1296b2981F7C3cAcEd84c5096b2Eb0C72C") => Some(&KEEP_NETWORK_137_2EB0C72C), + (137, addr) if addr == address!("0x324b28d6565f784d596422B0F2E5aB6e9CFA1Dc7") => Some(&KYBER_NETWORK_CRYSTAL_137_9CFA1DC7), + (137, addr) if addr == address!("0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39") => Some(&CHAINLINK_TOKEN_137_3FABAD39), + (137, addr) if addr == address!("0x66EfB7cC647e0efab02eBA4316a2d2941193F6b3") => Some(&LOOM_NETWORK_137_1193F6B3), + (137, addr) if addr == address!("0x84e1670F61347CDaeD56dcc736FB990fBB47ddC1") => Some(&LOOPRINGCOIN_V2_137_BB47DDC1), + (137, addr) if addr == address!("0xA1c57f48F0Deb89f569dFbE6E2B7f46D33606fD4") => Some(&DECENTRALAND_137_33606FD4), + (137, addr) if addr == address!("0x0000000000000000000000000000000000001010") => Some(&POLYGON_137_00001010), + (137, addr) if addr == address!("0x6f7C932e7684666C9fd1d44527765433e01fF61d") => Some(&MAKER_137_E01FF61D), + (137, addr) if addr == address!("0x0Bf519071b02F22C17E7Ed5F4002ee1911f46729") => Some(&NUMERAIRE_137_11F46729), + (137, addr) if addr == address!("0x9880e3dDA13c8e7D4804691A45160102d31F6060") => Some(&ORCHID_137_D31F6060), + (137, addr) if addr == address!("0x19782D3Dc4701cEeeDcD90f0993f0A9126ed89d0") => Some(&REPUBLIC_TOKEN_137_26ED89D0), + (137, addr) if addr == address!("0x6563c1244820CfBd6Ca8820FBdf0f2847363F733") => Some(&REPUTATION_AUGUR_V2_137_7363F733), + (137, addr) if addr == address!("0x50B728D8D964fd00C2d0AAD81718b71311feF68a") => Some(&SYNTHETIX_NETWORK_TOKEN_137_11FEF68A), + (137, addr) if addr == address!("0xd72357dAcA2cF11A5F155b9FF7880E595A3F5792") => Some(&STORJ_TOKEN_137_5A3F5792), + (137, addr) if addr == address!("0xF81b4Bec6Ca8f9fe7bE01CA734F55B2b6e03A7a0") => Some(&SYNTH_SUSD_137_6E03A7A0), + (137, addr) if addr == address!("0x3066818837c5e6eD6601bd5a91B0762877A6B731") => Some(&UMA_VOTING_TOKEN_V1_137_77A6B731), + (137, addr) if addr == address!("0xb33EaAd8d922B1083446DC23f610c2567fB5180f") => Some(&UNISWAP_137_7FB5180F), + (137, addr) if addr == address!("0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359") => Some(&USDCOIN_137_3D5C3359), + (137, addr) if addr == address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174") => Some(&USDCOIN_POS), + (137, addr) if addr == address!("0xc2132D05D31c914a87C6611C10748AEb04B58e8F") => Some(&TETHER_USD_137_04B58E8F), + (137, addr) if addr == address!("0x8DE5B80a0C1B02Fe4976851D030B36122dbb8624") => Some(&VANAR_CHAIN), + (137, addr) if addr == address!("0xd0258a3fD00f38aa8090dfee343f10A9D4d30D3F") => Some(&VOXIES), + (137, addr) if addr == address!("0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6") => Some(&WRAPPED_BTC_137_47D9BFD6), + (137, addr) if addr == address!("0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619") => Some(&WRAPPED_ETHER_137_F1B9F619), + (137, addr) if addr == address!("0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270") => Some(&WRAPPED_MATIC), + (137, addr) if addr == address!("0xDC3326e71D45186F113a2F448984CA0e8D201995") => Some(&XSGD_137_8D201995), + (137, addr) if addr == address!("0xDA537104D6A5edd53c6fBba9A898708E465260b6") => Some(&YEARN_FINANCE_137_465260B6), + (137, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_137_F13271CD), + (137, addr) if addr == address!("0x5559Edb74751A0edE9DeA4DC23aeE72cCA6bE3D5") => Some(&TOKEN_0X_PROTOCOL_TOKEN_137_CA6BE3D5), + (143, addr) if addr == address!("0xea17E5a9efEBf1477dB45082d67010E2245217f1") => Some(&SOL_WORMHOLE_143_245217F1), + (143, addr) if addr == address!("0x754704Bc059F8C67012fEd69BC8A327a5aafb603") => Some(&USDCOIN_143_5AAFB603), + (143, addr) if addr == address!("0xe7cd86e13AC4309349F30B3435a9d337750fC82D") => Some(&TETHER_USD_143_750FC82D), + (143, addr) if addr == address!("0x0555E30da8f98308EdB960aa94C0Db47230d2B9c") => Some(&WRAPPED_BTC_143_230D2B9C), + (143, addr) if addr == address!("0xEE8c0E9f1BFFb4Eb878d8f15f368A02a35481242") => Some(&WRAPPED_ETHER_143_35481242), + (196, addr) if addr == address!("0x4ae46a509F6b1D9056937BA4500cb143933D2dc8") => Some(&GLOBAL_DOLLAR_196_933D2DC8), + (324, addr) if addr == address!("0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E") => Some(&ZKSYNC), + (480, addr) if addr == address!("0x79A02482A880bCE3F13e09Da970dC34db4CD24d1") => Some(&BRIDGED_USDC), + (480, addr) if addr == address!("0x03C7054BCB39f7b2e5B2c7AcB37583e32D70Cfa3") => Some(&WRAPPED_BTC_480_2D70CFA3), + (480, addr) if addr == address!("0x4200000000000000000000000000000000000006") => Some(&WRAPPED_ETHER_480_00000006), + (1868, addr) if addr == address!("0xbA9986D2381edf1DA03B0B9c1f8b00dc4AacC369") => Some(&USDCOIN_1868_4AACC369), + (1868, addr) if addr == address!("0x3A337a6adA9d885b6Ad95ec48F9b75f197b5AE35") => Some(&TETHER_USD_1868_97B5AE35), + (1868, addr) if addr == address!("0x4200000000000000000000000000000000000006") => Some(&WRAPPED_ETHER_1868_00000006), + (8453, addr) if addr == address!("0xc5fecC3a29Fb57B5024eEc8a2239d4621e111CBE") => Some(&TOKEN_1INCH_8453_1E111CBE), + (8453, addr) if addr == address!("0x63706e401c06ac8513145b7687A14804d17f814b") => Some(&AAVE_8453_D17F814B), + (8453, addr) if addr == address!("0xe2A8cCB00E328a0EC2204CB0c736309D7c1fa556") => Some(&ARCBLOCK_8453_7C1FA556), + (8453, addr) if addr == address!("0x3c87e7AF3cDBAe5bB56b4936325Ea95CA3E0EfD9") => Some(&AMBIRE_ADEX_8453_A3E0EFD9), + (8453, addr) if addr == address!("0x940181a94A35A4569E4529A3CDfB74e38FD98631") => Some(&AERODROME_FINANCE), + (8453, addr) if addr == address!("0x4F9Fd6Be4a90f2620860d680c0d4d5Fb53d1A825") => Some(&AIXBT_BY_VIRTUALS), + (8453, addr) if addr == address!("0x97c806e7665d3AFd84A8Fe1837921403D59F3Dcc") => Some(&ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_8453_D59F3DCC), + (8453, addr) if addr == address!("0x449B3317a6d1efb1Bc3ba0700C9EaA4FFFf4Ae65") => Some(&AUSTRALIAN_DIGITAL_DOLLAR), + (8453, addr) if addr == address!("0x696F9436B67233384889472Cd7cD58A6fB5DF4f1") => Some(&AVANTIS), + (8453, addr) if addr == address!("0x1B4617734C43F6159F3a70b7E06d883647512778") => Some(&AWE_NETWORK), + (8453, addr) if addr == address!("0xB3B32F9f8827D4634fE7d973Fa1034Ec9fdDB3B3") => Some(&B3), + (8453, addr) if addr == address!("0x2a06A17CBC6d0032Cac2c6696DA90f29D39a1a29") => Some(&HARRYPOTTEROBAMASONIC10INU_8453_D39A1A29), + (8453, addr) if addr == address!("0x22aF33FE49fD1Fa80c7149773dDe5890D3c76F3b") => Some(&BANKRCOIN), + (8453, addr) if addr == address!("0xcbADA732173e39521CDBE8bf59a6Dc85A9fc7b8c") => Some(&COINBASE_WRAPPED_ADA), + (8453, addr) if addr == address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf") => Some(&COINBASE_WRAPPED_BTC_8453_0EED33BF), + (8453, addr) if addr == address!("0xcbD06E5A2B0C65597161de254AA074E489dEb510") => Some(&COINBASE_WRAPPED_DOGE), + (8453, addr) if addr == address!("0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22") => Some(&COINBASE_WRAPPED_STAKED_ETH_8453_CF0DEC22), + (8453, addr) if addr == address!("0xcb17C9Db87B595717C857a08468793f5bAb6445F") => Some(&COINBASE_WRAPPED_LTC), + (8453, addr) if addr == address!("0xcb585250f852C6c6bf90434AB21A00f02833a4af") => Some(&COINBASE_WRAPPED_XRP), + (8453, addr) if addr == address!("0x1bc0c42215582d5A085795f4baDbaC3ff36d1Bcb") => Some(&TOKENBOT), + (8453, addr) if addr == address!("0x9e1028F5F1D5eDE59748FFceE5532509976840E0") => Some(&COMPOUND_8453_976840E0), + (8453, addr) if addr == address!("0xC0041EF357B183448B235a8Ea73Ce4E4eC8c265F") => Some(&COOKIE), + (8453, addr) if addr == address!("0x8Ee73c484A26e0A5df2Ee2a4960B789967dd0415") => Some(&CURVE_DAO_TOKEN_8453_67DD0415), + (8453, addr) if addr == address!("0x259Fac10c5CbFEFE3E710e1D9467f70a76138d45") => Some(&CARTESI_8453_76138D45), + (8453, addr) if addr == address!("0xBB22Ff867F8Ca3D5F2251B4084F6Ec86D4666E14") => Some(&CRYPTEX_FINANCE_8453_D4666E14), + (8453, addr) if addr == address!("0xB1E1f3Cc2B6fE4420C1Ac82022b457018Eb628ff") => Some(&COVALENT_X_TOKEN_8453_8EB628FF), + (8453, addr) if addr == address!("0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb") => Some(&DAI_STABLECOIN_8453_917DB0CB), + (8453, addr) if addr == address!("0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed") => Some(&DEGEN), + (8453, addr) if addr == address!("0x6921B130D297cc43754afba22e5EAc0FBf8Db75b") => Some(&DOGINME), + (8453, addr) if addr == address!("0xB38266e0e9D9681b77aEB0A280E98131b953F865") => Some(&DOVU_8453_B953F865), + (8453, addr) if addr == address!("0x9d0E8f5b25384C7310CB8C6aE32C8fbeb645d083") => Some(&DERIVE_8453_B645D083), + (8453, addr) if addr == address!("0xED6E000dEF95780fb89734c07EE2ce9F6dcAf110") => Some(&DEFINITIVE), + (8453, addr) if addr == address!("0x29cC30f9D113B356Ce408667aa6433589CeCBDcA") => Some(&ELSA), + (8453, addr) if addr == address!("0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42") => Some(&EURC), + (8453, addr) if addr == address!("0xb33Ff54b9F7242EF1593d2C9Bcd8f9df46c77935") => Some(&FAI), + (8453, addr) if addr == address!("0x5aB3D4c385B400F3aBB49e80DE2fAF6a88A7B691") => Some(&FLOCK), + (8453, addr) if addr == address!("0x61E030A56D33e8260FdD81f03B162A79Fe3449Cd") => Some(&FLUID), + (8453, addr) if addr == address!("0x16EE7ecAc70d1028E7712751E2Ee6BA808a7dd92") => Some(&SPORT_FUN), + (8453, addr) if addr == address!("0x4BfAa776991E85e5f8b1255461cbbd216cFc714f") => Some(&HOME), + (8453, addr) if addr == address!("0xC9d23ED2ADB0f551369946BD377f8644cE1ca5c4") => Some(&HYPERLANE), + (8453, addr) if addr == address!("0xBCBAf311ceC8a4EAC0430193A528d9FF27ae38C1") => Some(&IOTEX_8453_27AE38C1), + (8453, addr) if addr == address!("0xFf9957816c813C5Ad0b9881A8990Df1E3AA2a057") => Some(&GEOJAM_8453_3AA2A057), + (8453, addr) if addr == address!("0x98d0baa52b2D063E780DE12F615f963Fe8537553") => Some(&KAITO), + (8453, addr) if addr == address!("0x9a26F5433671751C3276a065f57e5a02D2817973") => Some(&KEYBOARD_CAT), + (8453, addr) if addr == address!("0xDAE49C25fAd3a62a8e8bFB6dA12c46bE611f9f7a") => Some(&KRYLL_8453_611F9F7A), + (8453, addr) if addr == address!("0xc0634090F2Fe6c6d75e61Be2b949464aBB498973") => Some(&KEETA), + (8453, addr) if addr == address!("0xd7468c14ae76C3Fc308aEAdC223D5D1F71d3c171") => Some(&LCX_8453_71D3C171), + (8453, addr) if addr == address!("0x5259384690aCF240e9b0A8811bD0FFbFBDdc125C") => Some(&LIQUITY_8453_BDDC125C), + (8453, addr) if addr == address!("0x7300B37DfdfAb110d83290A29DfB31B1740219fE") => Some(&MAMO), + (8453, addr) if addr == address!("0x9Cb41FD9dC6891BAe8187029461bfAADF6CC0C69") => Some(&NOICE), + (8453, addr) if addr == address!("0xca73ed1815e5915489570014e024b7EbE65dE679") => Some(&ODOS_TOKEN), + (8453, addr) if addr == address!("0xA99F6e6785Da0F5d6fB42495Fe424BCE029Eeb3E") => Some(&PENDLE_8453_029EEB3E), + (8453, addr) if addr == address!("0xB4fDe59a779991bfB6a52253B51947828b982be3") => Some(&PEPE_8453_8B982BE3), + (8453, addr) if addr == address!("0xCD6dDDa305955AcD6b94b934f057E8b0daaD58dE") => Some(&PERPETUAL_PROTOCOL_8453_DAAD58DE), + (8453, addr) if addr == address!("0xfA980cEd6895AC314E7dE34Ef1bFAE90a5AdD21b") => Some(&PRIME_8453_A5ADD21B), + (8453, addr) if addr == address!("0x18dD5B087bCA9920562aFf7A0199b96B9230438b") => Some(&PROPY_8453_9230438B), + (8453, addr) if addr == address!("0x30c7235866872213F68cb1F08c37Cb9eCCB93452") => Some(&PROMPT), + (8453, addr) if addr == address!("0x1aA8fD5BCce2231C6100d55Bf8B377cff33Acfc3") => Some(&RAVEDAO), + (8453, addr) if addr == address!("0x1f16e03C1a5908818F47f6EE7bB16690b40D0671") => Some(&RECALL_NETWORK), + (8453, addr) if addr == address!("0xa53887F7e7c1bf5010b8627F1C1ba94fE7a5d6E0") => Some(&RAINBOW), + (8453, addr) if addr == address!("0xFbB75A59193A3525a8825BeBe7D4b56899E2f7e1") => Some(&RESEARCHCOIN), + (8453, addr) if addr == address!("0xaB36452DbAC151bE02b16Ca17d8919826072f64a") => Some(&RESERVE_RIGHTS_8453_6072F64A), + (8453, addr) if addr == address!("0xC729777d0470F30612B1564Fd96E8Dd26f5814E3") => Some(&SAPIEN), + (8453, addr) if addr == address!("0x1C7a460413dD4e964f96D8dFC56E7223cE88CD85") => Some(&SEAMLESSS), + (8453, addr) if addr == address!("0x662015EC830DF08C0FC45896FaB726542e8AC09E") => Some(&STATUS_8453_2E8AC09E), + (8453, addr) if addr == address!("0x22e6966B799c4D5B13BE962E1D117b56327FDa66") => Some(&SYNTHETIX_NETWORK_TOKEN_8453_327FDA66), + (8453, addr) if addr == address!("0x50dA645f148798F68EF2d7dB7C1CB22A6819bb2C") => Some(&SPX6900_8453_6819BB2C), + (8453, addr) if addr == address!("0xa69f80524381275A7fFdb3AE01c54150644c8792") => Some(&SUPERFLUID_TOKEN), + (8453, addr) if addr == address!("0x7D49a065D17d6d4a55dc13649901fdBB98B2AFBA") => Some(&SUSHI_8453_98B2AFBA), + (8453, addr) if addr == address!("0x11dC28D01984079b7efE7763b533e6ed9E3722B9") => Some(&SYNDICATE), + (8453, addr) if addr == address!("0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b") => Some(&TBTC_8453_22AB794B), + (8453, addr) if addr == address!("0xAC1Bd2486aAf3B5C0fc3Fd868558b082a531B2B4") => Some(&TOSHI), + (8453, addr) if addr == address!("0x00000000A22C618fd6b4D7E9A335C4B96B189a38") => Some(&TOWNS), + (8453, addr) if addr == address!("0x6cd905dF2Ed214b22e0d48FF17CD4200C1C6d8A3") => Some(&INTUITION), + (8453, addr) if addr == address!("0xc3De830EA07524a0761646a6a4e4be0e114a3C83") => Some(&UNISWAP_8453_114A3C83), + (8453, addr) if addr == address!("0x5b2193fDc451C1f847bE09CA9d13A4Bf60f8c86B") => Some(&SUPERFORM), + (8453, addr) if addr == address!("0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA") => Some(&USD_BASE_COIN), + (8453, addr) if addr == address!("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913") => Some(&USD_COIN), + (8453, addr) if addr == address!("0xacfE6019Ed1A7Dc6f7B508C02d1b04ec88cC21bf") => Some(&VENICE_TOKEN), + (8453, addr) if addr == address!("0xeF4461891DfB3AC8572cCf7C794664A8DD927945") => Some(&WALLETCONNECT_TOKEN_8453_DD927945), + (8453, addr) if addr == address!("0xA88594D404727625A9437C3f886C7643872296AE") => Some(&MOONWELL), + (8453, addr) if addr == address!("0x4200000000000000000000000000000000000006") => Some(&WRAPPED_ETHER_8453_00000006), + (8453, addr) if addr == address!("0x3e31966d4f81C72D2a55310A6365A56A4393E98D") => Some(&WORLD_MOBILE_TOKEN), + (8453, addr) if addr == address!("0xD7B99ffB8B2afc6fe013a17207cbe50f223aDc94") => Some(&XYO_NETWORK_8453_223ADC94), + (8453, addr) if addr == address!("0x9EaF8C1E34F05a589EDa6BAfdF391Cf6Ad3CB239") => Some(&YEARN_FINANCE_8453_AD3CB239), + (8453, addr) if addr == address!("0xaAC78d1219c08AecC8e37e03858FE885f5EF1799") => Some(&YIELD_GUILD_GAMES_8453_F5EF1799), + (8453, addr) if addr == address!("0xf43eB8De897Fbc7F2502483B2Bef7Bb9EA179229") => Some(&HORIZEN), + (8453, addr) if addr == address!("0xAA61bB7777bD01B684347961918f1E07fBbCe7CF") => Some(&BOUNDLESS_8453_FBBCE7CF), + (8453, addr) if addr == address!("0x1111111111166b7FE7bd91427724B487980aFc69") => Some(&ZORA), + (8453, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_8453_F13271CD), + (8453, addr) if addr == address!("0x3bB4445D30AC020a84c1b5A8A2C6248ebC9779D0") => Some(&TOKEN_0X_PROTOCOL_TOKEN_8453_BC9779D0), + (42161, addr) if addr == address!("0x6314C31A7a1652cE482cffe247E9CB7c3f4BB9aF") => Some(&TOKEN_1INCH_42161_3F4BB9AF), + (42161, addr) if addr == address!("0xba5DdD1f9d7F570dc94a51479a000E3BCE967196") => Some(&AAVE_42161_CE967196), + (42161, addr) if addr == address!("0x53691596d1BCe8CEa565b84d4915e69e03d9C99d") => Some(&ACROSS_PROTOCOL_TOKEN_42161_03D9C99D), + (42161, addr) if addr == address!("0x377c1Fc73D4D0f5600cd943776CED07c2B9783cd") => Some(&AEVO_42161_2B9783CD), + (42161, addr) if addr == address!("0xFA5Ed56A203466CbBC2430a43c66b9D8723528E7") => Some(&AGEUR_42161_723528E7), + (42161, addr) if addr == address!("0xb7910E8b16e63EFD51d5D1a093d56280012A3B9C") => Some(&ADVENTURE_GOLD_42161_012A3B9C), + (42161, addr) if addr == address!("0xeC76E8fe6e2242e6c2117caA244B9e2DE1569923") => Some(&AIOZ_NETWORK_42161_E1569923), + (42161, addr) if addr == address!("0xe7dcD50836d0A28c959c72D72122fEDB8E245A6C") => Some(&ALEPH_IM_42161_8E245A6C), + (42161, addr) if addr == address!("0xeF6124368c0B56556667e0de77eA008DfC0a71d1") => Some(&ALETHEA_ARTIFICIAL_LIQUID_INTELLIGENCE_42161_FC0A71D1), + (42161, addr) if addr == address!("0xC9CBf102c73fb77Ec14f8B4C8bd88e050a6b2646") => Some(&ALPHA_VENTURE_DAO_42161_0A6B2646), + (42161, addr) if addr == address!("0x1bfc5d35bf0f7B9e15dc24c78b8C02dbC1e95447") => Some(&ANKR_42161_C1E95447), + (42161, addr) if addr == address!("0x74885b4D524d497261259B38900f54e6dbAd2210") => Some(&APECOIN_42161_DBAD2210), + (42161, addr) if addr == address!("0xF01dB12F50D0CDF5Fe360ae005b9c52F92CA7811") => Some(&API3_42161_92CA7811), + (42161, addr) if addr == address!("0x912CE59144191C1204E64559FE8253a0e49E6548") => Some(&ARBITRUM_42161_E49E6548), + (42161, addr) if addr == address!("0xDac5094B7D59647626444a4F905060FCda4E656E") => Some(&ARKHAM_42161_DA4E656E), + (42161, addr) if addr == address!("0xAC9Ac2C17cdFED4AbC80A53c5553388575714d03") => Some(&AUTOMATA_42161_75714D03), + (42161, addr) if addr == address!("0xc7dEf82Ba77BAF30BbBc9b6162DC075b49092fb4") => Some(&AETHIR_TOKEN_42161_49092FB4), + (42161, addr) if addr == address!("0x23ee2343B892b1BB63503a4FAbc840E0e2C6810f") => Some(&AXELAR_42161_E2C6810F), + (42161, addr) if addr == address!("0xe88998Fb579266628aF6a03e3821d5983e5D0089") => Some(&AXIE_INFINITY_42161_3E5D0089), + (42161, addr) if addr == address!("0xBfa641051Ba0a0Ad1b0AcF549a89536A0D76472E") => Some(&BADGER_DAO_42161_0D76472E), + (42161, addr) if addr == address!("0x040d1EdC9569d4Bab2D15287Dc5A4F10F56a56B8") => Some(&BALANCER_42161_F56A56B8), + (42161, addr) if addr == address!("0x3450687EF141dCd6110b77c2DC44B008616AeE75") => Some(&BASIC_ATTENTION_TOKEN_42161_616AEE75), + (42161, addr) if addr == address!("0xa68Ec98D7ca870cF1Dd0b00EBbb7c4bF60A8e74d") => Some(&BICONOMY_42161_60A8E74D), + (42161, addr) if addr == address!("0x406C8dB506653D882295875F633bEC0bEb921C2A") => Some(&BITDAO_42161_EB921C2A), + (42161, addr) if addr == address!("0xf7e17BA61973bcDB61f471eFb989E47d13bD565D") => Some(&HARRYPOTTEROBAMASONIC10INU_42161_13BD565D), + (42161, addr) if addr == address!("0xEf171a5BA71348eff16616fd692855c2Fe606EB2") => Some(&BLUR_42161_FE606EB2), + (42161, addr) if addr == address!("0x7A24159672b83ED1b89467c9d6A99556bA06D073") => Some(&BANCOR_NETWORK_TOKEN_42161_BA06D073), + (42161, addr) if addr == address!("0x0D81E50bC677fa67341c44D7eaA9228DEE64A4e1") => Some(&BARNBRIDGE_42161_EE64A4E1), + (42161, addr) if addr == address!("0x31190254504622cEFdFA55a7d3d272e6462629a2") => Some(&BINANCE_USD_42161_462629A2), + (42161, addr) if addr == address!("0xCdc343ebf71e38F003eD6c80171F5B8D7cF58860") => Some(&PANCAKESWAP_42161_7CF58860), + (42161, addr) if addr == address!("0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf") => Some(&COINBASE_WRAPPED_BTC_42161_0EED33BF), + (42161, addr) if addr == address!("0x1DEBd73E752bEaF79865Fd6446b0c970EaE7732f") => Some(&COINBASE_WRAPPED_STAKED_ETH_42161_EAE7732F), + (42161, addr) if addr == address!("0x4E51aC49bC5e2d87e0EF713E9e5AB2D71EF4F336") => Some(&CELO_NATIVE_ASSET_WORMHOLE_42161_1EF4F336), + (42161, addr) if addr == address!("0x3a8B787f78D775AECFEEa15706D4221B40F345AB") => Some(&CELER_NETWORK_42161_40F345AB), + (42161, addr) if addr == address!("0x354A6dA3fcde098F8389cad84b0182725c6C91dE") => Some(&COMPOUND_42161_5C6C91DE), + (42161, addr) if addr == address!("0x6FE14d3CC2f7bDdffBa5CdB3BBE7467dd81ea101") => Some(&COTI_42161_D81EA101), + (42161, addr) if addr == address!("0xcb8b5CD20BdCaea9a010aC1F8d835824F5C87A04") => Some(&COW_PROTOCOL_42161_F5C87A04), + (42161, addr) if addr == address!("0x69b937dB799a9BECC9E8A6F0a5d36eA3657273bf") => Some(&COVALENT_42161_657273BF), + (42161, addr) if addr == address!("0x8ea3156f834A0dfC78F1A5304fAC2CdA676F354C") => Some(&CRONOS_42161_676F354C), + (42161, addr) if addr == address!("0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978") => Some(&CURVE_DAO_TOKEN_42161_FA034978), + (42161, addr) if addr == address!("0x319f865b287fCC10b30d8cE6144e8b6D1b476999") => Some(&CARTESI_42161_1B476999), + (42161, addr) if addr == address!("0x84F5c2cFba754E76DD5aE4fB369CfC920425E12b") => Some(&CRYPTEX_FINANCE_42161_0425E12B), + (42161, addr) if addr == address!("0x9DfFB23CAd3322440bCcFF7aB1C58E781dDBF144") => Some(&CIVIC_42161_1DDBF144), + (42161, addr) if addr == address!("0xaAFcFD42c9954C6689ef1901e03db742520829c5") => Some(&CONVEX_FINANCE_42161_520829C5), + (42161, addr) if addr == address!("0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1") => Some(&DAI_STABLECOIN_42161_C9000DA1), + (42161, addr) if addr == address!("0x3Be7cB2e9413Ef8F42b4A202a0114EB59b64e227") => Some(&DEXTOOLS_42161_9B64E227), + (42161, addr) if addr == address!("0xca642467C6Ebe58c13cB4A7091317f34E17ac05e") => Some(&DIA_42161_E17AC05E), + (42161, addr) if addr == address!("0xE3696a02b2C9557639E29d829E9C45EFa49aD47A") => Some(&DISTRICT0X_42161_A49AD47A), + (42161, addr) if addr == address!("0x4667cf53C4eDF659E402B733BEA42B18B68dd74c") => Some(&DEFI_PULSE_INDEX_42161_B68DD74C), + (42161, addr) if addr == address!("0x77b7787a09818502305C95d68A2571F090abb135") => Some(&DERIVE_42161_90ABB135), + (42161, addr) if addr == address!("0x51863cB90Ce5d6dA9663106F292fA27c8CC90c5a") => Some(&DYDX_42161_8CC90C5A), + (42161, addr) if addr == address!("0x606C3e5075e5555e79Aa15F1E9FACB776F96C248") => Some(&EIGENLAYER_42161_6F96C248), + (42161, addr) if addr == address!("0x3e4Cff6E50F37F731284A92d44AE943e17077fD4") => Some(&DOGELON_MARS_42161_17077FD4), + (42161, addr) if addr == address!("0xdf8F0c63D9335A0AbD89F9F752d293A98EA977d8") => Some(ÐENA_42161_8EA977D8), + (42161, addr) if addr == address!("0x7fa9549791EFc9030e1Ed3F25D18014163806758") => Some(&ENJIN_COIN_42161_63806758), + (42161, addr) if addr == address!("0xfeA31d704DEb0975dA8e77Bf13E04239e70d7c28") => Some(ÐEREUM_NAME_SERVICE_42161_E70D7C28), + (42161, addr) if addr == address!("0x2354c8e9Ea898c751F1A15Addeb048714D667f96") => Some(ÐERNITY_CHAIN_42161_4D667F96), + (42161, addr) if addr == address!("0x3b8db18e69d6686Ad9371A423aFe3Dd1065C94f1") => Some(&ESPRESSO_42161_065C94F1), + (42161, addr) if addr == address!("0x07D65C18CECbA423298c0aEB5d2BeDED4DFd5736") => Some(ÐER_FI_42161_4DFD5736), + (42161, addr) if addr == address!("0x863708032B5c328e11aBcbC0DF9D79C71Fc52a48") => Some(&EURO_COIN_42161_1FC52A48), + (42161, addr) if addr == address!("0x8553d254Cb6934b16F87D2e486b64BbD24C83C70") => Some(&HARVEST_FINANCE_42161_24C83C70), + (42161, addr) if addr == address!("0x4BE87C766A7CE11D5Cc864b6C3Abb7457dCC4cC9") => Some(&FETCH_AI_42161_7DCC4CC9), + (42161, addr) if addr == address!("0x849B40AB2469309117Ed1038c5A99894767C7282") => Some(&STAFI_42161_767C7282), + (42161, addr) if addr == address!("0xA8C25FdC09763A176353CC6a76882e05b4905FAe") => Some(&FLOKI_42161_B4905FAE), + (42161, addr) if addr == address!("0x63806C056Fa458c548Fb416B15E358A9D685710A") => Some(&FLUX_42161_D685710A), + (42161, addr) if addr == address!("0x3A1429d50E0cBBc45c997aF600541Fe1cc3D2923") => Some(&FORTA_42161_CC3D2923), + (42161, addr) if addr == address!("0xf929de51D91C77E42f5090069E0AD7A09e513c73") => Some(&SHAPESHIFT_FOX_TOKEN_42161_9E513C73), + (42161, addr) if addr == address!("0x7468a5d8E02245B00E8C0217fCE021C70Bc51305") => Some(&FRAX_42161_0BC51305), + (42161, addr) if addr == address!("0xd42785D323e608B9E99fa542bd8b1000D4c2Df37") => Some(&FANTOM_42161_D4C2DF37), + (42161, addr) if addr == address!("0xd9f9d2Ee2d3EFE420699079f16D9e924affFdEA4") => Some(&FRAX_SHARE_42161_AFFFDEA4), + (42161, addr) if addr == address!("0xc27E7325a6BEA1FcC06de7941473f5279bfd1182") => Some(&GALXE_42161_9BFD1182), + (42161, addr) if addr == address!("0x2A676eeAd159c4C8e8593471c6d666F02827FF8C") => Some(&GALA_42161_2827FF8C), + (42161, addr) if addr == address!("0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a") => Some(&GMX), + (42161, addr) if addr == address!("0xa0b862F60edEf4452F25B4160F177db44DeB6Cf1") => Some(&GNOSIS_TOKEN_42161_4DEB6CF1), + (42161, addr) if addr == address!("0x9623063377AD1B27544C965cCd7342f7EA7e88C7") => Some(&THE_GRAPH_42161_EA7E88C7), + (42161, addr) if addr == address!("0x7f9a7DB853Ca816B9A138AEe3380Ef34c437dEe0") => Some(&GITCOIN_42161_C437DEE0), + (42161, addr) if addr == address!("0x589d35656641d6aB57A545F08cf473eCD9B6D5F7") => Some(&GYEN_42161_D9B6D5F7), + (42161, addr) if addr == address!("0xd12Eeb0142D4Efe7Af82e4f29E5Af382615bcEeA") => Some(&HIGHSTREET_42161_615BCEEA), + (42161, addr) if addr == address!("0x177F394A3eD18FAa85c1462Ae626438a70294EF7") => Some(&HOPR_42161_70294EF7), + (42161, addr) if addr == address!("0x68731d6F14B827bBCfFbEBb62b19Daa18de1d79c") => Some(&IDOS_TOKEN), + (42161, addr) if addr == address!("0x61cA9D186f6b9a793BC08F6C79fd35f205488673") => Some(&ILLUVIUM_42161_05488673), + (42161, addr) if addr == address!("0x3cFD99593a7F035F717142095a3898e3Fca7783e") => Some(&IMMUTABLE_X_42161_FCA7783E), + (42161, addr) if addr == address!("0x2A2053cb633CAD465B4A8975eD3d7f09DF608F80") => Some(&INJECTIVE_42161_DF608F80), + (42161, addr) if addr == address!("0x25f05699548D3A0820b99f93c10c8BB573E27083") => Some(&JASMYCOIN_42161_73E27083), + (42161, addr) if addr == address!("0x010700AB046Dd8e92b0e3587842080Df36364ed3") => Some(&KINTO), + (42161, addr) if addr == address!("0xf75eE6D319741057a82a88Eeff1DbAFAB7307b69") => Some(&KRYLL_42161_B7307B69), + (42161, addr) if addr == address!("0x3A18dcC9745eDcD1Ef33ecB93b0b6eBA5671e7Ca") => Some(&KUJIRA_42161_5671E7CA), + (42161, addr) if addr == address!("0x13Ad51ed4F1B7e9Dc168d8a00cB3f4dDD85EfA60") => Some(&LIDO_DAO_42161_D85EFA60), + (42161, addr) if addr == address!("0xf97f4df75117a78c1A5a0DBb814Af92458539FB4") => Some(&CHAINLINK_TOKEN_42161_58539FB4), + (42161, addr) if addr == address!("0x349fc93da004a63F3B1343361465981330A40B25") => Some(&LITENTRY_42161_30A40B25), + (42161, addr) if addr == address!("0x289ba1701C2F088cf0faf8B3705246331cB8A839") => Some(&LIVEPEER_42161_1CB8A839), + (42161, addr) if addr == address!("0xfb9E5D956D889D91a82737B9bFCDaC1DCE3e1449") => Some(&LIQUITY_42161_CE3E1449), + (42161, addr) if addr == address!("0x46d0cE7de6247b0A95f67b43B589b4041BaE7fbE") => Some(&LOOPRINGCOIN_V2_42161_1BAE7FBE), + (42161, addr) if addr == address!("0x93b346b6BC2548dA6A1E7d98E9a421B42541425b") => Some(&LIQUITY_USD_42161_2541425B), + (42161, addr) if addr == address!("0x539bdE0d7Dbd336b79148AA742883198BBF60342") => Some(&MAGIC), + (42161, addr) if addr == address!("0x442d24578A564EF628A65e6a7E3e7be2a165E231") => Some(&DECENTRALAND_42161_A165E231), + (42161, addr) if addr == address!("0x533A7B414CD1236815a5e09F1E97FC7d5c313739") => Some(&MASK_NETWORK_42161_5C313739), + (42161, addr) if addr == address!("0x99F40b01BA9C469193B360f72740E416B17Ac332") => Some(&MATH_42161_B17AC332), + (42161, addr) if addr == address!("0x561877b6b3DD7651313794e5F2894B2F18bE0766") => Some(&POLYGON_42161_18BE0766), + (42161, addr) if addr == address!("0x7F728F3595db17B0B359f4FC47aE80FAd2e33769") => Some(&METIS_42161_D2E33769), + (42161, addr) if addr == address!("0xB20A02dfFb172C474BC4bDa3fD6f4eE70C04daf2") => Some(&MAGIC_INTERNET_MONEY_42161_0C04DAF2), + (42161, addr) if addr == address!("0x2e9a6Df78E42a30712c10a9Dc4b1C8656f8F2879") => Some(&MAKER_42161_6F8F2879), + (42161, addr) if addr == address!("0x8f5c1A99b1df736Ad685006Cb6ADCA7B7Ae4b514") => Some(&MELON_42161_7AE4B514), + (42161, addr) if addr == address!("0x9c1a1C7bA9c2602123FD7EF3eb41a769edf6C53A") => Some(&MANTLE_42161_EDF6C53A), + (42161, addr) if addr == address!("0x96c42662820F6Ea32f0A61A06a38a72B206aABaC") => Some(&MOG_COIN_42161_206AABAC), + (42161, addr) if addr == address!("0xE390C0B46bd723995BE02640E6F1e1c802F620AC") => Some(&MORPHO_TOKEN_42161_02F620AC), + (42161, addr) if addr == address!("0x29024832eC3baBF5074D4F46102aA988097f0Ca0") => Some(&MAPLE_42161_097F0CA0), + (42161, addr) if addr == address!("0x7b9b94aebe5E2039531af8E31045f377EcD9A39A") => Some(&MULTICHAIN_42161_ECD9A39A), + (42161, addr) if addr == address!("0x5445972E76c5e4CEdD12B6e2BceF69133E15992F") => Some(&GENSOKISHI_METAVERSE_42161_3E15992F), + (42161, addr) if addr == address!("0x91b468Fe3dce581D7a6cFE34189F1314b6862eD6") => Some(&MXC_42161_B6862ED6), + (42161, addr) if addr == address!("0x53236015A675fcB937485F1AE58040e4Fb920d5b") => Some(&POLYSWARM_42161_FB920D5B), + (42161, addr) if addr == address!("0xBE06ca305A5Cb49ABf6B1840da7c42690406177b") => Some(&NKN_42161_0406177B), + (42161, addr) if addr == address!("0x597701b32553b9fa473e21362D480b3a6B569711") => Some(&NUMERAIRE_42161_6B569711), + (42161, addr) if addr == address!("0x933d31561e470478079FEB9A6Dd2691fAD8234DF") => Some(&OCEAN_PROTOCOL_42161_AD8234DF), + (42161, addr) if addr == address!("0x6FEb262FEb0f775B5312D2e009923f7f58AE423E") => Some(&ORIGIN_PROTOCOL_42161_58AE423E), + (42161, addr) if addr == address!("0xd962C1895c46AC0378C502c207748b7061421e8e") => Some(&OMG_NETWORK_42161_61421E8E), + (42161, addr) if addr == address!("0xA2d52A05B8Bead5d824DF54Dd1AA63188B37A5E7") => Some(&ONDO_FINANCE_42161_8B37A5E7), + (42161, addr) if addr == address!("0x1BDCC2075d5370293E248Cab0173eC3E551e6218") => Some(&ORION_PROTOCOL_42161_551E6218), + (42161, addr) if addr == address!("0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8") => Some(&PENDLE_42161_B9A8C9E8), + (42161, addr) if addr == address!("0x35E6A59F786d9266c7961eA28c7b768B33959cbB") => Some(&PEPE_42161_33959CBB), + (42161, addr) if addr == address!("0x753D224bCf9AAFaCD81558c32341416df61D3DAC") => Some(&PERPETUAL_PROTOCOL_42161_F61D3DAC), + (42161, addr) if addr == address!("0xac7CE9F2794e01c0D27b096C52f592e343D77cbf") => Some(&PIRATE_NATION_42161_43D77CBF), + (42161, addr) if addr == address!("0x73efDC761596328461B68E5FC58c3284CB15ba13") => Some(&PLUME_42161_CB15BA13), + (42161, addr) if addr == address!("0x044d8e7F3A17751D521efEa8CCf9282268fE08CC") => Some(&POLYGON_ECOSYSTEM_TOKEN_42161_68FE08CC), + (42161, addr) if addr == address!("0xeeeB5EaC2dB7A7Fc28134aA3248580d48b016b64") => Some(&POLKASTARTER_42161_8B016B64), + (42161, addr) if addr == address!("0xE12F29704F635F4A6E7Ae154838d21F9B33809e9") => Some(&POLYMATH_42161_B33809E9), + (42161, addr) if addr == address!("0xdA0a57B710768ae17941a9Fa33f8B720c8bD9ddD") => Some(&MARLIN_42161_C8BD9DDD), + (42161, addr) if addr == address!("0x6380F3d0C1412a80EB00F49064DA30749DB991DE") => Some(&PORTAL_42161_9DB991DE), + (42161, addr) if addr == address!("0x4e91F2AF1ee0F84B529478f19794F5AFD423e4A6") => Some(&POWER_LEDGER_42161_D423E4A6), + (42161, addr) if addr == address!("0x8d8e1b6ffc6832E8D2eF0DE8a3d957cAE7ac5067") => Some(&PRIME_42161_E7AC5067), + (42161, addr) if addr == address!("0x82164a8B646401a8776F9dC5c8Cba35DcAf60Cd2") => Some(&PARSIQ_42161_CAF60CD2), + (42161, addr) if addr == address!("0x327006c8712FE0AbdbbD55B7999DB39b0967342E") => Some(&PAYPAL_USD_42161_0967342E), + (42161, addr) if addr == address!("0xC7557C73e0eCa2E1BF7348bB6874Aee63C7eFF85") => Some(&QUANT_42161_3C7EFF85), + (42161, addr) if addr == address!("0x3c45038f4807c5bb72F6BC72c2A2B9c012155e49") => Some(&RADICLE_42161_12155E49), + (42161, addr) if addr == address!("0xaeF5bbcbFa438519a5ea80B4c7181B4E78d419f2") => Some(&RAI_REFLEX_INDEX_42161_78D419F2), + (42161, addr) if addr == address!("0xCf78572A8fE97b2B9a4B9709f6a7D9a863c1b8E0") => Some(&RARIBLE_42161_63C1B8E0), + (42161, addr) if addr == address!("0x2E9AE8f178d5Ea81970C7799A377B3985cbC335F") => Some(&RUBIC_42161_5CBC335F), + (42161, addr) if addr == address!("0x9fA891e1dB0a6D1eEAC4B929b5AAE1011C79a204") => Some(&REPUBLIC_TOKEN_42161_1C79A204), + (42161, addr) if addr == address!("0x1Cb5bBc64e148C5b889E3c667B49edF78BB92171") => Some(&REQUEST_42161_8BB92171), + (42161, addr) if addr == address!("0xef888bcA6AB6B1d26dbeC977C455388ecd794794") => Some(&RARI_GOVERNANCE_TOKEN_42161_CD794794), + (42161, addr) if addr == address!("0xE575586566b02A16338c199c23cA6d295D794e66") => Some(&IEXEC_RLC_42161_5D794E66), + (42161, addr) if addr == address!("0xC8a4EeA31E9B6b61c406DF013DD4FEc76f21E279") => Some(&RENDER_TOKEN_42161_6F21E279), + (42161, addr) if addr == address!("0xB766039cc6DB368759C1E56B79AFfE831d0Cc507") => Some(&ROCKET_POOL_PROTOCOL_42161_1D0CC507), + (42161, addr) if addr == address!("0xCa5Ca9083702c56b481D1eec86F1776FDbd2e594") => Some(&RESERVE_RIGHTS_42161_DBD2E594), + (42161, addr) if addr == address!("0xd1318eb19DBF2647743c720ed35174efd64e3DAC") => Some(&THE_SANDBOX_42161_D64E3DAC), + (42161, addr) if addr == address!("0x1629c4112952a7a377cB9B8d7d8c903092f34B63") => Some(&STADER_42161_92F34B63), + (42161, addr) if addr == address!("0x5033833c9fe8B9d3E09EEd2f73d2aaF7E3872fd1") => Some(&SHIBA_INU_42161_E3872FD1), + (42161, addr) if addr == address!("0x4F9b7DEDD8865871dF65c5D26B1c2dD537267878") => Some(&SKALE_42161_37267878), + (42161, addr) if addr == address!("0x707F635951193dDaFBB40971a0fCAAb8A6415160") => Some(&STATUS_42161_A6415160), + (42161, addr) if addr == address!("0xcBA56Cd8216FCBBF3fA6DF6137F3147cBcA37D60") => Some(&SYNTHETIX_NETWORK_TOKEN_42161_BCA37D60), + (42161, addr) if addr == address!("0xb2BE52744a804Cc732d606817C2572C5A3B264e7") => Some(&UNISOCKS_42161_A3B264E7), + (42161, addr) if addr == address!("0xb74Da9FE2F96B9E0a5f4A3cf0b92dd2bEC617124") => Some(&SOL_WORMHOLE_42161_EC617124), + (42161, addr) if addr == address!("0x3E6648C5a70A150A88bCE65F4aD4d506Fe15d2AF") => Some(&SPELL_TOKEN_42161_FE15D2AF), + (42161, addr) if addr == address!("0x53e70cc1d527b524A1C46Eaa892e4CB35d2ba901") => Some(&SPX6900_42161_5D2BA901), + (42161, addr) if addr == address!("0x1337420dED5ADb9980CFc35f8f2B054ea86f8aB1") => Some(&SQD), + (42161, addr) if addr == address!("0xe018C7a3d175Fb0fE15D70Da2c874d3CA16313EC") => Some(&STARGATE_FINANCE_42161_A16313EC), + (42161, addr) if addr == address!("0xE6320ebF209971b4F4696F7f0954b8457Aa2FCC2") => Some(&STORJ_TOKEN_42161_7AA2FCC2), + (42161, addr) if addr == address!("0x7f9cf5a2630a0d58567122217dF7609c26498956") => Some(&SUPERFARM_42161_26498956), + (42161, addr) if addr == address!("0xA970AF1a584579B618be4d69aD6F73459D112F95") => Some(&SYNTH_SUSD_42161_9D112F95), + (42161, addr) if addr == address!("0xd4d42F0b6DEF4CE0383636770eF773390d85c61A") => Some(&SUSHI_42161_0D85C61A), + (42161, addr) if addr == address!("0x2C96bE2612bec20fe2975C3ACFcbBe61a58f2571") => Some(&SWELL_42161_A58F2571), + (42161, addr) if addr == address!("0x1bCfc0B4eE1471674cd6A9F6B363A034375eAD84") => Some(&SYNAPSE_42161_375EAD84), + (42161, addr) if addr == address!("0x0945Cae3ae47cb384b2d47BC448Dc6A9dEC21F55") => Some(&THRESHOLD_NETWORK_42161_DEC21F55), + (42161, addr) if addr == address!("0x7E2a1eDeE171C5B19E6c54D73752396C0A572594") => Some(&TBTC_42161_0A572594), + (42161, addr) if addr == address!("0xd58D345Fd9c82262E087d2D0607624B410D88242") => Some(&TELLOR_42161_10D88242), + (42161, addr) if addr == address!("0xBfAE6fecD8124ba33cbB2180aAb0Fe4c03914A5A") => Some(&TRIBE_42161_03914A5A), + (42161, addr) if addr == address!("0x5C816d4582c857dcadb1bB1F62Ad6c9DEde4576a") => Some(&TURBO_42161_EDE4576A), + (42161, addr) if addr == address!("0xd693Ec944A85eeca4247eC1c3b130DCa9B0C3b22") => Some(&UMA_VOTING_TOKEN_V1_42161_9B0C3B22), + (42161, addr) if addr == address!("0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0") => Some(&UNISWAP_42161_72F1F7F0), + (42161, addr) if addr == address!("0x7550dE0A4b9Fb8CAbA8c32E72Ee356AFdd217A33") => Some(&WORLD_LIBERTY_FINANCIAL_USD_42161_DD217A33), + (42161, addr) if addr == address!("0xaf88d065e77c8cC2239327C5EDb3A432268e5831") => Some(&USDCOIN_42161_268E5831), + (42161, addr) if addr == address!("0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8") => Some(&BRIDGED_USDC_42161_BDDB5CC8), + (42161, addr) if addr == address!("0x78df3a6044Ce3cB1905500345B967788b699dF8f") => Some(&PAX_DOLLAR_42161_B699DF8F), + (42161, addr) if addr == address!("0x6491c05A82219b8D1479057361ff1654749b876b") => Some(&USDS_STABLECOIN_42161_749B876B), + (42161, addr) if addr == address!("0x7639AB8599f1b417CbE4ceD492fB30162140AbbB") => Some(&USUAL_42161_2140ABBB), + (42161, addr) if addr == address!("0x1c8Ec4DE3c2BFD3050695D89853EC6d78AE650bb") => Some(&WRAPPED_AMPLEFORTH_42161_8AE650BB), + (42161, addr) if addr == address!("0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f") => Some(&WRAPPED_BTC_42161_AEFC5B0F), + (42161, addr) if addr == address!("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1") => Some(&WRAPPED_ETHER_42161_523FBAB1), + (42161, addr) if addr == address!("0x4D1d7134B87490AE5eEbdB22A5820d7d0E1980bf") => Some(&WORLD_LIBERTY_FINANCIAL_42161_0E1980BF), + (42161, addr) if addr == address!("0xcAFcD85D8ca7Ad1e1C6F82F651fA15E33AEfD07b") => Some(&WOO_NETWORK_42161_3AEFD07B), + (42161, addr) if addr == address!("0x9B86f3c7d145979ec6b2F42eD7f92D06cfC6C9d3") => Some(&TETHER_GOLD_42161_CFC6C9D3), + (42161, addr) if addr == address!("0x58BbC087e36Db40a84b22c1B93a042294deEAFEd") => Some(&CHAIN_42161_4DEEAFED), + (42161, addr) if addr == address!("0xa05245Ade25cC1063EE50Cf7c083B4524c1C4302") => Some(&XSGD_42161_4C1C4302), + (42161, addr) if addr == address!("0x82e3A8F066a6989666b031d916c43672085b1582") => Some(&YEARN_FINANCE_42161_085B1582), + (42161, addr) if addr == address!("0x6DdBbcE7858D276678FC2B36123fD60547b88954") => Some(&ZETACHAIN_42161_47B88954), + (42161, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_42161_F13271CD), + (42161, addr) if addr == address!("0xBD591Bd4DdB64b77B5f76Eab8f03d02519235Ae2") => Some(&TOKEN_0X_PROTOCOL_TOKEN_42161_19235AE2), + (42220, addr) if addr == address!("0xD629eb00dEced2a080B7EC630eF6aC117e614f1b") => Some(&WRAPPED_BITCOIN), + (42220, addr) if addr == address!("0x471EcE3750Da237f93B8E339c536989b8978a438") => Some(&CELO), + (42220, addr) if addr == address!("0xcebA9300f2b948710d2653dD7B07f33A8B32118C") => Some(&USDCOIN_42220_8B32118C), + (42220, addr) if addr == address!("0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e") => Some(&TETHER_USD_42220_87483D5E), + (42220, addr) if addr == address!("0x2DEf4285787d58a2f811AF24755A8150622f4361") => Some(&WRAPPED_ETHER_42220_622F4361), + (43114, addr) if addr == address!("0xd501281565bf7789224523144Fe5D98e8B28f267") => Some(&TOKEN_1INCH_43114_8B28F267), + (43114, addr) if addr == address!("0x63a72806098Bd3D9520cC43356dD78afe5D386D9") => Some(&AAVE_43114_E5D386D9), + (43114, addr) if addr == address!("0xAEC8318a9a59bAEb39861d10ff6C7f7bf1F96C57") => Some(&AGEUR_43114_F1F96C57), + (43114, addr) if addr == address!("0x2147EFFF675e4A4eE1C2f918d181cDBd7a8E208f") => Some(&ALPHA_VENTURE_DAO_43114_7A8E208F), + (43114, addr) if addr == address!("0x20CF1b6E9d856321ed4686877CF4538F2C84B4dE") => Some(&ANKR_43114_2C84B4DE), + (43114, addr) if addr == address!("0x44c784266cf024a60e8acF2427b9857Ace194C5d") => Some(&AXELAR_43114_CE194C5D), + (43114, addr) if addr == address!("0x98443B96EA4b0858FDF3219Cd13e98C7A4690588") => Some(&BASIC_ATTENTION_TOKEN_43114_A4690588), + (43114, addr) if addr == address!("0x9C9e5fD8bbc25984B178FdCE6117Defa39d2db39") => Some(&BINANCE_USD_43114_39D2DB39), + (43114, addr) if addr == address!("0xc3048E19E76CB9a3Aa9d77D8C03c29Fc906e2437") => Some(&COMPOUND_43114_906E2437), + (43114, addr) if addr == address!("0x6b289CCeAA8639e3831095D75A3e43520faBf552") => Some(&CARTESI_43114_0FABF552), + (43114, addr) if addr == address!("0xd586E7F844cEa2F87f50152665BCbc2C279D8d70") => Some(&DAI_E_TOKEN), + (43114, addr) if addr == address!("0x961C8c0B1aaD0c0b10a51FeF6a867E3091BCef17") => Some(&DEFI_YIELD_PROTOCOL_43114_91BCEF17), + (43114, addr) if addr == address!("0xC891EB4cbdEFf6e073e859e987815Ed1505c2ACD") => Some(&EURO_COIN_43114_505C2ACD), + (43114, addr) if addr == address!("0xc4B06F17ECcB2215a5DBf042C672101Fc20daF55") => Some(&FLUX_43114_C20DAF55), + (43114, addr) if addr == address!("0xD24C2Ad096400B6FBcd2ad8B24E7acBc21A1da64") => Some(&FRAX_43114_21A1DA64), + (43114, addr) if addr == address!("0x214DB107654fF987AD859F34125307783fC8e387") => Some(&FRAX_SHARE_43114_3FC8E387), + (43114, addr) if addr == address!("0x62edc0692BD897D2295872a9FFCac5425011c661") => Some(&GMX_43114_5011C661), + (43114, addr) if addr == address!("0x8a0cAc13c7da965a312f08ea4229c37869e85cB9") => Some(&THE_GRAPH_43114_69E85CB9), + (43114, addr) if addr == address!("0x26deBD39D5eD069770406FCa10A0E4f8d2c743eB") => Some(&GUNZ), + (43114, addr) if addr == address!("0x5947BB275c521040051D82396192181b413227A3") => Some(&CHAINLINK_TOKEN_43114_413227A3), + (43114, addr) if addr == address!("0x130966628846BFd36ff31a822705796e8cb8C18D") => Some(&MAGIC_INTERNET_MONEY_43114_8CB8C18D), + (43114, addr) if addr == address!("0x88128fd4b259552A9A1D457f435a6527AAb72d42") => Some(&MAKER_43114_AAB72D42), + (43114, addr) if addr == address!("0x9Fb9a33956351cf4fa040f65A13b835A3C8764E3") => Some(&MULTICHAIN_43114_3C8764E3), + (43114, addr) if addr == address!("0xfB98B335551a418cD0737375a2ea0ded62Ea213b") => Some(&PENDLE_43114_62EA213B), + (43114, addr) if addr == address!("0x97Cd1CFE2ed5712660bb6c14053C0EcB031Bff7d") => Some(&RAI_REFLEX_INDEX_43114_031BFF7D), + (43114, addr) if addr == address!("0xBeC243C995409E6520D7C41E404da5dEba4b209B") => Some(&SYNTHETIX_NETWORK_TOKEN_43114_BA4B209B), + (43114, addr) if addr == address!("0xFE6B19286885a4F7F55AdAD09C3Cd1f906D2478F") => Some(&SOL_WORMHOLE_43114_06D2478F), + (43114, addr) if addr == address!("0xCE1bFFBD5374Dac86a2893119683F4911a2F7814") => Some(&SPELL_TOKEN_43114_1A2F7814), + (43114, addr) if addr == address!("0x2F6F07CDcf3588944Bf4C42aC74ff24bF56e7590") => Some(&STARGATE_FINANCE_43114_F56E7590), + (43114, addr) if addr == address!("0x37B608519F91f70F2EeB0e5Ed9AF4061722e4F76") => Some(&SUSHI_43114_722E4F76), + (43114, addr) if addr == address!("0x1f1E7c893855525b303f99bDF5c3c05Be09ca251") => Some(&SYNAPSE_43114_E09CA251), + (43114, addr) if addr == address!("0x3Bd2B1c7ED8D396dbb98DED3aEbb41350a5b2339") => Some(&UMA_VOTING_TOKEN_V1_43114_0A5B2339), + (43114, addr) if addr == address!("0x8eBAf22B6F053dFFeaf46f4Dd9eFA95D89ba8580") => Some(&UNI_E_TOKEN), + (43114, addr) if addr == address!("0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E") => Some(&USDC_TOKEN), + (43114, addr) if addr == address!("0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7") => Some(&TETHER_USD_43114_4DF4A8C7), + (43114, addr) if addr == address!("0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7") => Some(&WRAPPED_AVAX), + (43114, addr) if addr == address!("0x50b7545627a5162F82A992c33b87aDc75187B218") => Some(&WRAPPED_BTC_43114_5187B218), + (43114, addr) if addr == address!("0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB") => Some(&WRAPPED_ETHER_43114_6BC10BAB), + (43114, addr) if addr == address!("0xaBC9547B534519fF73921b1FBA6E672b5f58D083") => Some(&WOO_NETWORK_43114_5F58D083), + (43114, addr) if addr == address!("0x9eAaC1B23d935365bD7b542Fe22cEEe2922f52dc") => Some(&YEARN_FINANCE_43114_922F52DC), + (43114, addr) if addr == address!("0x6985884C4392D348587B19cb9eAAf157F13271cd") => Some(&LAYERZERO_43114_F13271CD), + (43114, addr) if addr == address!("0x596fA47043f99A4e0F122243B841E55375cdE0d2") => Some(&TOKEN_0X_PROTOCOL_TOKEN_43114_75CDE0D2), + (80001, addr) if addr == address!("0xA6FA4fB5f76172d178d61B04b0ecd319C5d1C0aa") => Some(&WRAPPED_ETHER_80001_C5D1C0AA), + (80001, addr) if addr == address!("0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889") => Some(&WRAPPED_MATIC_80001_FB032889), + (81457, addr) if addr == address!("0xb1a5700fA2358173Fe465e6eA4Ff52E36e88E2ad") => Some(&BLAST), + (7777777, addr) if addr == address!("0xCccCCccc7021b32EBb4e8C08314bD62F7c653EC4") => Some(&USD_COIN_BRIDGED_FROM_ETHEREUM), + (11155111, addr) if addr == address!("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") => Some(&UNISWAP_11155111_4201F984), + (11155111, addr) if addr == address!("0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14") => Some(&WRAPPED_ETHER_11155111_324D6B14), + _ => None, + } +} diff --git a/server/crates/arbiter-tokens-registry/src/lib.rs b/server/crates/arbiter-tokens-registry/src/lib.rs index c469d0c..d850a94 100644 --- a/server/crates/arbiter-tokens-registry/src/lib.rs +++ b/server/crates/arbiter-tokens-registry/src/lib.rs @@ -1 +1 @@ -pub mod evm; +pub mod evm; diff --git a/server/rules/safecell/new-inline.yaml b/server/rules/safecell/new-inline.yaml index 48c2e4e..2d23a41 100644 --- a/server/rules/safecell/new-inline.yaml +++ b/server/rules/safecell/new-inline.yaml @@ -1,10 +1,10 @@ -id: safecell-new-inline -language: Rust -rule: - pattern: $CELL.write_inline(|$W| $BODY); - follows: - pattern: let mut $CELL = SafeCell::new($INIT); -fix: - template: let mut $CELL = SafeCell::new_inline(|$W| $BODY); - expandStart: +id: safecell-new-inline +language: Rust +rule: + pattern: $CELL.write_inline(|$W| $BODY); + follows: + pattern: let mut $CELL = SafeCell::new($INIT); +fix: + template: let mut $CELL = SafeCell::new_inline(|$W| $BODY); + expandStart: pattern: let mut $CELL = SafeCell::new($INIT) \ No newline at end of file diff --git a/server/rules/safecell/read-inline.yaml b/server/rules/safecell/read-inline.yaml index e5bbee6..4a2dadd 100644 --- a/server/rules/safecell/read-inline.yaml +++ b/server/rules/safecell/read-inline.yaml @@ -1,17 +1,17 @@ -id: safecell-read-inline -language: Rust -rule: - pattern: - context: | - { - let $READ = $CELL.read(); - $$$BODY - } - selector: block - inside: - kind: block -fix: - template: | - $CELL.read_inline(|$READ| { - $$$BODY +id: safecell-read-inline +language: Rust +rule: + pattern: + context: | + { + let $READ = $CELL.read(); + $$$BODY + } + selector: block + inside: + kind: block +fix: + template: | + $CELL.read_inline(|$READ| { + $$$BODY }); \ No newline at end of file diff --git a/server/rules/safecell/write-inline.yaml b/server/rules/safecell/write-inline.yaml index cfa13fe..08ef99f 100644 --- a/server/rules/safecell/write-inline.yaml +++ b/server/rules/safecell/write-inline.yaml @@ -1,13 +1,13 @@ -id: safecell-write-inline -language: Rust -rule: - pattern: | - { - let mut $WRITE = $CELL.write(); - $$$BODY - } -fix: - template: | - $CELL.write_inline(|$WRITE| { - $$$BODY +id: safecell-write-inline +language: Rust +rule: + pattern: | + { + let mut $WRITE = $CELL.write(); + $$$BODY + } +fix: + template: | + $CELL.write_inline(|$WRITE| { + $$$BODY }); \ No newline at end of file diff --git a/server/sgconfig.yml b/server/sgconfig.yml index b0f5823..dfe7faf 100644 --- a/server/sgconfig.yml +++ b/server/sgconfig.yml @@ -1,2 +1,2 @@ -ruleDirs: -- ./rules +ruleDirs: +- ./rules diff --git a/server/supply-chain/audits.toml b/server/supply-chain/audits.toml index eb9b258..4f61c12 100644 --- a/server/supply-chain/audits.toml +++ b/server/supply-chain/audits.toml @@ -1,993 +1,993 @@ - -# cargo-vet audits file - -[[audits.alloy-primitives]] -who = "CleverWild " -criteria = "safe-to-deploy" -version = "1.5.7" - -[[audits.console]] -who = "CleverWild " -criteria = "safe-to-deploy" -version = "0.15.11" - -[[audits.encode_unicode]] -who = "CleverWild " -criteria = "safe-to-deploy" -version = "0.3.6" - -[[audits.futures-timer]] -who = "CleverWild " -criteria = "safe-to-run" -version = "3.0.3" - -[[audits.insta]] -who = "CleverWild " -criteria = "safe-to-run" -version = "1.46.3" - -[[audits.pin-project]] -who = "CleverWild " -criteria = "safe-to-deploy" -version = "0.2.16" - -[[audits.protoc-bin-vendored]] -who = "CleverWild " -criteria = "safe-to-deploy" -version = "3.2.0" - -[[audits.similar]] -who = "hdbg " -criteria = "safe-to-deploy" -version = "2.2.1" - -[[audits.test-log]] -who = "hdbg " -criteria = "safe-to-deploy" -delta = "0.2.18 -> 0.2.19" - -[[audits.test-log-macros]] -who = "hdbg " -criteria = "safe-to-deploy" -delta = "0.2.18 -> 0.2.19" - -[[audits.wasm-bindgen]] -who = "CleverWild " -criteria = "safe-to-deploy" -delta = "0.2.100 -> 0.2.114" - -[[trusted.addr2line]] -criteria = "safe-to-deploy" -user-id = 4415 # Philip Craig (philipc) -start = "2019-05-01" -end = "2027-03-14" - -[[trusted.aho-corasick]] -criteria = "safe-to-deploy" -user-id = 189 # Andrew Gallant (BurntSushi) -start = "2019-03-28" -end = "2027-03-14" - -[[trusted.anyhow]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-10-05" -end = "2027-03-14" - -[[trusted.async-stream]] -criteria = "safe-to-deploy" -user-id = 10 # Carl Lerche (carllerche) -start = "2019-06-07" -end = "2027-03-14" - -[[trusted.async-stream]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2021-04-21" -end = "2027-03-14" - -[[trusted.async-stream-impl]] -criteria = "safe-to-deploy" -user-id = 10 # Carl Lerche (carllerche) -start = "2019-08-13" -end = "2027-03-14" - -[[trusted.async-stream-impl]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2021-04-21" -end = "2027-03-14" - -[[trusted.async-trait]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-07-23" -end = "2027-03-14" - -[[trusted.auto_impl]] -criteria = "safe-to-deploy" -user-id = 3204 # Ashley Mannix (KodrAus) -start = "2022-06-01" -end = "2027-03-14" - -[[trusted.aws-lc-rs]] -criteria = "safe-to-deploy" -user-id = 156764 # Justin W Smith (justsmth) -start = "2023-04-11" -end = "2027-03-14" - -[[trusted.aws-lc-sys]] -criteria = "safe-to-deploy" -user-id = 156764 # Justin W Smith (justsmth) -start = "2022-11-09" -end = "2027-03-14" - -[[trusted.backtrace]] -criteria = "safe-to-deploy" -user-id = 55123 # rust-lang-owner -start = "2025-05-06" -end = "2027-03-14" - -[[trusted.bitflags]] -criteria = "safe-to-deploy" -user-id = 3204 # Ashley Mannix (KodrAus) -start = "2019-05-02" -end = "2027-03-14" - -[[trusted.bytes]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2019-11-27" -end = "2027-03-14" - -[[trusted.bytes]] -criteria = "safe-to-deploy" -user-id = 6741 # Alice Ryhl (Darksonn) -start = "2021-01-11" -end = "2027-03-14" - -[[trusted.cc]] -criteria = "safe-to-deploy" -user-id = 55123 # rust-lang-owner -start = "2022-10-29" -end = "2027-03-14" - -[[trusted.cmake]] -criteria = "safe-to-deploy" -user-id = 55123 # rust-lang-owner -start = "2022-10-29" -end = "2027-03-14" - -[[trusted.crossbeam-utils]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2020-10-12" -end = "2027-03-14" - -[[trusted.derive_more]] -criteria = "safe-to-deploy" -user-id = 3797 # Jelte Fennema-Nio (JelteF) -start = "2019-05-25" -end = "2027-03-14" - -[[trusted.derive_more-impl]] -criteria = "safe-to-deploy" -user-id = 3797 # Jelte Fennema-Nio (JelteF) -start = "2023-07-23" -end = "2027-03-14" - -[[trusted.dyn-clone]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-12-23" -end = "2027-03-14" - -[[trusted.ff]] -criteria = "safe-to-deploy" -user-id = 6289 # Jack Grigg (str4d) -start = "2021-08-11" -end = "2027-03-14" - -[[trusted.find-msvc-tools]] -criteria = "safe-to-deploy" -user-id = 539 # Josh Stone (cuviper) -start = "2025-08-29" -end = "2027-03-14" - -[[trusted.flate2]] -criteria = "safe-to-deploy" -user-id = 980 # Sebastian Thiel (Byron) -start = "2023-08-15" -end = "2027-03-14" - -[[trusted.futures]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2020-10-05" -end = "2027-03-14" - -[[trusted.futures-channel]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2020-10-05" -end = "2027-03-14" - -[[trusted.futures-core]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2020-10-05" -end = "2027-03-14" - -[[trusted.futures-executor]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2020-10-05" -end = "2027-03-14" - -[[trusted.futures-io]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2020-10-05" -end = "2027-03-14" - -[[trusted.futures-macro]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2020-10-05" -end = "2027-03-14" - -[[trusted.futures-sink]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2020-10-05" -end = "2027-03-14" - -[[trusted.futures-task]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2019-07-29" -end = "2027-03-14" - -[[trusted.futures-util]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2020-10-05" -end = "2027-03-14" - -[[trusted.group]] -criteria = "safe-to-deploy" -user-id = 1244 # ebfull -start = "2019-10-08" -end = "2027-03-14" - -[[trusted.h2]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2019-03-13" -end = "2027-02-14" - -[[trusted.hashbrown]] -criteria = "safe-to-deploy" -user-id = 2915 # Amanieu d'Antras (Amanieu) -start = "2019-04-02" -end = "2027-03-14" - -[[trusted.hashbrown]] -criteria = "safe-to-deploy" -user-id = 55123 # rust-lang-owner -start = "2025-04-30" -end = "2027-02-14" - -[[trusted.http]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2019-04-05" -end = "2027-03-14" - -[[trusted.http-body-util]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2022-10-25" -end = "2027-03-14" - -[[trusted.httparse]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2019-07-03" -end = "2027-03-14" - -[[trusted.hyper]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2019-03-01" -end = "2027-03-14" - -[[trusted.hyper-util]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2022-01-15" -end = "2027-02-14" - -[[trusted.id-arena]] -criteria = "safe-to-deploy" -user-id = 696 # Nick Fitzgerald (fitzgen) -start = "2026-01-14" -end = "2027-03-14" - -[[trusted.indexmap]] -criteria = "safe-to-deploy" -user-id = 539 # Josh Stone (cuviper) -start = "2020-01-15" -end = "2027-03-14" - -[[trusted.itoa]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-05-02" -end = "2027-03-14" - -[[trusted.jobserver]] -criteria = "safe-to-deploy" -user-id = 55123 # rust-lang-owner -start = "2024-07-23" -end = "2027-03-14" - -[[trusted.js-sys]] -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2019-03-04" -end = "2027-03-14" - -[[trusted.libc]] -criteria = "safe-to-deploy" -user-id = 55123 # rust-lang-owner -start = "2024-08-15" -end = "2027-02-16" - -[[trusted.libm]] -criteria = "safe-to-deploy" -user-id = 55123 # rust-lang-owner -start = "2024-10-26" -end = "2027-03-14" - -[[trusted.linux-raw-sys]] -criteria = "safe-to-deploy" -user-id = 6825 # Dan Gohman (sunfishcode) -start = "2021-06-12" -end = "2027-03-14" - -[[trusted.lock_api]] -criteria = "safe-to-deploy" -user-id = 2915 # Amanieu d'Antras (Amanieu) -start = "2019-05-04" -end = "2027-03-14" - -[[trusted.log]] -criteria = "safe-to-deploy" -user-id = 3204 # Ashley Mannix (KodrAus) -start = "2019-07-10" -end = "2027-03-14" - -[[trusted.macro-string]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2025-02-02" -end = "2027-03-14" - -[[trusted.memchr]] -criteria = "safe-to-deploy" -user-id = 189 # Andrew Gallant (BurntSushi) -start = "2019-07-07" -end = "2027-03-14" - -[[trusted.mime]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2019-09-09" -end = "2027-03-14" - -[[trusted.mio]] -criteria = "safe-to-deploy" -user-id = 6025 # Thomas de Zeeuw (Thomasdezeeuw) -start = "2019-12-17" -end = "2027-03-14" - -[[trusted.num-bigint]] -criteria = "safe-to-deploy" -user-id = 539 # Josh Stone (cuviper) -start = "2019-09-04" -end = "2027-03-14" - -[[trusted.num_cpus]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2019-06-10" -end = "2027-03-14" - -[[trusted.object]] -criteria = "safe-to-deploy" -user-id = 4415 # Philip Craig (philipc) -start = "2019-04-26" -end = "2027-03-14" - -[[trusted.parking_lot]] -criteria = "safe-to-deploy" -user-id = 2915 # Amanieu d'Antras (Amanieu) -start = "2019-05-04" -end = "2027-03-14" - -[[trusted.parking_lot_core]] -criteria = "safe-to-deploy" -user-id = 2915 # Amanieu d'Antras (Amanieu) -start = "2019-05-04" -end = "2027-03-14" - -[[trusted.paste]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-03-19" -end = "2027-03-14" - -[[trusted.pin-project]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2019-03-02" -end = "2027-03-14" - -[[trusted.pin-project-internal]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2019-08-11" -end = "2027-03-14" - -[[trusted.pin-project-lite]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2019-10-22" -end = "2027-03-14" - -[[trusted.portable-atomic]] -criteria = "safe-to-deploy" -user-id = 33035 # Taiki Endo (taiki-e) -start = "2022-02-24" -end = "2027-03-14" - -[[trusted.prettyplease]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2022-01-04" -end = "2027-03-14" - -[[trusted.proc-macro2]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-04-23" -end = "2027-03-14" - -[[trusted.prost]] -criteria = "safe-to-deploy" -user-id = 3959 # Lucio Franco (LucioFranco) -start = "2021-07-08" -end = "2027-03-14" - -[[trusted.prost-build]] -criteria = "safe-to-deploy" -user-id = 3959 # Lucio Franco (LucioFranco) -start = "2021-07-08" -end = "2027-03-14" - -[[trusted.prost-derive]] -criteria = "safe-to-deploy" -user-id = 3959 # Lucio Franco (LucioFranco) -start = "2021-07-08" -end = "2027-03-14" - -[[trusted.prost-types]] -criteria = "safe-to-deploy" -user-id = 3959 # Lucio Franco (LucioFranco) -start = "2021-07-08" -end = "2027-03-14" - -[[trusted.protoc-bin-vendored-linux-aarch_64]] -criteria = "safe-to-deploy" -user-id = 220 # Stepan Koltsov (stepancheg) -start = "2022-02-07" -end = "2027-03-14" - -[[trusted.protoc-bin-vendored-linux-ppcle_64]] -criteria = "safe-to-deploy" -user-id = 220 # Stepan Koltsov (stepancheg) -start = "2022-02-07" -end = "2027-03-14" - -[[trusted.protoc-bin-vendored-linux-s390_64]] -criteria = "safe-to-deploy" -user-id = 220 # Stepan Koltsov (stepancheg) -start = "2025-07-21" -end = "2027-03-14" - -[[trusted.protoc-bin-vendored-linux-x86_32]] -criteria = "safe-to-deploy" -user-id = 220 # Stepan Koltsov (stepancheg) -start = "2022-02-07" -end = "2027-03-14" - -[[trusted.protoc-bin-vendored-linux-x86_64]] -criteria = "safe-to-deploy" -user-id = 220 # Stepan Koltsov (stepancheg) -start = "2022-02-07" -end = "2027-03-14" - -[[trusted.protoc-bin-vendored-macos-aarch_64]] -criteria = "safe-to-deploy" -user-id = 220 # Stepan Koltsov (stepancheg) -start = "2024-09-30" -end = "2027-03-14" - -[[trusted.protoc-bin-vendored-macos-x86_64]] -criteria = "safe-to-deploy" -user-id = 220 # Stepan Koltsov (stepancheg) -start = "2022-02-07" -end = "2027-03-14" - -[[trusted.protoc-bin-vendored-win32]] -criteria = "safe-to-deploy" -user-id = 220 # Stepan Koltsov (stepancheg) -start = "2022-02-07" -end = "2027-03-14" - -[[trusted.pulldown-cmark-to-cmark]] -criteria = "safe-to-deploy" -user-id = 980 # Sebastian Thiel (Byron) -start = "2019-07-03" -end = "2027-03-14" - -[[trusted.quote]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-04-09" -end = "2027-03-14" - -[[trusted.ref-cast]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-05-05" -end = "2027-03-14" - -[[trusted.ref-cast-impl]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-05-05" -end = "2027-03-14" - -[[trusted.regex]] -criteria = "safe-to-deploy" -user-id = 189 # Andrew Gallant (BurntSushi) -start = "2019-02-27" -end = "2027-03-14" - -[[trusted.regex-automata]] -criteria = "safe-to-deploy" -user-id = 189 # Andrew Gallant (BurntSushi) -start = "2019-02-25" -end = "2027-03-14" - -[[trusted.regex-syntax]] -criteria = "safe-to-deploy" -user-id = 189 # Andrew Gallant (BurntSushi) -start = "2019-03-30" -end = "2027-03-14" - -[[trusted.reqwest]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2019-03-04" -end = "2027-03-14" - -[[trusted.rustc-demangle]] -criteria = "safe-to-deploy" -user-id = 55123 # rust-lang-owner -start = "2023-03-23" -end = "2027-03-14" - -[[trusted.rustix]] -criteria = "safe-to-deploy" -user-id = 6825 # Dan Gohman (sunfishcode) -start = "2021-10-29" -end = "2027-02-14" - -[[trusted.ryu]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-05-02" -end = "2027-03-14" - -[[trusted.scopeguard]] -criteria = "safe-to-deploy" -user-id = 2915 # Amanieu d'Antras (Amanieu) -start = "2020-02-16" -end = "2027-03-14" - -[[trusted.semver]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2021-05-25" -end = "2027-03-14" - -[[trusted.serde_json]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-02-28" -end = "2027-02-14" - -[[trusted.slab]] -criteria = "safe-to-deploy" -user-id = 6741 # Alice Ryhl (Darksonn) -start = "2021-10-13" -end = "2027-03-14" - -[[trusted.socket2]] -criteria = "safe-to-deploy" -user-id = 6025 # Thomas de Zeeuw (Thomasdezeeuw) -start = "2020-09-09" -end = "2027-03-14" - -[[trusted.syn]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2019-03-01" -end = "2027-02-14" - -[[trusted.thread_local]] -criteria = "safe-to-deploy" -user-id = 2915 # Amanieu d'Antras (Amanieu) -start = "2019-09-07" -end = "2027-02-16" - -[[trusted.time]] -criteria = "safe-to-deploy" -user-id = 15682 # Jacob Pratt (jhpratt) -start = "2019-12-19" -end = "2027-03-14" - -[[trusted.tinystr]] -criteria = "safe-to-deploy" -user-id = 1139 # Manish Goregaokar (Manishearth) -start = "2021-01-14" -end = "2027-03-14" - -[[trusted.tokio]] -criteria = "safe-to-deploy" -user-id = 6741 # Alice Ryhl (Darksonn) -start = "2020-12-25" -end = "2027-03-14" - -[[trusted.tokio-macros]] -criteria = "safe-to-deploy" -user-id = 6741 # Alice Ryhl (Darksonn) -start = "2020-10-26" -end = "2027-03-14" - -[[trusted.tokio-stream]] -criteria = "safe-to-deploy" -user-id = 6741 # Alice Ryhl (Darksonn) -start = "2021-01-04" -end = "2027-03-14" - -[[trusted.tokio-util]] -criteria = "safe-to-deploy" -user-id = 6741 # Alice Ryhl (Darksonn) -start = "2021-01-12" -end = "2027-03-14" - -[[trusted.toml]] -criteria = "safe-to-deploy" -user-id = 6743 # Ed Page (epage) -start = "2022-12-14" -end = "2027-02-16" - -[[trusted.toml_datetime]] -criteria = "safe-to-deploy" -user-id = 6743 # Ed Page (epage) -start = "2022-10-21" -end = "2027-03-14" - -[[trusted.toml_edit]] -criteria = "safe-to-deploy" -user-id = 6743 # Ed Page (epage) -start = "2021-09-13" -end = "2027-03-14" - -[[trusted.toml_parser]] -criteria = "safe-to-deploy" -user-id = 6743 # Ed Page (epage) -start = "2025-07-08" -end = "2027-02-16" - -[[trusted.tonic]] -criteria = "safe-to-deploy" -user-id = 3959 # Lucio Franco (LucioFranco) -start = "2019-10-02" -end = "2027-03-14" - -[[trusted.tonic-build]] -criteria = "safe-to-deploy" -user-id = 10 # Carl Lerche (carllerche) -start = "2019-09-10" -end = "2027-03-14" - -[[trusted.tonic-build]] -criteria = "safe-to-deploy" -user-id = 3959 # Lucio Franco (LucioFranco) -start = "2019-10-02" -end = "2027-03-14" - -[[trusted.tonic-prost]] -criteria = "safe-to-deploy" -user-id = 3959 # Lucio Franco (LucioFranco) -start = "2025-07-28" -end = "2027-03-14" - -[[trusted.tonic-prost-build]] -criteria = "safe-to-deploy" -user-id = 3959 # Lucio Franco (LucioFranco) -start = "2025-07-28" -end = "2027-03-14" - -[[trusted.tower]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2024-09-09" -end = "2027-03-14" - -[[trusted.tower-http]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2024-09-23" -end = "2027-03-14" - -[[trusted.tower-layer]] -criteria = "safe-to-deploy" -user-id = 10 # Carl Lerche (carllerche) -start = "2019-04-27" -end = "2027-03-14" - -[[trusted.tower-layer]] -criteria = "safe-to-deploy" -user-id = 3959 # Lucio Franco (LucioFranco) -start = "2019-09-11" -end = "2027-03-14" - -[[trusted.tower-service]] -criteria = "safe-to-deploy" -user-id = 3959 # Lucio Franco (LucioFranco) -start = "2019-08-20" -end = "2027-03-14" - -[[trusted.tracing-subscriber]] -criteria = "safe-to-deploy" -user-id = 10 # Carl Lerche (carllerche) -start = "2025-08-29" -end = "2027-03-14" - -[[trusted.ucd-trie]] -criteria = "safe-to-deploy" -user-id = 189 # Andrew Gallant (BurntSushi) -start = "2019-07-21" -end = "2027-03-14" - -[[trusted.unicase]] -criteria = "safe-to-deploy" -user-id = 359 # Sean McArthur (seanmonstar) -start = "2019-03-05" -end = "2027-03-14" - -[[trusted.unicode-ident]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2021-10-02" -end = "2027-03-14" - -[[trusted.url]] -criteria = "safe-to-deploy" -user-id = 1139 # Manish Goregaokar (Manishearth) -start = "2021-02-18" -end = "2027-03-14" - -[[trusted.uuid]] -criteria = "safe-to-deploy" -user-id = 3204 # Ashley Mannix (KodrAus) -start = "2019-10-18" -end = "2027-03-14" - -[[trusted.valuable]] -criteria = "safe-to-deploy" -user-id = 10 # Carl Lerche (carllerche) -start = "2022-01-03" -end = "2027-03-14" - -[[trusted.wait-timeout]] -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2025-02-03" -end = "2027-03-14" - -[[trusted.wasi]] -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2020-06-03" -end = "2027-03-14" - -[[trusted.wasi]] -criteria = "safe-to-deploy" -user-id = 6825 # Dan Gohman (sunfishcode) -start = "2019-07-22" -end = "2027-03-14" - -[[trusted.wasm-bindgen]] -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2019-03-04" -end = "2027-03-14" - -[[trusted.wasm-bindgen-futures]] -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2019-03-04" -end = "2027-03-14" - -[[trusted.wasm-bindgen-macro]] -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2019-03-04" -end = "2027-03-14" - -[[trusted.wasm-bindgen-macro-support]] -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2019-03-04" -end = "2027-03-14" - -[[trusted.wasm-bindgen-shared]] -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2019-03-04" -end = "2027-03-14" - -[[trusted.web-sys]] -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2019-03-04" -end = "2027-03-14" - -[[trusted.windows-core]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2021-11-15" -end = "2027-03-14" - -[[trusted.windows-implement]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2022-01-27" -end = "2027-03-14" - -[[trusted.windows-interface]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2022-02-18" -end = "2027-03-14" - -[[trusted.windows-result]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2024-02-02" -end = "2027-03-14" - -[[trusted.windows-strings]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2024-02-02" -end = "2027-03-14" - -[[trusted.windows-sys]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2021-11-15" -end = "2027-02-16" - -[[trusted.windows-targets]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2022-09-09" -end = "2027-03-14" - -[[trusted.windows_aarch64_gnullvm]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2022-09-01" -end = "2027-03-14" - -[[trusted.windows_aarch64_msvc]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2021-11-05" -end = "2027-03-14" - -[[trusted.windows_i686_gnu]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2021-10-28" -end = "2027-03-14" - -[[trusted.windows_i686_gnullvm]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2024-04-02" -end = "2027-03-14" - -[[trusted.windows_i686_msvc]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2021-10-27" -end = "2027-03-14" - -[[trusted.windows_x86_64_gnu]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2021-10-28" -end = "2027-03-14" - -[[trusted.windows_x86_64_gnullvm]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2022-09-01" -end = "2027-03-14" - -[[trusted.windows_x86_64_msvc]] -criteria = "safe-to-deploy" -user-id = 64539 # Kenny Kerr (kennykerr) -start = "2021-10-27" -end = "2027-03-14" - -[[trusted.winnow]] -criteria = "safe-to-deploy" -user-id = 6743 # Ed Page (epage) -start = "2023-02-22" -end = "2027-03-14" - -[[trusted.yoke]] -criteria = "safe-to-deploy" -user-id = 1139 # Manish Goregaokar (Manishearth) -start = "2021-05-01" -end = "2027-03-14" - -[[trusted.zerocopy]] -criteria = "safe-to-deploy" -user-id = 7178 # Joshua Liebow-Feeser (joshlf) -start = "2019-02-28" -end = "2027-03-14" - -[[trusted.zerocopy-derive]] -criteria = "safe-to-deploy" -user-id = 7178 # Joshua Liebow-Feeser (joshlf) -start = "2019-02-28" -end = "2027-03-14" - -[[trusted.zerotrie]] -criteria = "safe-to-deploy" -user-id = 1139 # Manish Goregaokar (Manishearth) -start = "2023-10-03" -end = "2027-03-14" - -[[trusted.zerovec]] -criteria = "safe-to-deploy" -user-id = 1139 # Manish Goregaokar (Manishearth) -start = "2021-04-19" -end = "2027-03-14" - -[[trusted.zmij]] -criteria = "safe-to-deploy" -user-id = 3618 # David Tolnay (dtolnay) -start = "2025-12-18" -end = "2027-03-14" + +# cargo-vet audits file + +[[audits.alloy-primitives]] +who = "CleverWild " +criteria = "safe-to-deploy" +version = "1.5.7" + +[[audits.console]] +who = "CleverWild " +criteria = "safe-to-deploy" +version = "0.15.11" + +[[audits.encode_unicode]] +who = "CleverWild " +criteria = "safe-to-deploy" +version = "0.3.6" + +[[audits.futures-timer]] +who = "CleverWild " +criteria = "safe-to-run" +version = "3.0.3" + +[[audits.insta]] +who = "CleverWild " +criteria = "safe-to-run" +version = "1.46.3" + +[[audits.pin-project]] +who = "CleverWild " +criteria = "safe-to-deploy" +version = "0.2.16" + +[[audits.protoc-bin-vendored]] +who = "CleverWild " +criteria = "safe-to-deploy" +version = "3.2.0" + +[[audits.similar]] +who = "hdbg " +criteria = "safe-to-deploy" +version = "2.2.1" + +[[audits.test-log]] +who = "hdbg " +criteria = "safe-to-deploy" +delta = "0.2.18 -> 0.2.19" + +[[audits.test-log-macros]] +who = "hdbg " +criteria = "safe-to-deploy" +delta = "0.2.18 -> 0.2.19" + +[[audits.wasm-bindgen]] +who = "CleverWild " +criteria = "safe-to-deploy" +delta = "0.2.100 -> 0.2.114" + +[[trusted.addr2line]] +criteria = "safe-to-deploy" +user-id = 4415 # Philip Craig (philipc) +start = "2019-05-01" +end = "2027-03-14" + +[[trusted.aho-corasick]] +criteria = "safe-to-deploy" +user-id = 189 # Andrew Gallant (BurntSushi) +start = "2019-03-28" +end = "2027-03-14" + +[[trusted.anyhow]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-10-05" +end = "2027-03-14" + +[[trusted.async-stream]] +criteria = "safe-to-deploy" +user-id = 10 # Carl Lerche (carllerche) +start = "2019-06-07" +end = "2027-03-14" + +[[trusted.async-stream]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2021-04-21" +end = "2027-03-14" + +[[trusted.async-stream-impl]] +criteria = "safe-to-deploy" +user-id = 10 # Carl Lerche (carllerche) +start = "2019-08-13" +end = "2027-03-14" + +[[trusted.async-stream-impl]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2021-04-21" +end = "2027-03-14" + +[[trusted.async-trait]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-07-23" +end = "2027-03-14" + +[[trusted.auto_impl]] +criteria = "safe-to-deploy" +user-id = 3204 # Ashley Mannix (KodrAus) +start = "2022-06-01" +end = "2027-03-14" + +[[trusted.aws-lc-rs]] +criteria = "safe-to-deploy" +user-id = 156764 # Justin W Smith (justsmth) +start = "2023-04-11" +end = "2027-03-14" + +[[trusted.aws-lc-sys]] +criteria = "safe-to-deploy" +user-id = 156764 # Justin W Smith (justsmth) +start = "2022-11-09" +end = "2027-03-14" + +[[trusted.backtrace]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2025-05-06" +end = "2027-03-14" + +[[trusted.bitflags]] +criteria = "safe-to-deploy" +user-id = 3204 # Ashley Mannix (KodrAus) +start = "2019-05-02" +end = "2027-03-14" + +[[trusted.bytes]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2019-11-27" +end = "2027-03-14" + +[[trusted.bytes]] +criteria = "safe-to-deploy" +user-id = 6741 # Alice Ryhl (Darksonn) +start = "2021-01-11" +end = "2027-03-14" + +[[trusted.cc]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2022-10-29" +end = "2027-03-14" + +[[trusted.cmake]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2022-10-29" +end = "2027-03-14" + +[[trusted.crossbeam-utils]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-12" +end = "2027-03-14" + +[[trusted.derive_more]] +criteria = "safe-to-deploy" +user-id = 3797 # Jelte Fennema-Nio (JelteF) +start = "2019-05-25" +end = "2027-03-14" + +[[trusted.derive_more-impl]] +criteria = "safe-to-deploy" +user-id = 3797 # Jelte Fennema-Nio (JelteF) +start = "2023-07-23" +end = "2027-03-14" + +[[trusted.dyn-clone]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-12-23" +end = "2027-03-14" + +[[trusted.ff]] +criteria = "safe-to-deploy" +user-id = 6289 # Jack Grigg (str4d) +start = "2021-08-11" +end = "2027-03-14" + +[[trusted.find-msvc-tools]] +criteria = "safe-to-deploy" +user-id = 539 # Josh Stone (cuviper) +start = "2025-08-29" +end = "2027-03-14" + +[[trusted.flate2]] +criteria = "safe-to-deploy" +user-id = 980 # Sebastian Thiel (Byron) +start = "2023-08-15" +end = "2027-03-14" + +[[trusted.futures]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2027-03-14" + +[[trusted.futures-channel]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2027-03-14" + +[[trusted.futures-core]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2027-03-14" + +[[trusted.futures-executor]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2027-03-14" + +[[trusted.futures-io]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2027-03-14" + +[[trusted.futures-macro]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2027-03-14" + +[[trusted.futures-sink]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2027-03-14" + +[[trusted.futures-task]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2019-07-29" +end = "2027-03-14" + +[[trusted.futures-util]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2020-10-05" +end = "2027-03-14" + +[[trusted.group]] +criteria = "safe-to-deploy" +user-id = 1244 # ebfull +start = "2019-10-08" +end = "2027-03-14" + +[[trusted.h2]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2019-03-13" +end = "2027-02-14" + +[[trusted.hashbrown]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2019-04-02" +end = "2027-03-14" + +[[trusted.hashbrown]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2025-04-30" +end = "2027-02-14" + +[[trusted.http]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2019-04-05" +end = "2027-03-14" + +[[trusted.http-body-util]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2022-10-25" +end = "2027-03-14" + +[[trusted.httparse]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2019-07-03" +end = "2027-03-14" + +[[trusted.hyper]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2019-03-01" +end = "2027-03-14" + +[[trusted.hyper-util]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2022-01-15" +end = "2027-02-14" + +[[trusted.id-arena]] +criteria = "safe-to-deploy" +user-id = 696 # Nick Fitzgerald (fitzgen) +start = "2026-01-14" +end = "2027-03-14" + +[[trusted.indexmap]] +criteria = "safe-to-deploy" +user-id = 539 # Josh Stone (cuviper) +start = "2020-01-15" +end = "2027-03-14" + +[[trusted.itoa]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-05-02" +end = "2027-03-14" + +[[trusted.jobserver]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2024-07-23" +end = "2027-03-14" + +[[trusted.js-sys]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-03-04" +end = "2027-03-14" + +[[trusted.libc]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2024-08-15" +end = "2027-02-16" + +[[trusted.libm]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2024-10-26" +end = "2027-03-14" + +[[trusted.linux-raw-sys]] +criteria = "safe-to-deploy" +user-id = 6825 # Dan Gohman (sunfishcode) +start = "2021-06-12" +end = "2027-03-14" + +[[trusted.lock_api]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2019-05-04" +end = "2027-03-14" + +[[trusted.log]] +criteria = "safe-to-deploy" +user-id = 3204 # Ashley Mannix (KodrAus) +start = "2019-07-10" +end = "2027-03-14" + +[[trusted.macro-string]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2025-02-02" +end = "2027-03-14" + +[[trusted.memchr]] +criteria = "safe-to-deploy" +user-id = 189 # Andrew Gallant (BurntSushi) +start = "2019-07-07" +end = "2027-03-14" + +[[trusted.mime]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2019-09-09" +end = "2027-03-14" + +[[trusted.mio]] +criteria = "safe-to-deploy" +user-id = 6025 # Thomas de Zeeuw (Thomasdezeeuw) +start = "2019-12-17" +end = "2027-03-14" + +[[trusted.num-bigint]] +criteria = "safe-to-deploy" +user-id = 539 # Josh Stone (cuviper) +start = "2019-09-04" +end = "2027-03-14" + +[[trusted.num_cpus]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2019-06-10" +end = "2027-03-14" + +[[trusted.object]] +criteria = "safe-to-deploy" +user-id = 4415 # Philip Craig (philipc) +start = "2019-04-26" +end = "2027-03-14" + +[[trusted.parking_lot]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2019-05-04" +end = "2027-03-14" + +[[trusted.parking_lot_core]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2019-05-04" +end = "2027-03-14" + +[[trusted.paste]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-03-19" +end = "2027-03-14" + +[[trusted.pin-project]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2019-03-02" +end = "2027-03-14" + +[[trusted.pin-project-internal]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2019-08-11" +end = "2027-03-14" + +[[trusted.pin-project-lite]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2019-10-22" +end = "2027-03-14" + +[[trusted.portable-atomic]] +criteria = "safe-to-deploy" +user-id = 33035 # Taiki Endo (taiki-e) +start = "2022-02-24" +end = "2027-03-14" + +[[trusted.prettyplease]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2022-01-04" +end = "2027-03-14" + +[[trusted.proc-macro2]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-04-23" +end = "2027-03-14" + +[[trusted.prost]] +criteria = "safe-to-deploy" +user-id = 3959 # Lucio Franco (LucioFranco) +start = "2021-07-08" +end = "2027-03-14" + +[[trusted.prost-build]] +criteria = "safe-to-deploy" +user-id = 3959 # Lucio Franco (LucioFranco) +start = "2021-07-08" +end = "2027-03-14" + +[[trusted.prost-derive]] +criteria = "safe-to-deploy" +user-id = 3959 # Lucio Franco (LucioFranco) +start = "2021-07-08" +end = "2027-03-14" + +[[trusted.prost-types]] +criteria = "safe-to-deploy" +user-id = 3959 # Lucio Franco (LucioFranco) +start = "2021-07-08" +end = "2027-03-14" + +[[trusted.protoc-bin-vendored-linux-aarch_64]] +criteria = "safe-to-deploy" +user-id = 220 # Stepan Koltsov (stepancheg) +start = "2022-02-07" +end = "2027-03-14" + +[[trusted.protoc-bin-vendored-linux-ppcle_64]] +criteria = "safe-to-deploy" +user-id = 220 # Stepan Koltsov (stepancheg) +start = "2022-02-07" +end = "2027-03-14" + +[[trusted.protoc-bin-vendored-linux-s390_64]] +criteria = "safe-to-deploy" +user-id = 220 # Stepan Koltsov (stepancheg) +start = "2025-07-21" +end = "2027-03-14" + +[[trusted.protoc-bin-vendored-linux-x86_32]] +criteria = "safe-to-deploy" +user-id = 220 # Stepan Koltsov (stepancheg) +start = "2022-02-07" +end = "2027-03-14" + +[[trusted.protoc-bin-vendored-linux-x86_64]] +criteria = "safe-to-deploy" +user-id = 220 # Stepan Koltsov (stepancheg) +start = "2022-02-07" +end = "2027-03-14" + +[[trusted.protoc-bin-vendored-macos-aarch_64]] +criteria = "safe-to-deploy" +user-id = 220 # Stepan Koltsov (stepancheg) +start = "2024-09-30" +end = "2027-03-14" + +[[trusted.protoc-bin-vendored-macos-x86_64]] +criteria = "safe-to-deploy" +user-id = 220 # Stepan Koltsov (stepancheg) +start = "2022-02-07" +end = "2027-03-14" + +[[trusted.protoc-bin-vendored-win32]] +criteria = "safe-to-deploy" +user-id = 220 # Stepan Koltsov (stepancheg) +start = "2022-02-07" +end = "2027-03-14" + +[[trusted.pulldown-cmark-to-cmark]] +criteria = "safe-to-deploy" +user-id = 980 # Sebastian Thiel (Byron) +start = "2019-07-03" +end = "2027-03-14" + +[[trusted.quote]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-04-09" +end = "2027-03-14" + +[[trusted.ref-cast]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-05-05" +end = "2027-03-14" + +[[trusted.ref-cast-impl]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-05-05" +end = "2027-03-14" + +[[trusted.regex]] +criteria = "safe-to-deploy" +user-id = 189 # Andrew Gallant (BurntSushi) +start = "2019-02-27" +end = "2027-03-14" + +[[trusted.regex-automata]] +criteria = "safe-to-deploy" +user-id = 189 # Andrew Gallant (BurntSushi) +start = "2019-02-25" +end = "2027-03-14" + +[[trusted.regex-syntax]] +criteria = "safe-to-deploy" +user-id = 189 # Andrew Gallant (BurntSushi) +start = "2019-03-30" +end = "2027-03-14" + +[[trusted.reqwest]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2019-03-04" +end = "2027-03-14" + +[[trusted.rustc-demangle]] +criteria = "safe-to-deploy" +user-id = 55123 # rust-lang-owner +start = "2023-03-23" +end = "2027-03-14" + +[[trusted.rustix]] +criteria = "safe-to-deploy" +user-id = 6825 # Dan Gohman (sunfishcode) +start = "2021-10-29" +end = "2027-02-14" + +[[trusted.ryu]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-05-02" +end = "2027-03-14" + +[[trusted.scopeguard]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2020-02-16" +end = "2027-03-14" + +[[trusted.semver]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2021-05-25" +end = "2027-03-14" + +[[trusted.serde_json]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-02-28" +end = "2027-02-14" + +[[trusted.slab]] +criteria = "safe-to-deploy" +user-id = 6741 # Alice Ryhl (Darksonn) +start = "2021-10-13" +end = "2027-03-14" + +[[trusted.socket2]] +criteria = "safe-to-deploy" +user-id = 6025 # Thomas de Zeeuw (Thomasdezeeuw) +start = "2020-09-09" +end = "2027-03-14" + +[[trusted.syn]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2019-03-01" +end = "2027-02-14" + +[[trusted.thread_local]] +criteria = "safe-to-deploy" +user-id = 2915 # Amanieu d'Antras (Amanieu) +start = "2019-09-07" +end = "2027-02-16" + +[[trusted.time]] +criteria = "safe-to-deploy" +user-id = 15682 # Jacob Pratt (jhpratt) +start = "2019-12-19" +end = "2027-03-14" + +[[trusted.tinystr]] +criteria = "safe-to-deploy" +user-id = 1139 # Manish Goregaokar (Manishearth) +start = "2021-01-14" +end = "2027-03-14" + +[[trusted.tokio]] +criteria = "safe-to-deploy" +user-id = 6741 # Alice Ryhl (Darksonn) +start = "2020-12-25" +end = "2027-03-14" + +[[trusted.tokio-macros]] +criteria = "safe-to-deploy" +user-id = 6741 # Alice Ryhl (Darksonn) +start = "2020-10-26" +end = "2027-03-14" + +[[trusted.tokio-stream]] +criteria = "safe-to-deploy" +user-id = 6741 # Alice Ryhl (Darksonn) +start = "2021-01-04" +end = "2027-03-14" + +[[trusted.tokio-util]] +criteria = "safe-to-deploy" +user-id = 6741 # Alice Ryhl (Darksonn) +start = "2021-01-12" +end = "2027-03-14" + +[[trusted.toml]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2022-12-14" +end = "2027-02-16" + +[[trusted.toml_datetime]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2022-10-21" +end = "2027-03-14" + +[[trusted.toml_edit]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2021-09-13" +end = "2027-03-14" + +[[trusted.toml_parser]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2025-07-08" +end = "2027-02-16" + +[[trusted.tonic]] +criteria = "safe-to-deploy" +user-id = 3959 # Lucio Franco (LucioFranco) +start = "2019-10-02" +end = "2027-03-14" + +[[trusted.tonic-build]] +criteria = "safe-to-deploy" +user-id = 10 # Carl Lerche (carllerche) +start = "2019-09-10" +end = "2027-03-14" + +[[trusted.tonic-build]] +criteria = "safe-to-deploy" +user-id = 3959 # Lucio Franco (LucioFranco) +start = "2019-10-02" +end = "2027-03-14" + +[[trusted.tonic-prost]] +criteria = "safe-to-deploy" +user-id = 3959 # Lucio Franco (LucioFranco) +start = "2025-07-28" +end = "2027-03-14" + +[[trusted.tonic-prost-build]] +criteria = "safe-to-deploy" +user-id = 3959 # Lucio Franco (LucioFranco) +start = "2025-07-28" +end = "2027-03-14" + +[[trusted.tower]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2024-09-09" +end = "2027-03-14" + +[[trusted.tower-http]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2024-09-23" +end = "2027-03-14" + +[[trusted.tower-layer]] +criteria = "safe-to-deploy" +user-id = 10 # Carl Lerche (carllerche) +start = "2019-04-27" +end = "2027-03-14" + +[[trusted.tower-layer]] +criteria = "safe-to-deploy" +user-id = 3959 # Lucio Franco (LucioFranco) +start = "2019-09-11" +end = "2027-03-14" + +[[trusted.tower-service]] +criteria = "safe-to-deploy" +user-id = 3959 # Lucio Franco (LucioFranco) +start = "2019-08-20" +end = "2027-03-14" + +[[trusted.tracing-subscriber]] +criteria = "safe-to-deploy" +user-id = 10 # Carl Lerche (carllerche) +start = "2025-08-29" +end = "2027-03-14" + +[[trusted.ucd-trie]] +criteria = "safe-to-deploy" +user-id = 189 # Andrew Gallant (BurntSushi) +start = "2019-07-21" +end = "2027-03-14" + +[[trusted.unicase]] +criteria = "safe-to-deploy" +user-id = 359 # Sean McArthur (seanmonstar) +start = "2019-03-05" +end = "2027-03-14" + +[[trusted.unicode-ident]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2021-10-02" +end = "2027-03-14" + +[[trusted.url]] +criteria = "safe-to-deploy" +user-id = 1139 # Manish Goregaokar (Manishearth) +start = "2021-02-18" +end = "2027-03-14" + +[[trusted.uuid]] +criteria = "safe-to-deploy" +user-id = 3204 # Ashley Mannix (KodrAus) +start = "2019-10-18" +end = "2027-03-14" + +[[trusted.valuable]] +criteria = "safe-to-deploy" +user-id = 10 # Carl Lerche (carllerche) +start = "2022-01-03" +end = "2027-03-14" + +[[trusted.wait-timeout]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2025-02-03" +end = "2027-03-14" + +[[trusted.wasi]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2020-06-03" +end = "2027-03-14" + +[[trusted.wasi]] +criteria = "safe-to-deploy" +user-id = 6825 # Dan Gohman (sunfishcode) +start = "2019-07-22" +end = "2027-03-14" + +[[trusted.wasm-bindgen]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-03-04" +end = "2027-03-14" + +[[trusted.wasm-bindgen-futures]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-03-04" +end = "2027-03-14" + +[[trusted.wasm-bindgen-macro]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-03-04" +end = "2027-03-14" + +[[trusted.wasm-bindgen-macro-support]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-03-04" +end = "2027-03-14" + +[[trusted.wasm-bindgen-shared]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-03-04" +end = "2027-03-14" + +[[trusted.web-sys]] +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2019-03-04" +end = "2027-03-14" + +[[trusted.windows-core]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2021-11-15" +end = "2027-03-14" + +[[trusted.windows-implement]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2022-01-27" +end = "2027-03-14" + +[[trusted.windows-interface]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2022-02-18" +end = "2027-03-14" + +[[trusted.windows-result]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2024-02-02" +end = "2027-03-14" + +[[trusted.windows-strings]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2024-02-02" +end = "2027-03-14" + +[[trusted.windows-sys]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2021-11-15" +end = "2027-02-16" + +[[trusted.windows-targets]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2022-09-09" +end = "2027-03-14" + +[[trusted.windows_aarch64_gnullvm]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2022-09-01" +end = "2027-03-14" + +[[trusted.windows_aarch64_msvc]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2021-11-05" +end = "2027-03-14" + +[[trusted.windows_i686_gnu]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2021-10-28" +end = "2027-03-14" + +[[trusted.windows_i686_gnullvm]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2024-04-02" +end = "2027-03-14" + +[[trusted.windows_i686_msvc]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2021-10-27" +end = "2027-03-14" + +[[trusted.windows_x86_64_gnu]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2021-10-28" +end = "2027-03-14" + +[[trusted.windows_x86_64_gnullvm]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2022-09-01" +end = "2027-03-14" + +[[trusted.windows_x86_64_msvc]] +criteria = "safe-to-deploy" +user-id = 64539 # Kenny Kerr (kennykerr) +start = "2021-10-27" +end = "2027-03-14" + +[[trusted.winnow]] +criteria = "safe-to-deploy" +user-id = 6743 # Ed Page (epage) +start = "2023-02-22" +end = "2027-03-14" + +[[trusted.yoke]] +criteria = "safe-to-deploy" +user-id = 1139 # Manish Goregaokar (Manishearth) +start = "2021-05-01" +end = "2027-03-14" + +[[trusted.zerocopy]] +criteria = "safe-to-deploy" +user-id = 7178 # Joshua Liebow-Feeser (joshlf) +start = "2019-02-28" +end = "2027-03-14" + +[[trusted.zerocopy-derive]] +criteria = "safe-to-deploy" +user-id = 7178 # Joshua Liebow-Feeser (joshlf) +start = "2019-02-28" +end = "2027-03-14" + +[[trusted.zerotrie]] +criteria = "safe-to-deploy" +user-id = 1139 # Manish Goregaokar (Manishearth) +start = "2023-10-03" +end = "2027-03-14" + +[[trusted.zerovec]] +criteria = "safe-to-deploy" +user-id = 1139 # Manish Goregaokar (Manishearth) +start = "2021-04-19" +end = "2027-03-14" + +[[trusted.zmij]] +criteria = "safe-to-deploy" +user-id = 3618 # David Tolnay (dtolnay) +start = "2025-12-18" +end = "2027-03-14" diff --git a/server/supply-chain/config.toml b/server/supply-chain/config.toml index 11f22ff..9b9fa95 100644 --- a/server/supply-chain/config.toml +++ b/server/supply-chain/config.toml @@ -1,454 +1,454 @@ - -# cargo-vet config file - -[cargo-vet] -version = "0.10" - -[imports.OpenDevicePartnership] -url = "https://raw.githubusercontent.com/OpenDevicePartnership/rust-crate-audits/refs/heads/main/audits.toml" - -[imports.bytecode-alliance] -url = "https://raw.githubusercontent.com/bytecodealliance/wasmtime/main/supply-chain/audits.toml" - -[imports.embark-studios] -url = "https://raw.githubusercontent.com/EmbarkStudios/rust-ecosystem/main/audits.toml" - -[imports.google] -url = "https://raw.githubusercontent.com/google/supply-chain/main/audits.toml" - -[imports.isrg] -url = "https://raw.githubusercontent.com/divviup/libprio-rs/main/supply-chain/audits.toml" - -[imports.mozilla] -url = "https://raw.githubusercontent.com/mozilla/supply-chain/main/audits.toml" - -[imports.zcash] -url = "https://raw.githubusercontent.com/zcash/rust-ecosystem/main/supply-chain/audits.toml" - -[[exemptions.asn1-rs]] -version = "0.7.1" -criteria = "safe-to-deploy" - -[[exemptions.asn1-rs-derive]] -version = "0.6.0" -criteria = "safe-to-deploy" - -[[exemptions.asn1-rs-impl]] -version = "0.2.0" -criteria = "safe-to-deploy" - -[[exemptions.axum]] -version = "0.8.8" -criteria = "safe-to-deploy" - -[[exemptions.axum-core]] -version = "0.5.6" -criteria = "safe-to-deploy" - -[[exemptions.backtrace-ext]] -version = "0.2.1" -criteria = "safe-to-deploy" - -[[exemptions.bb8]] -version = "0.9.1" -criteria = "safe-to-deploy" - -[[exemptions.block-buffer]] -version = "0.11.0" -criteria = "safe-to-deploy" - -[[exemptions.cc]] -version = "1.2.55" -criteria = "safe-to-deploy" - -[[exemptions.chacha20]] -version = "0.10.0" -criteria = "safe-to-deploy" - -[[exemptions.chrono]] -version = "0.4.43" -criteria = "safe-to-deploy" - -[[exemptions.cpufeatures]] -version = "0.2.17" -criteria = "safe-to-deploy" - -[[exemptions.crc32fast]] -version = "1.5.0" -criteria = "safe-to-deploy" - -[[exemptions.crypto-common]] -version = "0.2.0" -criteria = "safe-to-deploy" - -[[exemptions.curve25519-dalek]] -version = "5.0.0-pre.6" -criteria = "safe-to-deploy" - -[[exemptions.curve25519-dalek-derive]] -version = "0.1.1" -criteria = "safe-to-deploy" - -[[exemptions.darling]] -version = "0.21.3" -criteria = "safe-to-deploy" - -[[exemptions.darling_core]] -version = "0.21.3" -criteria = "safe-to-deploy" - -[[exemptions.darling_macro]] -version = "0.21.3" -criteria = "safe-to-deploy" - -[[exemptions.dashmap]] -version = "6.1.0" -criteria = "safe-to-deploy" - -[[exemptions.data-encoding]] -version = "2.10.0" -criteria = "safe-to-deploy" - -[[exemptions.der-parser]] -version = "10.0.0" -criteria = "safe-to-deploy" - -[[exemptions.diesel]] -version = "2.3.6" -criteria = "safe-to-deploy" - -[[exemptions.diesel-async]] -version = "0.7.4" -criteria = "safe-to-deploy" - -[[exemptions.diesel_derives]] -version = "2.3.7" -criteria = "safe-to-deploy" - -[[exemptions.diesel_migrations]] -version = "2.3.1" -criteria = "safe-to-deploy" - -[[exemptions.diesel_table_macro_syntax]] -version = "0.3.0" -criteria = "safe-to-deploy" - -[[exemptions.digest]] -version = "0.11.0-rc.11" -criteria = "safe-to-deploy" - -[[exemptions.downcast-rs]] -version = "2.0.2" -criteria = "safe-to-deploy" - -[[exemptions.dsl_auto_type]] -version = "0.2.0" -criteria = "safe-to-deploy" - -[[exemptions.ed25519]] -version = "3.0.0-rc.4" -criteria = "safe-to-deploy" - -[[exemptions.ed25519-dalek]] -version = "3.0.0-pre.6" -criteria = "safe-to-deploy" - -[[exemptions.find-msvc-tools]] -version = "0.1.9" -criteria = "safe-to-deploy" - -[[exemptions.fixedbitset]] -version = "0.5.7" -criteria = "safe-to-deploy" - -[[exemptions.fs_extra]] -version = "1.3.0" -criteria = "safe-to-deploy" - -[[exemptions.getrandom]] -version = "0.2.17" -criteria = "safe-to-deploy" - -[[exemptions.getrandom]] -version = "0.3.4" -criteria = "safe-to-deploy" - -[[exemptions.getrandom]] -version = "0.4.1" -criteria = "safe-to-deploy" - -[[exemptions.hybrid-array]] -version = "0.4.7" -criteria = "safe-to-deploy" - -[[exemptions.hyper-timeout]] -version = "0.5.2" -criteria = "safe-to-deploy" - -[[exemptions.iana-time-zone]] -version = "0.1.65" -criteria = "safe-to-deploy" - -[[exemptions.is_ci]] -version = "1.2.0" -criteria = "safe-to-deploy" - -[[exemptions.itertools]] -version = "0.14.0" -criteria = "safe-to-deploy" - -[[exemptions.js-sys]] -version = "0.3.85" -criteria = "safe-to-deploy" - -[[exemptions.kameo]] -version = "0.19.2" -criteria = "safe-to-deploy" - -[[exemptions.kameo_macros]] -version = "0.19.0" -criteria = "safe-to-deploy" - -[[exemptions.libsqlite3-sys]] -version = "0.35.0" -criteria = "safe-to-deploy" - -[[exemptions.matchit]] -version = "0.8.4" -criteria = "safe-to-deploy" - -[[exemptions.memsafe]] -version = "0.4.0" -criteria = "safe-to-deploy" - -[[exemptions.miette]] -version = "7.6.0" -criteria = "safe-to-deploy" - -[[exemptions.miette-derive]] -version = "7.6.0" -criteria = "safe-to-deploy" - -[[exemptions.migrations_internals]] -version = "2.3.0" -criteria = "safe-to-deploy" - -[[exemptions.migrations_macros]] -version = "2.3.0" -criteria = "safe-to-deploy" - -[[exemptions.minimal-lexical]] -version = "0.2.1" -criteria = "safe-to-deploy" - -[[exemptions.multimap]] -version = "0.10.1" -criteria = "safe-to-deploy" - -[[exemptions.oid-registry]] -version = "0.8.1" -criteria = "safe-to-deploy" - -[[exemptions.once_cell]] -version = "1.21.3" -criteria = "safe-to-deploy" - -[[exemptions.owo-colors]] -version = "4.2.3" -criteria = "safe-to-deploy" - -[[exemptions.pem]] -version = "3.0.6" -criteria = "safe-to-deploy" - -[[exemptions.petgraph]] -version = "0.8.3" -criteria = "safe-to-deploy" - -[[exemptions.pin-project]] -version = "1.1.10" -criteria = "safe-to-deploy" - -[[exemptions.pin-project-internal]] -version = "1.1.10" -criteria = "safe-to-deploy" - -[[exemptions.pulldown-cmark]] -version = "0.13.0" -criteria = "safe-to-deploy" - -[[exemptions.r-efi]] -version = "5.3.0" -criteria = "safe-to-deploy" - -[[exemptions.rcgen]] -version = "0.14.7" -criteria = "safe-to-deploy" - -[[exemptions.redox_syscall]] -version = "0.5.18" -criteria = "safe-to-deploy" - -[[exemptions.ring]] -version = "0.17.14" -criteria = "safe-to-deploy" - -[[exemptions.rsqlite-vfs]] -version = "0.1.0" -criteria = "safe-to-deploy" - -[[exemptions.rusticata-macros]] -version = "4.1.0" -criteria = "safe-to-deploy" - -[[exemptions.rustls]] -version = "0.23.36" -criteria = "safe-to-deploy" - -[[exemptions.rustls-pki-types]] -version = "1.14.0" -criteria = "safe-to-deploy" - -[[exemptions.rustls-webpki]] -version = "0.103.9" -criteria = "safe-to-deploy" - -[[exemptions.scoped-futures]] -version = "0.1.4" -criteria = "safe-to-deploy" - -[[exemptions.secrecy]] -version = "0.10.3" -criteria = "safe-to-deploy" - -[[exemptions.semver]] -version = "1.0.27" -criteria = "safe-to-deploy" - -[[exemptions.sha2]] -version = "0.11.0-rc.5" -criteria = "safe-to-deploy" - -[[exemptions.signal-hook-registry]] -version = "1.4.8" -criteria = "safe-to-deploy" - -[[exemptions.signature]] -version = "3.0.0-rc.10" -criteria = "safe-to-deploy" - -[[exemptions.simd-adler32]] -version = "0.3.8" -criteria = "safe-to-deploy" - -[[exemptions.smlang]] -version = "0.8.0" -criteria = "safe-to-deploy" - -[[exemptions.smlang-macros]] -version = "0.8.0" -criteria = "safe-to-deploy" - -[[exemptions.sqlite-wasm-rs]] -version = "0.5.2" -criteria = "safe-to-deploy" - -[[exemptions.string_morph]] -version = "0.1.0" -criteria = "safe-to-deploy" - -[[exemptions.supports-color]] -version = "3.0.2" -criteria = "safe-to-deploy" - -[[exemptions.supports-hyperlinks]] -version = "3.2.0" -criteria = "safe-to-deploy" - -[[exemptions.supports-unicode]] -version = "3.0.0" -criteria = "safe-to-deploy" - -[[exemptions.sync_wrapper]] -version = "1.0.2" -criteria = "safe-to-deploy" - -[[exemptions.tempfile]] -version = "3.25.0" -criteria = "safe-to-deploy" - -[[exemptions.terminal_size]] -version = "0.4.3" -criteria = "safe-to-deploy" - -[[exemptions.tokio-rustls]] -version = "0.26.4" -criteria = "safe-to-deploy" - -[[exemptions.tracing]] -version = "0.1.44" -criteria = "safe-to-deploy" - -[[exemptions.tracing-attributes]] -version = "0.1.31" -criteria = "safe-to-deploy" - -[[exemptions.tracing-core]] -version = "0.1.36" -criteria = "safe-to-deploy" - -[[exemptions.tracing-subscriber]] -version = "0.3.22" -criteria = "safe-to-run" - -[[exemptions.typenum]] -version = "1.19.0" -criteria = "safe-to-deploy" - -[[exemptions.untrusted]] -version = "0.9.0" -criteria = "safe-to-deploy" - -[[exemptions.wasm-bindgen-macro]] -version = "0.2.108" -criteria = "safe-to-deploy" - -[[exemptions.wasm-bindgen-macro-support]] -version = "0.2.108" -criteria = "safe-to-deploy" - -[[exemptions.wasm-bindgen-shared]] -version = "0.2.108" -criteria = "safe-to-deploy" - -[[exemptions.winapi]] -version = "0.3.9" -criteria = "safe-to-deploy" - -[[exemptions.winapi-i686-pc-windows-gnu]] -version = "0.4.0" -criteria = "safe-to-deploy" - -[[exemptions.winapi-x86_64-pc-windows-gnu]] -version = "0.4.0" -criteria = "safe-to-deploy" - -[[exemptions.x509-parser]] -version = "0.18.1" -criteria = "safe-to-deploy" - -[[exemptions.yasna]] -version = "0.5.2" -criteria = "safe-to-deploy" - -[[exemptions.zstd]] -version = "0.13.3" -criteria = "safe-to-deploy" - -[[exemptions.zstd-safe]] -version = "7.2.4" -criteria = "safe-to-deploy" - -[[exemptions.zstd-sys]] -version = "2.0.16+zstd.1.5.7" -criteria = "safe-to-deploy" + +# cargo-vet config file + +[cargo-vet] +version = "0.10" + +[imports.OpenDevicePartnership] +url = "https://raw.githubusercontent.com/OpenDevicePartnership/rust-crate-audits/refs/heads/main/audits.toml" + +[imports.bytecode-alliance] +url = "https://raw.githubusercontent.com/bytecodealliance/wasmtime/main/supply-chain/audits.toml" + +[imports.embark-studios] +url = "https://raw.githubusercontent.com/EmbarkStudios/rust-ecosystem/main/audits.toml" + +[imports.google] +url = "https://raw.githubusercontent.com/google/supply-chain/main/audits.toml" + +[imports.isrg] +url = "https://raw.githubusercontent.com/divviup/libprio-rs/main/supply-chain/audits.toml" + +[imports.mozilla] +url = "https://raw.githubusercontent.com/mozilla/supply-chain/main/audits.toml" + +[imports.zcash] +url = "https://raw.githubusercontent.com/zcash/rust-ecosystem/main/supply-chain/audits.toml" + +[[exemptions.asn1-rs]] +version = "0.7.1" +criteria = "safe-to-deploy" + +[[exemptions.asn1-rs-derive]] +version = "0.6.0" +criteria = "safe-to-deploy" + +[[exemptions.asn1-rs-impl]] +version = "0.2.0" +criteria = "safe-to-deploy" + +[[exemptions.axum]] +version = "0.8.8" +criteria = "safe-to-deploy" + +[[exemptions.axum-core]] +version = "0.5.6" +criteria = "safe-to-deploy" + +[[exemptions.backtrace-ext]] +version = "0.2.1" +criteria = "safe-to-deploy" + +[[exemptions.bb8]] +version = "0.9.1" +criteria = "safe-to-deploy" + +[[exemptions.block-buffer]] +version = "0.11.0" +criteria = "safe-to-deploy" + +[[exemptions.cc]] +version = "1.2.55" +criteria = "safe-to-deploy" + +[[exemptions.chacha20]] +version = "0.10.0" +criteria = "safe-to-deploy" + +[[exemptions.chrono]] +version = "0.4.43" +criteria = "safe-to-deploy" + +[[exemptions.cpufeatures]] +version = "0.2.17" +criteria = "safe-to-deploy" + +[[exemptions.crc32fast]] +version = "1.5.0" +criteria = "safe-to-deploy" + +[[exemptions.crypto-common]] +version = "0.2.0" +criteria = "safe-to-deploy" + +[[exemptions.curve25519-dalek]] +version = "5.0.0-pre.6" +criteria = "safe-to-deploy" + +[[exemptions.curve25519-dalek-derive]] +version = "0.1.1" +criteria = "safe-to-deploy" + +[[exemptions.darling]] +version = "0.21.3" +criteria = "safe-to-deploy" + +[[exemptions.darling_core]] +version = "0.21.3" +criteria = "safe-to-deploy" + +[[exemptions.darling_macro]] +version = "0.21.3" +criteria = "safe-to-deploy" + +[[exemptions.dashmap]] +version = "6.1.0" +criteria = "safe-to-deploy" + +[[exemptions.data-encoding]] +version = "2.10.0" +criteria = "safe-to-deploy" + +[[exemptions.der-parser]] +version = "10.0.0" +criteria = "safe-to-deploy" + +[[exemptions.diesel]] +version = "2.3.6" +criteria = "safe-to-deploy" + +[[exemptions.diesel-async]] +version = "0.7.4" +criteria = "safe-to-deploy" + +[[exemptions.diesel_derives]] +version = "2.3.7" +criteria = "safe-to-deploy" + +[[exemptions.diesel_migrations]] +version = "2.3.1" +criteria = "safe-to-deploy" + +[[exemptions.diesel_table_macro_syntax]] +version = "0.3.0" +criteria = "safe-to-deploy" + +[[exemptions.digest]] +version = "0.11.0-rc.11" +criteria = "safe-to-deploy" + +[[exemptions.downcast-rs]] +version = "2.0.2" +criteria = "safe-to-deploy" + +[[exemptions.dsl_auto_type]] +version = "0.2.0" +criteria = "safe-to-deploy" + +[[exemptions.ed25519]] +version = "3.0.0-rc.4" +criteria = "safe-to-deploy" + +[[exemptions.ed25519-dalek]] +version = "3.0.0-pre.6" +criteria = "safe-to-deploy" + +[[exemptions.find-msvc-tools]] +version = "0.1.9" +criteria = "safe-to-deploy" + +[[exemptions.fixedbitset]] +version = "0.5.7" +criteria = "safe-to-deploy" + +[[exemptions.fs_extra]] +version = "1.3.0" +criteria = "safe-to-deploy" + +[[exemptions.getrandom]] +version = "0.2.17" +criteria = "safe-to-deploy" + +[[exemptions.getrandom]] +version = "0.3.4" +criteria = "safe-to-deploy" + +[[exemptions.getrandom]] +version = "0.4.1" +criteria = "safe-to-deploy" + +[[exemptions.hybrid-array]] +version = "0.4.7" +criteria = "safe-to-deploy" + +[[exemptions.hyper-timeout]] +version = "0.5.2" +criteria = "safe-to-deploy" + +[[exemptions.iana-time-zone]] +version = "0.1.65" +criteria = "safe-to-deploy" + +[[exemptions.is_ci]] +version = "1.2.0" +criteria = "safe-to-deploy" + +[[exemptions.itertools]] +version = "0.14.0" +criteria = "safe-to-deploy" + +[[exemptions.js-sys]] +version = "0.3.85" +criteria = "safe-to-deploy" + +[[exemptions.kameo]] +version = "0.19.2" +criteria = "safe-to-deploy" + +[[exemptions.kameo_macros]] +version = "0.19.0" +criteria = "safe-to-deploy" + +[[exemptions.libsqlite3-sys]] +version = "0.35.0" +criteria = "safe-to-deploy" + +[[exemptions.matchit]] +version = "0.8.4" +criteria = "safe-to-deploy" + +[[exemptions.memsafe]] +version = "0.4.0" +criteria = "safe-to-deploy" + +[[exemptions.miette]] +version = "7.6.0" +criteria = "safe-to-deploy" + +[[exemptions.miette-derive]] +version = "7.6.0" +criteria = "safe-to-deploy" + +[[exemptions.migrations_internals]] +version = "2.3.0" +criteria = "safe-to-deploy" + +[[exemptions.migrations_macros]] +version = "2.3.0" +criteria = "safe-to-deploy" + +[[exemptions.minimal-lexical]] +version = "0.2.1" +criteria = "safe-to-deploy" + +[[exemptions.multimap]] +version = "0.10.1" +criteria = "safe-to-deploy" + +[[exemptions.oid-registry]] +version = "0.8.1" +criteria = "safe-to-deploy" + +[[exemptions.once_cell]] +version = "1.21.3" +criteria = "safe-to-deploy" + +[[exemptions.owo-colors]] +version = "4.2.3" +criteria = "safe-to-deploy" + +[[exemptions.pem]] +version = "3.0.6" +criteria = "safe-to-deploy" + +[[exemptions.petgraph]] +version = "0.8.3" +criteria = "safe-to-deploy" + +[[exemptions.pin-project]] +version = "1.1.10" +criteria = "safe-to-deploy" + +[[exemptions.pin-project-internal]] +version = "1.1.10" +criteria = "safe-to-deploy" + +[[exemptions.pulldown-cmark]] +version = "0.13.0" +criteria = "safe-to-deploy" + +[[exemptions.r-efi]] +version = "5.3.0" +criteria = "safe-to-deploy" + +[[exemptions.rcgen]] +version = "0.14.7" +criteria = "safe-to-deploy" + +[[exemptions.redox_syscall]] +version = "0.5.18" +criteria = "safe-to-deploy" + +[[exemptions.ring]] +version = "0.17.14" +criteria = "safe-to-deploy" + +[[exemptions.rsqlite-vfs]] +version = "0.1.0" +criteria = "safe-to-deploy" + +[[exemptions.rusticata-macros]] +version = "4.1.0" +criteria = "safe-to-deploy" + +[[exemptions.rustls]] +version = "0.23.36" +criteria = "safe-to-deploy" + +[[exemptions.rustls-pki-types]] +version = "1.14.0" +criteria = "safe-to-deploy" + +[[exemptions.rustls-webpki]] +version = "0.103.9" +criteria = "safe-to-deploy" + +[[exemptions.scoped-futures]] +version = "0.1.4" +criteria = "safe-to-deploy" + +[[exemptions.secrecy]] +version = "0.10.3" +criteria = "safe-to-deploy" + +[[exemptions.semver]] +version = "1.0.27" +criteria = "safe-to-deploy" + +[[exemptions.sha2]] +version = "0.11.0-rc.5" +criteria = "safe-to-deploy" + +[[exemptions.signal-hook-registry]] +version = "1.4.8" +criteria = "safe-to-deploy" + +[[exemptions.signature]] +version = "3.0.0-rc.10" +criteria = "safe-to-deploy" + +[[exemptions.simd-adler32]] +version = "0.3.8" +criteria = "safe-to-deploy" + +[[exemptions.smlang]] +version = "0.8.0" +criteria = "safe-to-deploy" + +[[exemptions.smlang-macros]] +version = "0.8.0" +criteria = "safe-to-deploy" + +[[exemptions.sqlite-wasm-rs]] +version = "0.5.2" +criteria = "safe-to-deploy" + +[[exemptions.string_morph]] +version = "0.1.0" +criteria = "safe-to-deploy" + +[[exemptions.supports-color]] +version = "3.0.2" +criteria = "safe-to-deploy" + +[[exemptions.supports-hyperlinks]] +version = "3.2.0" +criteria = "safe-to-deploy" + +[[exemptions.supports-unicode]] +version = "3.0.0" +criteria = "safe-to-deploy" + +[[exemptions.sync_wrapper]] +version = "1.0.2" +criteria = "safe-to-deploy" + +[[exemptions.tempfile]] +version = "3.25.0" +criteria = "safe-to-deploy" + +[[exemptions.terminal_size]] +version = "0.4.3" +criteria = "safe-to-deploy" + +[[exemptions.tokio-rustls]] +version = "0.26.4" +criteria = "safe-to-deploy" + +[[exemptions.tracing]] +version = "0.1.44" +criteria = "safe-to-deploy" + +[[exemptions.tracing-attributes]] +version = "0.1.31" +criteria = "safe-to-deploy" + +[[exemptions.tracing-core]] +version = "0.1.36" +criteria = "safe-to-deploy" + +[[exemptions.tracing-subscriber]] +version = "0.3.22" +criteria = "safe-to-run" + +[[exemptions.typenum]] +version = "1.19.0" +criteria = "safe-to-deploy" + +[[exemptions.untrusted]] +version = "0.9.0" +criteria = "safe-to-deploy" + +[[exemptions.wasm-bindgen-macro]] +version = "0.2.108" +criteria = "safe-to-deploy" + +[[exemptions.wasm-bindgen-macro-support]] +version = "0.2.108" +criteria = "safe-to-deploy" + +[[exemptions.wasm-bindgen-shared]] +version = "0.2.108" +criteria = "safe-to-deploy" + +[[exemptions.winapi]] +version = "0.3.9" +criteria = "safe-to-deploy" + +[[exemptions.winapi-i686-pc-windows-gnu]] +version = "0.4.0" +criteria = "safe-to-deploy" + +[[exemptions.winapi-x86_64-pc-windows-gnu]] +version = "0.4.0" +criteria = "safe-to-deploy" + +[[exemptions.x509-parser]] +version = "0.18.1" +criteria = "safe-to-deploy" + +[[exemptions.yasna]] +version = "0.5.2" +criteria = "safe-to-deploy" + +[[exemptions.zstd]] +version = "0.13.3" +criteria = "safe-to-deploy" + +[[exemptions.zstd-safe]] +version = "7.2.4" +criteria = "safe-to-deploy" + +[[exemptions.zstd-sys]] +version = "2.0.16+zstd.1.5.7" +criteria = "safe-to-deploy" diff --git a/server/supply-chain/imports.lock b/server/supply-chain/imports.lock index 7737ea1..5977b98 100644 --- a/server/supply-chain/imports.lock +++ b/server/supply-chain/imports.lock @@ -1,3632 +1,3632 @@ - -# cargo-vet imports lock - -[[publisher.addr2line]] -version = "0.25.1" -when = "2025-09-13" -user-id = 4415 -user-login = "philipc" -user-name = "Philip Craig" - -[[publisher.aho-corasick]] -version = "1.1.4" -when = "2025-10-28" -user-id = 189 -user-login = "BurntSushi" -user-name = "Andrew Gallant" - -[[publisher.anyhow]] -version = "1.0.102" -when = "2026-02-20" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.async-stream]] -version = "0.3.6" -when = "2024-10-01" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.async-stream-impl]] -version = "0.3.6" -when = "2024-10-01" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.async-trait]] -version = "0.1.89" -when = "2025-08-14" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.auto_impl]] -version = "1.3.0" -when = "2025-04-09" -user-id = 3204 -user-login = "KodrAus" -user-name = "Ashley Mannix" - -[[publisher.aws-lc-rs]] -version = "1.16.1" -when = "2026-03-02" -user-id = 156764 -user-login = "justsmth" -user-name = "Justin W Smith" - -[[publisher.aws-lc-sys]] -version = "0.38.0" -when = "2026-03-02" -user-id = 156764 -user-login = "justsmth" -user-name = "Justin W Smith" - -[[publisher.backtrace]] -version = "0.3.76" -when = "2025-09-26" -user-id = 55123 -user-login = "rust-lang-owner" - -[[publisher.bitflags]] -version = "2.11.0" -when = "2026-02-14" -user-id = 3204 -user-login = "KodrAus" -user-name = "Ashley Mannix" - -[[publisher.bumpalo]] -version = "3.20.2" -when = "2026-02-19" -user-id = 696 -user-login = "fitzgen" -user-name = "Nick Fitzgerald" - -[[publisher.bytes]] -version = "1.11.1" -when = "2026-02-03" -user-id = 6741 -user-login = "Darksonn" -user-name = "Alice Ryhl" - -[[publisher.cmake]] -version = "0.1.57" -when = "2025-12-17" -user-id = 55123 -user-login = "rust-lang-owner" - -[[publisher.core-foundation-sys]] -version = "0.8.4" -when = "2023-04-03" -user-id = 5946 -user-login = "jrmuizel" -user-name = "Jeff Muizelaar" - -[[publisher.crossbeam-utils]] -version = "0.8.21" -when = "2024-12-15" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.derive_more]] -version = "2.1.1" -when = "2025-12-22" -user-id = 3797 -user-login = "JelteF" -user-name = "Jelte Fennema-Nio" - -[[publisher.derive_more-impl]] -version = "2.1.1" -when = "2025-12-22" -user-id = 3797 -user-login = "JelteF" -user-name = "Jelte Fennema-Nio" - -[[publisher.dyn-clone]] -version = "1.0.20" -when = "2025-07-27" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.ff]] -version = "0.13.1" -when = "2025-03-09" -user-id = 6289 -user-login = "str4d" -user-name = "Jack Grigg" - -[[publisher.flate2]] -version = "1.1.9" -when = "2026-02-03" -user-id = 980 -user-login = "Byron" -user-name = "Sebastian Thiel" - -[[publisher.futures]] -version = "0.3.32" -when = "2026-02-15" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.futures-channel]] -version = "0.3.32" -when = "2026-02-15" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.futures-core]] -version = "0.3.32" -when = "2026-02-15" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.futures-executor]] -version = "0.3.32" -when = "2026-02-15" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.futures-io]] -version = "0.3.32" -when = "2026-02-15" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.futures-macro]] -version = "0.3.32" -when = "2026-02-15" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.futures-sink]] -version = "0.3.32" -when = "2026-02-15" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.futures-task]] -version = "0.3.32" -when = "2026-02-15" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.futures-util]] -version = "0.3.32" -when = "2026-02-15" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.group]] -version = "0.12.0" -when = "2022-05-04" -user-id = 1244 -user-login = "ebfull" - -[[publisher.h2]] -version = "0.4.13" -when = "2026-01-05" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.hashbrown]] -version = "0.14.5" -when = "2024-04-28" -user-id = 2915 -user-login = "Amanieu" -user-name = "Amanieu d'Antras" - -[[publisher.hashbrown]] -version = "0.15.5" -when = "2025-08-07" -user-id = 55123 -user-login = "rust-lang-owner" - -[[publisher.hashbrown]] -version = "0.16.1" -when = "2025-11-20" -user-id = 55123 -user-login = "rust-lang-owner" - -[[publisher.http]] -version = "1.4.0" -when = "2025-11-24" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.http-body-util]] -version = "0.1.3" -when = "2025-03-11" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.httparse]] -version = "1.10.1" -when = "2025-03-03" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.hyper]] -version = "1.8.1" -when = "2025-11-13" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.hyper-util]] -version = "0.1.20" -when = "2026-02-02" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.id-arena]] -version = "2.3.0" -when = "2026-01-14" -user-id = 696 -user-login = "fitzgen" -user-name = "Nick Fitzgerald" - -[[publisher.indexmap]] -version = "1.9.3" -when = "2023-03-24" -user-id = 539 -user-login = "cuviper" -user-name = "Josh Stone" - -[[publisher.indexmap]] -version = "2.13.0" -when = "2026-01-07" -user-id = 539 -user-login = "cuviper" -user-name = "Josh Stone" - -[[publisher.itoa]] -version = "1.0.17" -when = "2025-12-27" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.jobserver]] -version = "0.1.34" -when = "2025-08-23" -user-id = 55123 -user-login = "rust-lang-owner" - -[[publisher.libc]] -version = "0.2.183" -when = "2026-03-08" -user-id = 55123 -user-login = "rust-lang-owner" - -[[publisher.libm]] -version = "0.2.16" -when = "2026-01-24" -user-id = 55123 -user-login = "rust-lang-owner" - -[[publisher.linux-raw-sys]] -version = "0.12.1" -when = "2025-12-23" -user-id = 6825 -user-login = "sunfishcode" -user-name = "Dan Gohman" - -[[publisher.lock_api]] -version = "0.4.14" -when = "2025-10-03" -user-id = 2915 -user-login = "Amanieu" -user-name = "Amanieu d'Antras" - -[[publisher.log]] -version = "0.4.29" -when = "2025-12-02" -user-id = 3204 -user-login = "KodrAus" -user-name = "Ashley Mannix" - -[[publisher.macro-string]] -version = "0.1.4" -when = "2025-03-03" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.memchr]] -version = "2.8.0" -when = "2026-02-06" -user-id = 189 -user-login = "BurntSushi" -user-name = "Andrew Gallant" - -[[publisher.mime]] -version = "0.3.17" -when = "2023-03-20" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.mio]] -version = "1.1.1" -when = "2025-12-04" -user-id = 6025 -user-login = "Thomasdezeeuw" -user-name = "Thomas de Zeeuw" - -[[publisher.num-bigint]] -version = "0.4.6" -when = "2024-06-27" -user-id = 539 -user-login = "cuviper" -user-name = "Josh Stone" - -[[publisher.num_cpus]] -version = "1.17.0" -when = "2025-05-30" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.object]] -version = "0.37.3" -when = "2025-08-13" -user-id = 4415 -user-login = "philipc" -user-name = "Philip Craig" - -[[publisher.parking_lot]] -version = "0.12.5" -when = "2025-10-03" -user-id = 2915 -user-login = "Amanieu" -user-name = "Amanieu d'Antras" - -[[publisher.parking_lot_core]] -version = "0.9.12" -when = "2025-10-03" -user-id = 2915 -user-login = "Amanieu" -user-name = "Amanieu d'Antras" - -[[publisher.paste]] -version = "1.0.15" -when = "2024-05-07" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.portable-atomic]] -version = "1.13.1" -when = "2026-01-31" -user-id = 33035 -user-login = "taiki-e" -user-name = "Taiki Endo" - -[[publisher.prettyplease]] -version = "0.2.37" -when = "2025-08-19" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.proc-macro2]] -version = "1.0.106" -when = "2026-01-21" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.prost]] -version = "0.14.3" -when = "2026-01-10" -user-id = 3959 -user-login = "LucioFranco" -user-name = "Lucio Franco" - -[[publisher.prost-build]] -version = "0.14.3" -when = "2026-01-10" -user-id = 3959 -user-login = "LucioFranco" -user-name = "Lucio Franco" - -[[publisher.prost-derive]] -version = "0.14.3" -when = "2026-01-10" -user-id = 3959 -user-login = "LucioFranco" -user-name = "Lucio Franco" - -[[publisher.prost-types]] -version = "0.14.3" -when = "2026-01-10" -user-id = 3959 -user-login = "LucioFranco" -user-name = "Lucio Franco" - -[[publisher.protoc-bin-vendored-linux-aarch_64]] -version = "3.2.0" -when = "2025-07-21" -user-id = 220 -user-login = "stepancheg" -user-name = "Stepan Koltsov" - -[[publisher.protoc-bin-vendored-linux-ppcle_64]] -version = "3.2.0" -when = "2025-07-21" -user-id = 220 -user-login = "stepancheg" -user-name = "Stepan Koltsov" - -[[publisher.protoc-bin-vendored-linux-s390_64]] -version = "3.2.0" -when = "2025-07-21" -user-id = 220 -user-login = "stepancheg" -user-name = "Stepan Koltsov" - -[[publisher.protoc-bin-vendored-linux-x86_32]] -version = "3.2.0" -when = "2025-07-21" -user-id = 220 -user-login = "stepancheg" -user-name = "Stepan Koltsov" - -[[publisher.protoc-bin-vendored-linux-x86_64]] -version = "3.2.0" -when = "2025-07-21" -user-id = 220 -user-login = "stepancheg" -user-name = "Stepan Koltsov" - -[[publisher.protoc-bin-vendored-macos-aarch_64]] -version = "3.2.0" -when = "2025-07-21" -user-id = 220 -user-login = "stepancheg" -user-name = "Stepan Koltsov" - -[[publisher.protoc-bin-vendored-macos-x86_64]] -version = "3.2.0" -when = "2025-07-21" -user-id = 220 -user-login = "stepancheg" -user-name = "Stepan Koltsov" - -[[publisher.protoc-bin-vendored-win32]] -version = "3.2.0" -when = "2025-07-21" -user-id = 220 -user-login = "stepancheg" -user-name = "Stepan Koltsov" - -[[publisher.pulldown-cmark-to-cmark]] -version = "22.0.0" -when = "2025-12-23" -user-id = 980 -user-login = "Byron" -user-name = "Sebastian Thiel" - -[[publisher.quote]] -version = "1.0.45" -when = "2026-03-03" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.ref-cast]] -version = "1.0.25" -when = "2025-09-28" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.ref-cast-impl]] -version = "1.0.25" -when = "2025-09-28" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.regex]] -version = "1.12.3" -when = "2026-02-03" -user-id = 189 -user-login = "BurntSushi" -user-name = "Andrew Gallant" - -[[publisher.regex-automata]] -version = "0.4.14" -when = "2026-02-03" -user-id = 189 -user-login = "BurntSushi" -user-name = "Andrew Gallant" - -[[publisher.regex-syntax]] -version = "0.8.10" -when = "2026-02-24" -user-id = 189 -user-login = "BurntSushi" -user-name = "Andrew Gallant" - -[[publisher.reqwest]] -version = "0.12.28" -when = "2025-12-22" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.rustc-demangle]] -version = "0.1.27" -when = "2026-01-15" -user-id = 55123 -user-login = "rust-lang-owner" - -[[publisher.rustix]] -version = "1.1.4" -when = "2026-02-22" -user-id = 6825 -user-login = "sunfishcode" -user-name = "Dan Gohman" - -[[publisher.ryu]] -version = "1.0.23" -when = "2026-02-08" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.scopeguard]] -version = "1.2.0" -when = "2023-07-17" -user-id = 2915 -user-login = "Amanieu" -user-name = "Amanieu d'Antras" - -[[publisher.serde_json]] -version = "1.0.149" -when = "2026-01-06" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.slab]] -version = "0.4.12" -when = "2026-01-31" -user-id = 6741 -user-login = "Darksonn" -user-name = "Alice Ryhl" - -[[publisher.socket2]] -version = "0.6.3" -when = "2026-03-06" -user-id = 6025 -user-login = "Thomasdezeeuw" -user-name = "Thomas de Zeeuw" - -[[publisher.syn]] -version = "1.0.109" -when = "2023-02-24" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.syn]] -version = "2.0.117" -when = "2026-02-20" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.thread_local]] -version = "1.1.9" -when = "2025-06-12" -user-id = 2915 -user-login = "Amanieu" -user-name = "Amanieu d'Antras" - -[[publisher.time]] -version = "0.3.47" -when = "2026-02-05" -user-id = 15682 -user-login = "jhpratt" -user-name = "Jacob Pratt" - -[[publisher.tinystr]] -version = "0.8.2" -when = "2025-10-28" -user-id = 1139 -user-login = "Manishearth" -user-name = "Manish Goregaokar" - -[[publisher.tokio]] -version = "1.50.0" -when = "2026-03-03" -user-id = 6741 -user-login = "Darksonn" -user-name = "Alice Ryhl" - -[[publisher.tokio-macros]] -version = "2.6.1" -when = "2026-03-02" -user-id = 6741 -user-login = "Darksonn" -user-name = "Alice Ryhl" - -[[publisher.tokio-stream]] -version = "0.1.18" -when = "2026-01-04" -user-id = 6741 -user-login = "Darksonn" -user-name = "Alice Ryhl" - -[[publisher.tokio-util]] -version = "0.7.18" -when = "2026-01-04" -user-id = 6741 -user-login = "Darksonn" -user-name = "Alice Ryhl" - -[[publisher.toml]] -version = "0.9.12+spec-1.1.0" -when = "2026-02-10" -user-id = 6743 -user-login = "epage" -user-name = "Ed Page" - -[[publisher.toml_datetime]] -version = "1.0.0+spec-1.1.0" -when = "2026-02-11" -user-id = 6743 -user-login = "epage" -user-name = "Ed Page" - -[[publisher.toml_edit]] -version = "0.25.4+spec-1.1.0" -when = "2026-03-04" -user-id = 6743 -user-login = "epage" -user-name = "Ed Page" - -[[publisher.toml_parser]] -version = "1.0.9+spec-1.1.0" -when = "2026-02-16" -user-id = 6743 -user-login = "epage" -user-name = "Ed Page" - -[[publisher.tonic]] -version = "0.14.5" -when = "2026-02-19" -user-id = 3959 -user-login = "LucioFranco" -user-name = "Lucio Franco" - -[[publisher.tonic-build]] -version = "0.14.5" -when = "2026-02-19" -user-id = 3959 -user-login = "LucioFranco" -user-name = "Lucio Franco" - -[[publisher.tonic-prost]] -version = "0.14.5" -when = "2026-02-19" -user-id = 3959 -user-login = "LucioFranco" -user-name = "Lucio Franco" - -[[publisher.tonic-prost-build]] -version = "0.14.5" -when = "2026-02-19" -user-id = 3959 -user-login = "LucioFranco" -user-name = "Lucio Franco" - -[[publisher.tower]] -version = "0.5.3" -when = "2026-01-12" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.tower-http]] -version = "0.6.8" -when = "2025-12-08" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.tower-layer]] -version = "0.3.3" -when = "2024-08-13" -user-id = 3959 -user-login = "LucioFranco" -user-name = "Lucio Franco" - -[[publisher.tower-service]] -version = "0.3.3" -when = "2024-08-13" -user-id = 3959 -user-login = "LucioFranco" -user-name = "Lucio Franco" - -[[publisher.ucd-trie]] -version = "0.1.7" -when = "2024-09-29" -user-id = 189 -user-login = "BurntSushi" -user-name = "Andrew Gallant" - -[[publisher.unicase]] -version = "2.9.0" -when = "2026-01-06" -user-id = 359 -user-login = "seanmonstar" -user-name = "Sean McArthur" - -[[publisher.unicode-ident]] -version = "1.0.24" -when = "2026-02-16" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[publisher.unicode-segmentation]] -version = "1.12.0" -when = "2024-09-13" -user-id = 1139 -user-login = "Manishearth" -user-name = "Manish Goregaokar" - -[[publisher.unicode-width]] -version = "0.1.14" -when = "2024-09-19" -user-id = 1139 -user-login = "Manishearth" -user-name = "Manish Goregaokar" - -[[publisher.unicode-width]] -version = "0.2.2" -when = "2025-10-06" -user-id = 1139 -user-login = "Manishearth" -user-name = "Manish Goregaokar" - -[[publisher.unicode-xid]] -version = "0.2.6" -when = "2024-09-19" -user-id = 1139 -user-login = "Manishearth" -user-name = "Manish Goregaokar" - -[[publisher.url]] -version = "2.5.8" -when = "2026-01-05" -user-id = 1139 -user-login = "Manishearth" -user-name = "Manish Goregaokar" - -[[publisher.utf8_iter]] -version = "1.0.4" -when = "2023-12-01" -user-id = 4484 -user-login = "hsivonen" -user-name = "Henri Sivonen" - -[[publisher.uuid]] -version = "1.22.0" -when = "2026-03-05" -user-id = 3204 -user-login = "KodrAus" -user-name = "Ashley Mannix" - -[[publisher.valuable]] -version = "0.1.0" -when = "2022-01-03" -user-id = 10 -user-login = "carllerche" -user-name = "Carl Lerche" - -[[publisher.wait-timeout]] -version = "0.2.1" -when = "2025-02-03" -user-id = 1 -user-login = "alexcrichton" -user-name = "Alex Crichton" - -[[publisher.wasi]] -version = "0.11.1+wasi-snapshot-preview1" -when = "2025-06-10" -user-id = 1 -user-login = "alexcrichton" -user-name = "Alex Crichton" - -[[publisher.wasip2]] -version = "1.0.2+wasi-0.2.9" -when = "2026-01-15" -user-id = 1 -user-login = "alexcrichton" -user-name = "Alex Crichton" - -[[publisher.wasip3]] -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -when = "2026-01-15" -user-id = 1 -user-login = "alexcrichton" -user-name = "Alex Crichton" - -[[publisher.wasm-bindgen]] -version = "0.2.99" -when = "2024-12-07" -user-id = 1 -user-login = "alexcrichton" -user-name = "Alex Crichton" - -[[publisher.wasm-encoder]] -version = "0.244.0" -when = "2026-01-06" -trusted-publisher = "github:bytecodealliance/wasm-tools" - -[[publisher.wasm-metadata]] -version = "0.236.0" -when = "2025-07-28" -user-id = 73222 -user-login = "wasmtime-publish" - -[[publisher.wasmparser]] -version = "0.244.0" -when = "2026-01-06" -trusted-publisher = "github:bytecodealliance/wasm-tools" - -[[publisher.windows-core]] -version = "0.62.2" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-implement]] -version = "0.60.2" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-interface]] -version = "0.59.3" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-result]] -version = "0.4.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-strings]] -version = "0.5.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-sys]] -version = "0.52.0" -when = "2023-11-15" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-sys]] -version = "0.59.0" -when = "2024-07-30" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-sys]] -version = "0.60.2" -when = "2025-06-12" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-sys]] -version = "0.61.2" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-targets]] -version = "0.52.6" -when = "2024-07-03" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-targets]] -version = "0.53.5" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_aarch64_gnullvm]] -version = "0.52.6" -when = "2024-07-03" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_aarch64_gnullvm]] -version = "0.53.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_aarch64_msvc]] -version = "0.52.6" -when = "2024-07-03" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_aarch64_msvc]] -version = "0.53.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_i686_gnu]] -version = "0.52.6" -when = "2024-07-03" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_i686_gnu]] -version = "0.53.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_i686_gnullvm]] -version = "0.52.6" -when = "2024-07-03" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_i686_gnullvm]] -version = "0.53.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_i686_msvc]] -version = "0.52.6" -when = "2024-07-03" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_i686_msvc]] -version = "0.53.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_x86_64_gnu]] -version = "0.52.6" -when = "2024-07-03" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_x86_64_gnu]] -version = "0.53.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_x86_64_gnullvm]] -version = "0.52.6" -when = "2024-07-03" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_x86_64_gnullvm]] -version = "0.53.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_x86_64_msvc]] -version = "0.52.6" -when = "2024-07-03" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows_x86_64_msvc]] -version = "0.53.1" -when = "2025-10-06" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.winnow]] -version = "0.7.15" -when = "2026-03-05" -user-id = 6743 -user-login = "epage" -user-name = "Ed Page" - -[[publisher.wit-bindgen]] -version = "0.51.0" -when = "2026-01-12" -trusted-publisher = "github:bytecodealliance/wit-bindgen" - -[[publisher.wit-bindgen-core]] -version = "0.51.0" -when = "2026-01-12" -trusted-publisher = "github:bytecodealliance/wit-bindgen" - -[[publisher.wit-bindgen-rust]] -version = "0.51.0" -when = "2026-01-12" -trusted-publisher = "github:bytecodealliance/wit-bindgen" - -[[publisher.wit-bindgen-rust-macro]] -version = "0.51.0" -when = "2026-01-12" -trusted-publisher = "github:bytecodealliance/wit-bindgen" - -[[publisher.wit-component]] -version = "0.244.0" -when = "2026-01-06" -trusted-publisher = "github:bytecodealliance/wasm-tools" - -[[publisher.wit-parser]] -version = "0.244.0" -when = "2026-01-06" -trusted-publisher = "github:bytecodealliance/wasm-tools" - -[[publisher.yoke]] -version = "0.8.1" -when = "2025-10-28" -user-id = 1139 -user-login = "Manishearth" -user-name = "Manish Goregaokar" - -[[publisher.zerocopy]] -version = "0.8.42" -when = "2026-03-09" -user-id = 7178 -user-login = "joshlf" -user-name = "Joshua Liebow-Feeser" - -[[publisher.zerocopy-derive]] -version = "0.8.42" -when = "2026-03-09" -user-id = 7178 -user-login = "joshlf" -user-name = "Joshua Liebow-Feeser" - -[[publisher.zerotrie]] -version = "0.2.3" -when = "2025-10-28" -user-id = 1139 -user-login = "Manishearth" -user-name = "Manish Goregaokar" - -[[publisher.zerovec]] -version = "0.11.5" -when = "2025-10-28" -user-id = 1139 -user-login = "Manishearth" -user-name = "Manish Goregaokar" - -[[publisher.zmij]] -version = "1.0.21" -when = "2026-02-12" -user-id = 3618 -user-login = "dtolnay" -user-name = "David Tolnay" - -[[audits.OpenDevicePartnership.audits.num_enum]] -who = "Billy Price " -criteria = "safe-to-deploy" -version = "0.7.5" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embassy-imxrt/refs/heads/main/supply-chain/audits.toml" - -[[audits.OpenDevicePartnership.audits.num_enum_derive]] -who = "Billy Price " -criteria = "safe-to-deploy" -version = "0.7.5" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embassy-imxrt/refs/heads/main/supply-chain/audits.toml" - -[[audits.OpenDevicePartnership.audits.proc-macro-error]] -who = "Jerry Xie " -criteria = "safe-to-deploy" -version = "1.0.4" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" - -[[audits.OpenDevicePartnership.audits.rand_core]] -who = "Billy Price " -criteria = "safe-to-deploy" -delta = "0.6.4 -> 0.9.5" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" - -[[audits.OpenDevicePartnership.audits.rstest]] -who = "Billy Price " -criteria = "safe-to-run" -delta = "0.22.0 -> 0.26.1" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" - -[[audits.OpenDevicePartnership.audits.rstest_macros]] -who = "Billy Price " -criteria = "safe-to-run" -delta = "0.22.0 -> 0.26.1" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" - -[[audits.OpenDevicePartnership.audits.serde]] -who = "Robert Zieba " -criteria = "safe-to-deploy" -version = "1.0.228" -notes = "Changes are mostly a reorganization of the internal module structure" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" - -[[audits.OpenDevicePartnership.audits.serde_core]] -who = "Robert Zieba " -criteria = "safe-to-deploy" -version = "1.0.226" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" - -[[audits.OpenDevicePartnership.audits.serde_derive]] -who = "Robert Zieba " -criteria = "safe-to-deploy" -version = "1.0.228" -notes = "Diff is clean-up in proc macros" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" - -[[audits.OpenDevicePartnership.audits.thiserror]] -who = "Felipe Balbi " -criteria = "safe-to-deploy" -version = "2.0.17" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/mcxa-pac/refs/heads/main/supply-chain/audits.toml" - -[[audits.OpenDevicePartnership.audits.thiserror-impl]] -who = "Felipe Balbi " -criteria = "safe-to-deploy" -version = "2.0.17" -aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/mcxa-pac/refs/heads/main/supply-chain/audits.toml" - -[[audits.bytecode-alliance.wildcard-audits.bumpalo]] -who = "Nick Fitzgerald " -criteria = "safe-to-deploy" -user-id = 696 # Nick Fitzgerald (fitzgen) -start = "2019-03-16" -end = "2026-08-21" - -[[audits.bytecode-alliance.wildcard-audits.wasip2]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2025-08-10" -end = "2026-08-21" -notes = """ -This is a Bytecode Alliance authored crate. -""" - -[[audits.bytecode-alliance.wildcard-audits.wasip3]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -user-id = 1 # Alex Crichton (alexcrichton) -start = "2025-09-10" -end = "2026-08-21" -notes = """ -This is a Bytecode Alliance authored crate. -""" - -[[audits.bytecode-alliance.wildcard-audits.wasm-encoder]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -trusted-publisher = "github:bytecodealliance/wasm-tools" -start = "2025-08-14" -end = "2027-01-08" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.wildcard-audits.wasm-metadata]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -user-id = 73222 # wasmtime-publish -start = "2023-01-01" -end = "2026-06-03" -notes = """ -The Bytecode Alliance uses the `wasmtime-publish` crates.io account to automate -publication of this crate from CI. This repository requires all PRs are reviewed -by a Bytecode Alliance maintainer and it owned by the Bytecode Alliance itself. -""" - -[[audits.bytecode-alliance.wildcard-audits.wasmparser]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -trusted-publisher = "github:bytecodealliance/wasm-tools" -start = "2025-08-14" -end = "2027-01-08" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.wildcard-audits.wit-bindgen]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -trusted-publisher = "github:bytecodealliance/wit-bindgen" -start = "2025-08-13" -end = "2027-01-08" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.wildcard-audits.wit-bindgen-core]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -trusted-publisher = "github:bytecodealliance/wit-bindgen" -start = "2025-08-13" -end = "2027-01-08" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.wildcard-audits.wit-bindgen-rust]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -trusted-publisher = "github:bytecodealliance/wit-bindgen" -start = "2025-08-13" -end = "2027-01-12" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.wildcard-audits.wit-bindgen-rust-macro]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -trusted-publisher = "github:bytecodealliance/wit-bindgen" -start = "2025-08-13" -end = "2027-01-08" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.wildcard-audits.wit-component]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -trusted-publisher = "github:bytecodealliance/wasm-tools" -start = "2025-08-14" -end = "2027-01-08" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.wildcard-audits.wit-parser]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -trusted-publisher = "github:bytecodealliance/wasm-tools" -start = "2025-08-14" -end = "2027-01-08" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.audits.adler2]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "2.0.0" -notes = "Fork of the original `adler` crate, zero unsfae code, works in `no_std`, does what it says on th tin." - -[[audits.bytecode-alliance.audits.allocator-api2]] -who = "Chris Fallin " -criteria = "safe-to-deploy" -delta = "0.2.18 -> 0.2.20" -notes = """ -The changes appear to be reasonable updates from Rust's stdlib imported into -`allocator-api2`'s copy of this code. -""" - -[[audits.bytecode-alliance.audits.atomic-waker]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "1.1.2" -notes = "Contains `unsafe` code but it's well-documented and scoped to what it's intended to be doing. Otherwise a well-focused and straightforward crate." - -[[audits.bytecode-alliance.audits.cfg-if]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "1.0.0" -notes = "I am the author of this crate." - -[[audits.bytecode-alliance.audits.cipher]] -who = "Andrew Brown " -criteria = "safe-to-deploy" -version = "0.4.4" -notes = "Most unsafe is hidden by `inout` dependency; only remaining unsafe is raw-splitting a slice and an unreachable hint. Older versions of this regularly reach ~150k daily downloads." - -[[audits.bytecode-alliance.audits.core-foundation-sys]] -who = "Dan Gohman " -criteria = "safe-to-deploy" -delta = "0.8.4 -> 0.8.6" -notes = """ -The changes here are all typical bindings updates: new functions, types, and -constants. I have not audited all the bindings for ABI conformance. -""" - -[[audits.bytecode-alliance.audits.der]] -who = "Chris Fallin " -criteria = "safe-to-deploy" -version = "0.7.10" -notes = "No unsafe code aside from transmutes for transparent newtypes." - -[[audits.bytecode-alliance.audits.displaydoc]] -who = "Nick Fitzgerald " -criteria = "safe-to-deploy" -delta = "0.2.4 -> 0.2.5" - -[[audits.bytecode-alliance.audits.encode_unicode]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.3.6 -> 1.0.0" -notes = "Lots of updates, small edits to `unsafe` code, but all as expected." - -[[audits.bytecode-alliance.audits.errno]] -who = "Dan Gohman " -criteria = "safe-to-deploy" -version = "0.3.0" -notes = "This crate uses libc and windows-sys APIs to get and set the raw OS error value." - -[[audits.bytecode-alliance.audits.errno]] -who = "Dan Gohman " -criteria = "safe-to-deploy" -delta = "0.3.0 -> 0.3.1" -notes = "Just a dependency version bump and a bug fix for redox" - -[[audits.bytecode-alliance.audits.errno]] -who = "Dan Gohman " -criteria = "safe-to-deploy" -delta = "0.3.9 -> 0.3.10" - -[[audits.bytecode-alliance.audits.fastrand]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "2.0.0 -> 2.0.1" -notes = """ -This update had a few doc updates but no otherwise-substantial source code -updates. -""" - -[[audits.bytecode-alliance.audits.fastrand]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "2.1.1 -> 2.3.0" -notes = "Minor refactoring, nothing new." - -[[audits.bytecode-alliance.audits.foldhash]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "0.1.3" -notes = """ -Only a minor amount of `unsafe` code in this crate related to global per-process -initialization which looks correct to me. -""" - -[[audits.bytecode-alliance.audits.gimli]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.29.0 -> 0.31.0" -notes = "Various updates here and there, nothing too major, what you'd expect from a DWARF parsing crate." - -[[audits.bytecode-alliance.audits.gimli]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.31.0 -> 0.31.1" -notes = "No fundmanetally new `unsafe` code, some small refactoring of existing code. Lots of changes in tests, not as many changes in the rest of the crate. More dwarf!" - -[[audits.bytecode-alliance.audits.gimli]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.31.1 -> 0.32.0" -notes = "Ever more DWARF to parse, but also no new `unsafe` and everything looks like gimli." - -[[audits.bytecode-alliance.audits.gimli]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.32.0 -> 0.32.3" -notes = "Ever more dwarf, it never ends! (nothing out of the ordinary)" - -[[audits.bytecode-alliance.audits.heck]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "0.4.0" -notes = "Contains `forbid_unsafe` and only uses `std::fmt` from the standard library. Otherwise only contains string manipulation." - -[[audits.bytecode-alliance.audits.heck]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.4.1 -> 0.5.0" -notes = "Minor changes for a `no_std` upgrade but otherwise everything looks as expected." - -[[audits.bytecode-alliance.audits.http-body]] -who = "Pat Hickey " -criteria = "safe-to-deploy" -version = "1.0.0-rc.2" - -[[audits.bytecode-alliance.audits.http-body]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "1.0.0-rc.2 -> 1.0.0" -notes = "Only minor changes made for a stable release." - -[[audits.bytecode-alliance.audits.iana-time-zone-haiku]] -who = "Dan Gohman " -criteria = "safe-to-deploy" -version = "0.1.2" - -[[audits.bytecode-alliance.audits.idna]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "0.3.0" -notes = """ -This is a crate without unsafe code or usage of the standard library. The large -size of this crate comes from the large generated unicode tables file. This -crate is broadly used throughout the ecosystem and does not contain anything -suspicious. -""" - -[[audits.bytecode-alliance.audits.inout]] -who = "Andrew Brown " -criteria = "safe-to-deploy" -version = "0.1.3" -notes = "A part of RustCrypto/utils, this crate is designed to handle unsafe buffers and carefully documents the safety concerns throughout. Older versions of this tally up to ~130k daily downloads." - -[[audits.bytecode-alliance.audits.leb128fmt]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "0.1.0" -notes = "Well-scoped crate do doing LEB encoding with no `unsafe` code and does what it says on the tin." - -[[audits.bytecode-alliance.audits.matchers]] -who = "Pat Hickey " -criteria = "safe-to-deploy" -version = "0.1.0" - -[[audits.bytecode-alliance.audits.matchers]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.1.0 -> 0.2.0" -notes = "Some unsafe code, but not more than before. Nothing awry." - -[[audits.bytecode-alliance.audits.miniz_oxide]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "0.7.1" -notes = """ -This crate is a Rust implementation of zlib compression/decompression and has -been used by default by the Rust standard library for quite some time. It's also -a default dependency of the popular `backtrace` crate for decompressing debug -information. This crate forbids unsafe code and does not otherwise access system -resources. It's originally a port of the `miniz.c` library as well, and given -its own longevity should be relatively hardened against some of the more common -compression-related issues. -""" - -[[audits.bytecode-alliance.audits.miniz_oxide]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.7.1 -> 0.8.0" -notes = "Minor updates, using new Rust features like `const`, no major changes." - -[[audits.bytecode-alliance.audits.miniz_oxide]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.8.0 -> 0.8.5" -notes = """ -Lots of small updates here and there, for example around modernizing Rust -idioms. No new `unsafe` code and everything looks like what you'd expect a -compression library to be doing. -""" - -[[audits.bytecode-alliance.audits.miniz_oxide]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.8.5 -> 0.8.9" -notes = "No new unsafe code, just refactorings." - -[[audits.bytecode-alliance.audits.nu-ansi-term]] -who = "Pat Hickey " -criteria = "safe-to-deploy" -version = "0.46.0" -notes = "one use of unsafe to call windows specific api to get console handle." - -[[audits.bytecode-alliance.audits.nu-ansi-term]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.46.0 -> 0.50.1" -notes = "Lots of stylistic/rust-related chanegs, plus new features, but nothing out of the ordrinary." - -[[audits.bytecode-alliance.audits.nu-ansi-term]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.50.1 -> 0.50.3" -notes = "CI changes, Rust changes, nothing out of the ordinary." - -[[audits.bytecode-alliance.audits.num-traits]] -who = "Andrew Brown " -criteria = "safe-to-deploy" -version = "0.2.19" -notes = "As advertised: a numeric library. The only `unsafe` is from some float-to-int conversions, which seems expected." - -[[audits.bytecode-alliance.audits.pem-rfc7468]] -who = "Chris Fallin " -criteria = "safe-to-deploy" -version = "0.7.0" -notes = "Only `unsafe` around a `from_utf8_unchecked`, and no IO." - -[[audits.bytecode-alliance.audits.percent-encoding]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "2.2.0" -notes = """ -This crate is a single-file crate that does what it says on the tin. There are -a few `unsafe` blocks related to utf-8 validation which are locally verifiable -as correct and otherwise this crate is good to go. -""" - -[[audits.bytecode-alliance.audits.pin-project-lite]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.2.13 -> 0.2.14" -notes = "No substantive changes in this update" - -[[audits.bytecode-alliance.audits.pin-utils]] -who = "Pat Hickey " -criteria = "safe-to-deploy" -version = "0.1.0" - -[[audits.bytecode-alliance.audits.pkg-config]] -who = "Pat Hickey " -criteria = "safe-to-deploy" -version = "0.3.25" -notes = "This crate shells out to the pkg-config executable, but it appears to sanitize inputs reasonably." - -[[audits.bytecode-alliance.audits.pkg-config]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.3.26 -> 0.3.29" -notes = """ -No `unsafe` additions or anything outside of the purview of the crate in this -change. -""" - -[[audits.bytecode-alliance.audits.pkg-config]] -who = "Chris Fallin " -criteria = "safe-to-deploy" -delta = "0.3.29 -> 0.3.32" - -[[audits.bytecode-alliance.audits.sharded-slab]] -who = "Pat Hickey " -criteria = "safe-to-deploy" -version = "0.1.4" -notes = "I always really enjoy reading eliza's code, she left perfect comments at every use of unsafe." - -[[audits.bytecode-alliance.audits.shlex]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "1.1.0" -notes = "Only minor `unsafe` code blocks which look valid and otherwise does what it says on the tin." - -[[audits.bytecode-alliance.audits.smallvec]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "1.13.2 -> 1.14.0" -notes = "Minor new feature, nothing out of the ordinary." - -[[audits.bytecode-alliance.audits.static_assertions]] -who = "Andrew Brown " -criteria = "safe-to-deploy" -version = "1.1.0" -notes = "No dependencies and completely a compile-time crate as advertised. Uses `unsafe` in one module as a compile-time check only: `mem::transmute` and `ptr::write` are wrapped in an impossible-to-run closure." - -[[audits.bytecode-alliance.audits.test-log]] -who = "Pat Hickey " -criteria = "safe-to-deploy" -version = "0.2.11" - -[[audits.bytecode-alliance.audits.test-log]] -who = "Alex Crichton " -criteria = "safe-to-run" -delta = "0.2.11 -> 0.2.16" -notes = "Crate implementation was moved to a `*-macros` crate, crate is very small as a result." - -[[audits.bytecode-alliance.audits.test-log]] -who = "Alex Crichton " -criteria = "safe-to-run" -delta = "0.2.16 -> 0.2.18" -notes = "Minor updates, nothing changing unsafe" - -[[audits.bytecode-alliance.audits.test-log-macros]] -who = "Alex Crichton " -criteria = "safe-to-run" -version = "0.2.16" -notes = "Simple procedural macro copied from its previous source." - -[[audits.bytecode-alliance.audits.test-log-macros]] -who = "Alex Crichton " -criteria = "safe-to-run" -delta = "0.2.16 -> 0.2.18" -notes = "Standard macro changes, nothing out of place" - -[[audits.bytecode-alliance.audits.tinyvec_macros]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "0.1.0" -notes = """ -This is a trivial crate which only contains a singular macro definition which is -intended to multiplex across the internal representation of a tinyvec, -presumably. This trivially doesn't contain anything bad. -""" - -[[audits.bytecode-alliance.audits.tracing-log]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "0.1.3" -notes = """ -This is a standard adapter between the `log` ecosystem and the `tracing` -ecosystem. There's one `unsafe` block in this crate and it's well-scoped. -""" - -[[audits.bytecode-alliance.audits.tracing-log]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.1.3 -> 0.2.0" -notes = "Nothing out of the ordinary, a typical major version update and nothing awry." - -[[audits.bytecode-alliance.audits.try-lock]] -who = "Pat Hickey " -criteria = "safe-to-deploy" -version = "0.2.4" -notes = "Implements a concurrency primitive with atomics, and is not obviously incorrect" - -[[audits.bytecode-alliance.audits.vcpkg]] -who = "Pat Hickey " -criteria = "safe-to-deploy" -version = "0.2.15" -notes = "no build.rs, no macros, no unsafe. It reads the filesystem and makes copies of DLLs into OUT_DIR." - -[[audits.bytecode-alliance.audits.want]] -who = "Pat Hickey " -criteria = "safe-to-deploy" -version = "0.3.0" - -[[audits.bytecode-alliance.audits.wasm-metadata]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.236.0 -> 0.237.0" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.audits.wasm-metadata]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.237.0 -> 0.238.1" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.audits.wasm-metadata]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.238.1 -> 0.239.0" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.audits.wasm-metadata]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.239.0 -> 0.240.0" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.audits.wasm-metadata]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.240.0 -> 0.241.2" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.audits.wasm-metadata]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.241.2 -> 0.242.0" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.audits.wasm-metadata]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.242.0 -> 0.243.0" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.bytecode-alliance.audits.wasm-metadata]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -delta = "0.243.0 -> 0.244.0" -notes = "The Bytecode Alliance is the author of this crate" - -[[audits.embark-studios.audits.cfg_aliases]] -who = "Johan Andersson " -criteria = "safe-to-deploy" -version = "0.1.1" -notes = "No unsafe usage or ambient capabilities" - -[[audits.embark-studios.audits.ident_case]] -who = "Johan Andersson " -criteria = "safe-to-deploy" -version = "1.0.1" -notes = "No unsafe usage or ambient capabilities" - -[[audits.embark-studios.audits.idna]] -who = "Johan Andersson " -criteria = "safe-to-deploy" -delta = "0.3.0 -> 0.4.0" -notes = "No unsafe usage or ambient capabilities" - -[[audits.embark-studios.audits.tap]] -who = "Johan Andersson " -criteria = "safe-to-deploy" -version = "1.0.1" -notes = "No unsafe usage or ambient capabilities" - -[[audits.google.audits.arrayvec]] -who = "Lukasz Anforowicz " -criteria = "safe-to-deploy" -version = "0.7.6" -notes = ''' -Grepped for `-i cipher`, `-i crypto`, `'\bfs\b'`, `'\bnet\b'` and there were -no hits, except for some `net` usage in tests. - -The crate has quite a few bits of `unsafe` Rust. The audit comments can be -found in https://chromium-review.googlesource.com/c/chromium/src/+/6187726/2 -''' -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.autocfg]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "1.4.0" -notes = "Contains no unsafe" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.base64]] -who = "amarjotgill " -criteria = "safe-to-deploy" -version = "0.22.1" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.byteorder]] -who = "danakj " -criteria = "safe-to-deploy" -version = "1.5.0" -notes = "Unsafe review in https://crrev.com/c/5838022" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.either]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "1.13.0" -notes = "Unsafe code pertaining to wrapping Pin APIs. Mostly passes invariants down." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.either]] -who = "Daniel Cheng " -criteria = "safe-to-deploy" -delta = "1.13.0 -> 1.14.0" -notes = """ -Inheriting ub-risk-1 from the baseline review of 1.13.0. While the delta has some diffs in unsafe code, they are either: -- migrating code to use helper macros -- migrating match patterns to take advantage of default bindings mode from RFC 2005 -Either way, the result is code that does exactly the same thing and does not change the risk of UB. - -See https://crrev.com/c/6323164 for more audit details. -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.either]] -who = "Lukasz Anforowicz " -criteria = "safe-to-deploy" -delta = "1.14.0 -> 1.15.0" -notes = 'The delta in `lib.rs` only tweaks doc comments and `#[cfg(feature = "std")]`.' -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.equivalent]] -who = "George Burgess IV " -criteria = "safe-to-deploy" -version = "1.0.1" -aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" - -[[audits.google.audits.equivalent]] -who = "Jonathan Hao " -criteria = "safe-to-deploy" -delta = "1.0.1 -> 1.0.2" -notes = "No changes to any .rs files or Rust code." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.fastrand]] -who = "George Burgess IV " -criteria = "safe-to-deploy" -version = "1.9.0" -notes = """ -`does-not-implement-crypto` is certified because this crate explicitly says -that the RNG here is not cryptographically secure. -""" -aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" - -[[audits.google.audits.foldhash]] -who = "Adrian Taylor " -criteria = "safe-to-deploy" -delta = "0.1.3 -> 0.1.4" -notes = "No changes to safety-relevant code" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.foldhash]] -who = "Chris Palmer " -criteria = "safe-to-deploy" -delta = "0.1.4 -> 0.1.5" -notes = "No new `unsafe`." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.glob]] -who = "George Burgess IV " -criteria = "safe-to-deploy" -version = "0.3.1" -aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" - -[[audits.google.audits.glob]] -who = "Dustin J. Mitchell " -criteria = "safe-to-deploy" -delta = "0.3.1 -> 0.3.2" -notes = "Still no unsafe" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.httpdate]] -who = "George Burgess IV " -criteria = "safe-to-deploy" -version = "1.0.3" -aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" - -[[audits.google.audits.icu_collections]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "2.0.0-beta1" -notes = """ -Two instances of unsafe : - - Non-safety related unsafe API that imposes additional invariants - - `from_utf8` for known-UTF8 integer - -Comments added/improved in https://github.com/unicode-org/icu4x/pull/6056. -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.icu_collections]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -delta = "2.0.0-beta1 -> 2.0.0-beta2" -notes = "from_utf8 unsafe removed. no new unsafe added" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.icu_locale_core]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "2.0.0-beta2" -notes = """ -All unsafe code commented (and improved from prior version): - - A checklisted ULE impl - - from-utf8 code on known-ASCII - - Some unchecked indexing around maintained invariants -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.icu_normalizer]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "2.0.0-beta2" -notes = """ -All unsafe is unchecked `char` and `str` conversion, mostly well-commented. -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.icu_normalizer_data]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "2.0.0-beta1" -notes = "Contains codegenned unsafe only, using safe Bake impls from zerovec/zerotrie" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.icu_normalizer_data]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -delta = "2.0.0-beta1 -> 2.0.0-beta2" -notes = "Contains codegenned unsafe only, using safe Bake impls from zerovec/zerotrie" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.icu_properties]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "2.0.0-beta2" -notes = "All unsafe was removed" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.icu_properties_data]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "2.0.0-beta1" -notes = "Contains codegenned unsafe only, using safe Bake impls from zerovec/zerotrie" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.icu_properties_data]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -delta = "2.0.0-beta1 -> 2.0.0-beta2" -notes = "Contains codegenned unsafe only, using safe Bake impls from zerovec/zerotrie" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.icu_provider]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "2.0.0-beta1" -notes = """ -All unsafe code commented: - - Minor unsafe transmutes between types which are identical but not type-system-provably so. - - One unsafe EqULE impl - - Some repr(transparent) transmutes - - A from_utf8_unchecked for an ascii-validated string - -Comment improvements can be found in https://github.com/unicode-org/icu4x/pull/6056 -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.icu_provider]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -delta = "2.0.0-beta1 -> 2.0.0-beta2" -notes = "from_utf8_unchecked unsafe remove, all other unsafe not meaningfully changed" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.lazy_static]] -who = "Lukasz Anforowicz " -criteria = "safe-to-deploy" -version = "1.4.0" -notes = ''' -I grepped for \"crypt\", \"cipher\", \"fs\", \"net\" - there were no hits. - -There are two places where `unsafe` is used. Unsafe review notes can be found -in https://crrev.com/c/5347418. - -This crate has been added to Chromium in https://crrev.com/c/3321895. -''' -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.lazy_static]] -who = "Lukasz Anforowicz " -criteria = "safe-to-deploy" -delta = "1.4.0 -> 1.5.0" -notes = "Unsafe review notes: https://crrev.com/c/5650836" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.litemap]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "0.7.4" -notes = "Contains no unsafe" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.litemap]] -who = "Daniel Cheng " -criteria = "safe-to-deploy" -delta = "0.7.4 -> 0.7.5" -notes = "Delta implements the entry API but doesn't add or change any unsafe code." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.nom]] -who = "danakj@chromium.org" -criteria = "safe-to-deploy" -version = "7.1.3" -notes = """ -Reviewed in https://chromium-review.googlesource.com/c/chromium/src/+/5046153 -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.num-integer]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "0.1.46" -notes = "Contains no unsafe" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.num-iter]] -who = "George Burgess IV " -criteria = "safe-to-deploy" -version = "0.1.43" -aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" - -[[audits.google.audits.pin-project-lite]] -who = "David Koloski " -criteria = "safe-to-deploy" -version = "0.2.9" -notes = "Reviewed on https://fxrev.dev/824504" -aggregated-from = "https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/third_party/rust_crates/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.pin-project-lite]] -who = "David Koloski " -criteria = "safe-to-deploy" -delta = "0.2.9 -> 0.2.13" -notes = "Audited at https://fxrev.dev/946396" -aggregated-from = "https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/third_party/rust_crates/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.potential_utf]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "0.1.0" -notes = "Contains a handful of lines of from-UTF8 unsafety and some `repr(transparent)` casting unsafety. Reasonably well commented, could do with listing invariants explicitly." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.potential_utf]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -delta = "0.1.0 -> 0.1.2" -notes = "Addition of safe comparison APIs since last audit" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.proc-macro-error-attr]] -who = "George Burgess IV " -criteria = "safe-to-deploy" -version = "1.0.4" -aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" - -[[audits.google.audits.rand]] -who = "Lukasz Anforowicz " -criteria = "safe-to-deploy" -version = "0.8.5" -notes = """ -For more detailed unsafe review notes please see https://crrev.com/c/6362797 -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rand_chacha]] -who = "Lukasz Anforowicz " -criteria = "safe-to-deploy" -version = "0.3.1" -notes = """ -For more detailed unsafe review notes please see https://crrev.com/c/6362797 -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rand_core]] -who = "Lukasz Anforowicz " -criteria = "safe-to-deploy" -version = "0.6.4" -notes = """ -For more detailed unsafe review notes please see https://crrev.com/c/6362797 -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.relative-path]] -who = "danakj " -criteria = "safe-to-deploy" -version = "1.9.3" -notes = """ -There is no net or fs usage, no crypto. -There is unsafe to convert pointers from str to RelativePath, where the latter -is a transparent wrapper around str so the pointer will be to a valid -type/value always. -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rstest]] -who = "danakj@chromium.org" -criteria = "safe-to-run" -version = "0.17.0" -notes = """ -Reviewed in https://crrev.com/c/5171063 - -Previously reviewed during security review and the audit is grandparented in. -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rstest]] -who = "danakj " -criteria = "safe-to-run" -delta = "0.17.0 -> 0.22.0" -notes = "No new unsafe. fs and net usage, but only in its own tests." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rstest_macros]] -who = "danakj " -criteria = "safe-to-run" -version = "0.22.0" -notes = """ -There is no fs or net usage directly, though there is fs -usage through the glob crate to get lists of files if the user -asks for it in their macro. - -There is no unsafe. Scanned through all the code. -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rustversion]] -who = "Lukasz Anforowicz " -criteria = "safe-to-deploy" -version = "1.0.14" -notes = """ -Grepped for `-i cipher`, `-i crypto`, `'\bfs\b'``, `'\bnet\b'``, `'\bunsafe\b'`` -and there were no hits except for: - -* Using trivially-safe `unsafe` in test code: - - ``` - tests/test_const.rs:unsafe fn _unsafe() {} - tests/test_const.rs:const _UNSAFE: () = unsafe { _unsafe() }; - ``` - -* Using `unsafe` in a string: - - ``` - src/constfn.rs: "unsafe" => Qualifiers::Unsafe, - ``` - -* Using `std::fs` in `build/build.rs` to write `${OUT_DIR}/version.expr` - which is later read back via `include!` used in `src/lib.rs`. - -Version `1.0.6` of this crate has been added to Chromium in -https://source.chromium.org/chromium/chromium/src/+/28841c33c77833cc30b286f9ae24c97e7a8f4057 -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rustversion]] -who = "Adrian Taylor " -criteria = "safe-to-deploy" -delta = "1.0.14 -> 1.0.15" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rustversion]] -who = "danakj " -criteria = "safe-to-deploy" -delta = "1.0.15 -> 1.0.16" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rustversion]] -who = "Dustin J. Mitchell " -criteria = "safe-to-deploy" -delta = "1.0.16 -> 1.0.17" -notes = "Just updates windows compat" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rustversion]] -who = "Liza Burakova " -criteria = "safe-to-deploy" -delta = "1.0.17 -> 1.0.18" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rustversion]] -who = "Dustin J. Mitchell " -criteria = "safe-to-deploy" -delta = "1.0.18 -> 1.0.19" -notes = "No unsafe, just doc changes" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.rustversion]] -who = "Daniel Cheng " -criteria = "safe-to-deploy" -delta = "1.0.19 -> 1.0.20" -notes = "Only minor updates to documentation and the mock today used for testing." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.smallvec]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "1.13.2" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.strsim]] -who = "danakj@chromium.org" -criteria = "safe-to-deploy" -version = "0.10.0" -notes = """ -Reviewed in https://crrev.com/c/5171063 - -Previously reviewed during security review and the audit is grandparented in. -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.strum]] -who = "danakj@chromium.org" -criteria = "safe-to-deploy" -version = "0.25.0" -notes = """ -Reviewed in https://crrev.com/c/5171063 - -Previously reviewed during security review and the audit is grandparented in. -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.strum_macros]] -who = "danakj@chromium.org" -criteria = "safe-to-deploy" -version = "0.25.3" -notes = """ -Reviewed in https://crrev.com/c/5171063 - -Previously reviewed during security review and the audit is grandparented in. -""" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.writeable]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "0.6.0" -notes = "Contains three lines of unsafe, thoroughly commented: one is for from-UTF8 on ASCII, the other two are for from-UTF8 on a datastructure that keeps track of a buffer with partial UTF8 validation. Relatively straigtforward." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.writeable]] -who = "Daniel Cheng " -criteria = "safe-to-deploy" -delta = "0.6.0 -> 0.6.1" -notes = "Minor comment/documentation updates and switch to a non-panicking alternative to split_at()." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.yoke-derive]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "0.7.5" -notes = "Custom derive implementing the `Yokeable` trait. Generally generates simple code that asserts covariance." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.yoke-derive]] -who = "Daniel Cheng " -criteria = "safe-to-deploy" -delta = "0.7.5 -> 0.8.0" -notes = "No code changes: only incrementing the version." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.zerofrom]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "0.1.5" -notes = "Contains no unsafe" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.zerofrom]] -who = "Daniel Cheng " -criteria = "safe-to-deploy" -delta = "0.1.5 -> 0.1.6" -notes = "Only minor cfg tweaks." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.zerofrom-derive]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -version = "0.1.5" -notes = "Contains no unsafe" -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.google.audits.zerofrom-derive]] -who = "Daniel Cheng " -criteria = "safe-to-deploy" -delta = "0.1.5 -> 0.1.6" -notes = "Only a minor clippy adjustment." -aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" - -[[audits.isrg.audits.cfg-if]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "1.0.0 -> 1.0.1" - -[[audits.isrg.audits.cfg-if]] -who = "J.C. Jones " -criteria = "safe-to-deploy" -delta = "1.0.1 -> 1.0.3" - -[[audits.isrg.audits.cfg-if]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "1.0.3 -> 1.0.4" - -[[audits.isrg.audits.cpufeatures]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.2.17 -> 0.3.0" - -[[audits.isrg.audits.fiat-crypto]] -who = "David Cook " -criteria = "safe-to-deploy" -version = "0.1.17" -notes = """ -This crate does not contain any unsafe code, and does not use any items from -the standard library or other crates, aside from operations backed by -`std::ops`. All paths with array indexing use integer literals for indexes, so -there are no panics due to indexes out of bounds (as rustc would catch an -out-of-bounds literal index). I did not check whether arithmetic overflows -could cause a panic, and I am relying on the Coq code having satisfied the -necessary preconditions to ensure panics due to overflows are unreachable. -""" - -[[audits.isrg.audits.fiat-crypto]] -who = "Brandon Pitman " -criteria = "safe-to-deploy" -delta = "0.1.17 -> 0.1.18" - -[[audits.isrg.audits.fiat-crypto]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.1.18 -> 0.1.19" -notes = """ -This release renames many items and adds a new module. The code in the new -module is entirely composed of arithmetic and array accesses. -""" - -[[audits.isrg.audits.fiat-crypto]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.1.19 -> 0.1.20" - -[[audits.isrg.audits.fiat-crypto]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.1.20 -> 0.2.0" - -[[audits.isrg.audits.fiat-crypto]] -who = "Brandon Pitman " -criteria = "safe-to-deploy" -delta = "0.2.0 -> 0.2.1" - -[[audits.isrg.audits.fiat-crypto]] -who = "Tim Geoghegan " -criteria = "safe-to-deploy" -delta = "0.2.1 -> 0.2.2" -notes = "No changes to `unsafe` code, or any functional changes that I can detect at all." - -[[audits.isrg.audits.fiat-crypto]] -who = "Brandon Pitman " -criteria = "safe-to-deploy" -delta = "0.2.2 -> 0.2.4" - -[[audits.isrg.audits.fiat-crypto]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.2.4 -> 0.2.5" - -[[audits.isrg.audits.fiat-crypto]] -who = "Brandon Pitman " -criteria = "safe-to-deploy" -delta = "0.2.5 -> 0.2.6" - -[[audits.isrg.audits.fiat-crypto]] -who = "Brandon Pitman " -criteria = "safe-to-deploy" -delta = "0.2.6 -> 0.2.7" - -[[audits.isrg.audits.fiat-crypto]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.2.7 -> 0.2.8" - -[[audits.isrg.audits.fiat-crypto]] -who = "Tim Geoghegan " -criteria = "safe-to-deploy" -delta = "0.2.8 -> 0.2.9" -notes = "No changes to Rust code between 0.2.8 and 0.2.9" - -[[audits.isrg.audits.fiat-crypto]] -who = "Tim Geoghegan " -criteria = "safe-to-deploy" -delta = "0.2.9 -> 0.3.0" -notes = "The diff is huge, but that's because it introduces a wrapper around indexing into arrays which is used in many many places. There is no new unsafe code and no change to build scripts I can detect." - -[[audits.isrg.audits.hmac]] -who = "David Cook " -criteria = "safe-to-deploy" -version = "0.12.1" - -[[audits.isrg.audits.num-iter]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.1.43 -> 0.1.44" - -[[audits.isrg.audits.num-iter]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.1.44 -> 0.1.45" - -[[audits.isrg.audits.once_cell]] -who = "J.C. Jones " -criteria = "safe-to-deploy" -delta = "1.21.3 -> 1.21.4" -notes = "The addition is a safe while loop around prior behavior. I don't see any way for that to become malicious." - -[[audits.isrg.audits.opaque-debug]] -who = "David Cook " -criteria = "safe-to-deploy" -version = "0.3.0" - -[[audits.isrg.audits.rand]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.8.5 -> 0.9.1" - -[[audits.isrg.audits.rand]] -who = "Tim Geoghegan " -criteria = "safe-to-deploy" -delta = "0.9.1 -> 0.9.2" - -[[audits.isrg.audits.rand]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.9.2 -> 0.10.0" - -[[audits.isrg.audits.rand_chacha]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.3.1 -> 0.9.0" - -[[audits.isrg.audits.rand_core]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.9.5 -> 0.10.0" - -[[audits.isrg.audits.sha2]] -who = "David Cook " -criteria = "safe-to-deploy" -version = "0.10.2" - -[[audits.isrg.audits.sha2]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.10.8 -> 0.10.9" - -[[audits.isrg.audits.sha3]] -who = "David Cook " -criteria = "safe-to-deploy" -version = "0.10.6" - -[[audits.isrg.audits.sha3]] -who = "Brandon Pitman " -criteria = "safe-to-deploy" -delta = "0.10.6 -> 0.10.7" - -[[audits.isrg.audits.sha3]] -who = "Brandon Pitman " -criteria = "safe-to-deploy" -delta = "0.10.7 -> 0.10.8" - -[[audits.isrg.audits.subtle]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "2.5.0 -> 2.6.1" - -[[audits.isrg.audits.thiserror]] -who = "J.C. Jones " -criteria = "safe-to-deploy" -delta = "2.0.17 -> 2.0.18" - -[[audits.isrg.audits.thiserror-impl]] -who = "J.C. Jones " -criteria = "safe-to-deploy" -delta = "2.0.17 -> 2.0.18" - -[[audits.isrg.audits.universal-hash]] -who = "David Cook " -criteria = "safe-to-deploy" -version = "0.4.1" - -[[audits.isrg.audits.universal-hash]] -who = "David Cook " -criteria = "safe-to-deploy" -delta = "0.5.0 -> 0.5.1" - -[[audits.isrg.audits.untrusted]] -who = "David Cook " -criteria = "safe-to-deploy" -version = "0.7.1" - -[[audits.mozilla.wildcard-audits.core-foundation-sys]] -who = "Bobby Holley " -criteria = "safe-to-deploy" -user-id = 5946 # Jeff Muizelaar (jrmuizel) -start = "2020-10-14" -end = "2023-05-04" -renew = false -notes = "I've reviewed every source contribution that was neither authored nor reviewed by Mozilla." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.wildcard-audits.unicode-segmentation]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -user-id = 1139 # Manish Goregaokar (Manishearth) -start = "2019-05-15" -end = "2026-02-01" -notes = "All code written or reviewed by Manish" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.wildcard-audits.unicode-width]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -user-id = 1139 # Manish Goregaokar (Manishearth) -start = "2019-12-05" -end = "2026-02-01" -notes = "All code written or reviewed by Manish" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.wildcard-audits.unicode-xid]] -who = "Manish Goregaokar " -criteria = "safe-to-deploy" -user-id = 1139 # Manish Goregaokar (Manishearth) -start = "2019-07-25" -end = "2026-02-01" -notes = "All code written or reviewed by Manish" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.wildcard-audits.utf8_iter]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -user-id = 4484 # Henri Sivonen (hsivonen) -start = "2022-04-19" -end = "2024-06-16" -notes = "Maintained by Henri Sivonen who works at Mozilla." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.adler2]] -who = "Erich Gubler " -criteria = "safe-to-deploy" -delta = "2.0.0 -> 2.0.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.allocator-api2]] -who = "Nicolas Silva " -criteria = "safe-to-deploy" -version = "0.2.18" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.allocator-api2]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.2.20 -> 0.2.21" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.android_system_properties]] -who = "Nicolas Silva " -criteria = "safe-to-deploy" -version = "0.1.2" -notes = "I wrote this crate, reviewed by jimb. It is mostly a Rust port of some C++ code we already ship." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.android_system_properties]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.1.2 -> 0.1.4" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.android_system_properties]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.1.4 -> 0.1.5" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.bit-set]] -who = "Aria Beingessner " -criteria = "safe-to-deploy" -version = "0.5.2" -notes = "Another crate I own via contain-rs that is ancient and maintenance mode, no known issues." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.bit-set]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.5.2 -> 0.5.3" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.bit-set]] -who = "Teodor Tanasoaia " -criteria = "safe-to-deploy" -delta = "0.5.3 -> 0.6.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.bit-set]] -who = "Jim Blandy " -criteria = "safe-to-deploy" -delta = "0.6.0 -> 0.8.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.bit-vec]] -who = "Aria Beingessner " -criteria = "safe-to-deploy" -version = "0.6.3" -notes = "Another crate I own via contain-rs that is ancient and in maintenance mode but otherwise perfectly fine." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.bit-vec]] -who = "Teodor Tanasoaia " -criteria = "safe-to-deploy" -delta = "0.6.3 -> 0.7.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.bit-vec]] -who = "Jim Blandy " -criteria = "safe-to-deploy" -delta = "0.7.0 -> 0.8.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.cfg_aliases]] -who = "Alex Franchuk " -criteria = "safe-to-deploy" -delta = "0.1.1 -> 0.2.1" -notes = "Very minor changes." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.core-foundation-sys]] -who = "Erich Gubler " -criteria = "safe-to-deploy" -delta = "0.8.6 -> 0.8.7" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.crunchy]] -who = "Erich Gubler " -criteria = "safe-to-deploy" -version = "0.2.3" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.deranged]] -who = "Alex Franchuk " -criteria = "safe-to-deploy" -version = "0.3.11" -notes = """ -This crate contains a decent bit of `unsafe` code, however all internal -unsafety is verified with copious assertions (many are compile-time), and -otherwise the unsafety is documented and left to the caller to verify. -""" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.deranged]] -who = "Lars Eggert " -criteria = "safe-to-deploy" -delta = "0.3.11 -> 0.4.0" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.deranged]] -who = "Lars Eggert " -criteria = "safe-to-deploy" -delta = "0.4.0 -> 0.5.8" -notes = "New unsafe code is properly guarded" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.displaydoc]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -version = "0.2.3" -notes = """ -This crate is convenient macros to implement core::fmt::Display trait. -Although `unsafe` is used for test code to call `libc::abort()`, it has no `unsafe` code in this crate. And there is no file access. -It meets the criteria for safe-to-deploy. -""" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.displaydoc]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.2.3 -> 0.2.4" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.errno]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.3.1 -> 0.3.3" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.fastrand]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "1.9.0 -> 2.0.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.fastrand]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "2.0.1 -> 2.1.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.fastrand]] -who = "Chris Martin " -criteria = "safe-to-deploy" -delta = "2.1.0 -> 2.1.1" -notes = "Fairly trivial changes, no chance of security regression." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.fnv]] -who = "Bobby Holley " -criteria = "safe-to-deploy" -version = "1.0.7" -notes = "Simple hasher implementation with no unsafe code." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.foldhash]] -who = "Erich Gubler " -criteria = "safe-to-deploy" -delta = "0.1.5 -> 0.2.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.form_urlencoded]] -who = "Valentin Gosu " -criteria = "safe-to-deploy" -version = "1.2.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.form_urlencoded]] -who = "Valentin Gosu " -criteria = "safe-to-deploy" -delta = "1.2.0 -> 1.2.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.form_urlencoded]] -who = "edgul " -criteria = "safe-to-deploy" -delta = "1.2.1 -> 1.2.2" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.gimli]] -who = "Alex Franchuk " -criteria = "safe-to-deploy" -version = "0.30.0" -notes = """ -Unsafe code blocks are sound. Minimal dependencies used. No use of -side-effectful std functions. -""" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.gimli]] -who = "Chris Martin " -criteria = "safe-to-deploy" -delta = "0.30.0 -> 0.29.0" -notes = "No unsafe code, mostly algorithms and parsing. Very unlikely to cause security issues." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.hashbrown]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -version = "0.12.3" -notes = "This version is used in rust's libstd, so effectively we're already trusting it" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.heck]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.4.0 -> 0.4.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.hex]] -who = "Simon Friedberger " -criteria = "safe-to-deploy" -version = "0.4.3" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_collections]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0-beta2 -> 2.0.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_collections]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0 -> 2.1.1" -notes = "Adding methods have unsafe code for faster, but these have the commnet why this is safe." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_locale_core]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0-beta2 -> 2.0.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_locale_core]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0 -> 2.1.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_normalizer]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0-beta2 -> 2.0.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_normalizer]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0 -> 2.1.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_normalizer_data]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0-beta2 -> 2.0.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_normalizer_data]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0 -> 2.1.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_properties]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0-beta2 -> 2.0.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_properties]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.1 -> 2.1.2" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_properties_data]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0-beta2 -> 2.0.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_properties_data]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.1 -> 2.1.2" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_provider]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0-beta2 -> 2.0.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.icu_provider]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "2.0.0 -> 2.1.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.idna]] -who = "Valentin Gosu " -criteria = "safe-to-deploy" -delta = "0.4.0 -> 0.5.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.idna]] -who = "Henri Sivonen " -criteria = "safe-to-deploy" -delta = "0.5.0 -> 1.0.2" -notes = "In the 0.5.0 to 1.0.2 delta, I, Henri Sivonen, rewrote the non-Punycode internals of the crate and made the changes to the Punycode code." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.idna]] -who = "Valentin Gosu " -criteria = "safe-to-deploy" -delta = "1.0.2 -> 1.0.3" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.idna]] -who = "edgul " -criteria = "safe-to-deploy" -delta = "1.0.3 -> 1.1.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.idna_adapter]] -who = "Valentin Gosu " -criteria = "safe-to-deploy" -version = "1.2.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.idna_adapter]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "1.2.0 -> 1.2.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.litemap]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "0.7.5 -> 0.8.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.num-conv]] -who = "Alex Franchuk " -criteria = "safe-to-deploy" -version = "0.1.0" -notes = """ -Very straightforward, simple crate. No dependencies, unsafe, extern, -side-effectful std functions, etc. -""" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.num-conv]] -who = "Lars Eggert " -criteria = "safe-to-deploy" -delta = "0.1.0 -> 0.2.0" -notes = "Revision only removes code" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.percent-encoding]] -who = "Valentin Gosu " -criteria = "safe-to-deploy" -delta = "2.2.0 -> 2.3.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.percent-encoding]] -who = "Valentin Gosu " -criteria = "safe-to-deploy" -delta = "2.3.0 -> 2.3.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.percent-encoding]] -who = "edgul " -criteria = "safe-to-deploy" -delta = "2.3.1 -> 2.3.2" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.pin-project-lite]] -who = "Nika Layzell " -criteria = "safe-to-deploy" -delta = "0.2.14 -> 0.2.16" -notes = """ -Only functional change is to work around a bug in the negative_impls feature -(https://github.com/taiki-e/pin-project/issues/340#issuecomment-2432146009) -""" -aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.pkg-config]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.3.25 -> 0.3.26" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.potential_utf]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "0.1.2 -> 0.1.4" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.powerfmt]] -who = "Alex Franchuk " -criteria = "safe-to-deploy" -version = "0.2.0" -notes = """ -A tiny bit of unsafe code to implement functionality that isn't in stable rust -yet, but it's all valid. Otherwise it's a pretty simple crate. -""" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.proc-macro-error-attr2]] -who = "Kagami Sascha Rosylight " -criteria = "safe-to-deploy" -version = "2.0.0" -notes = "No unsafe block." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.proc-macro-error2]] -who = "Kagami Sascha Rosylight " -criteria = "safe-to-deploy" -version = "2.0.1" -notes = "No unsafe block with a lovely `#![forbid(unsafe_code)]`." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.quinn-udp]] -who = "Max Inden " -criteria = "safe-to-deploy" -version = "0.5.4" -notes = "This is a small crate, providing safe wrappers around various low-level networking specific operating system features. Given that the Rust standard library does not provide safe wrappers for these low-level features, safe wrappers need to be build in the crate itself, i.e. `quinn-udp`, thus requiring `unsafe` code." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.quinn-udp]] -who = "Max Inden " -criteria = "safe-to-deploy" -delta = "0.5.4 -> 0.5.6" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.quinn-udp]] -who = "Max Inden " -criteria = "safe-to-deploy" -delta = "0.5.6 -> 0.5.8" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.quinn-udp]] -who = "Max Inden " -criteria = "safe-to-deploy" -delta = "0.5.8 -> 0.5.9" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.quinn-udp]] -who = "Max Leonard Inden " -criteria = "safe-to-deploy" -delta = "0.5.9 -> 0.5.10" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.quinn-udp]] -who = "Max Leonard Inden " -criteria = "safe-to-deploy" -delta = "0.5.10 -> 0.5.11" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.quinn-udp]] -who = "Max Leonard Inden " -criteria = "safe-to-deploy" -delta = "0.5.11 -> 0.5.12" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.quinn-udp]] -who = "Max Leonard Inden " -criteria = "safe-to-deploy" -delta = "0.5.12 -> 0.5.13" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.rustc-hash]] -who = "Bobby Holley " -criteria = "safe-to-deploy" -version = "1.1.0" -notes = "Straightforward crate with no unsafe code, does what it says on the tin." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.rustc-hash]] -who = "Ben Dean-Kawamura " -criteria = "safe-to-deploy" -delta = "1.1.0 -> 2.1.1" -notes = "Simple hashing crate, no unsafe code." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.rustc_version]] -who = "Nika Layzell " -criteria = "safe-to-deploy" -version = "0.4.0" -notes = """ -Use of powerful capabilities is limited to invoking `rustc -vV` to get version -information for parsing version information. -""" -aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.serde_core]] -who = "Erich Gubler " -criteria = "safe-to-deploy" -delta = "1.0.226 -> 1.0.227" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.serde_core]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -delta = "1.0.227 -> 1.0.228" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.serde_spanned]] -who = "Ben Dean-Kawamura " -criteria = "safe-to-deploy" -version = "1.0.3" -notes = "Relatively simple Serde trait implementations. No IO or unsafe code." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.serde_spanned]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -delta = "1.0.3 -> 1.0.4" -notes = "Unchanged" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.sha2]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.10.2 -> 0.10.6" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.sha2]] -who = "Jeff Muizelaar " -criteria = "safe-to-deploy" -delta = "0.10.6 -> 0.10.8" -notes = """ -The bulk of this is https://github.com/RustCrypto/hashes/pull/490 which adds aarch64 support along with another PR adding longson. -I didn't check the implementation thoroughly but there wasn't anything obviously nefarious. 0.10.8 has been out for more than a year -which suggests no one else has found anything either. -""" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.sharded-slab]] -who = "Mark Hammond " -criteria = "safe-to-deploy" -delta = "0.1.4 -> 0.1.7" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.shlex]] -who = "Max Inden " -criteria = "safe-to-deploy" -delta = "1.1.0 -> 1.3.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.similar]] -who = "Nika Layzell " -criteria = "safe-to-deploy" -delta = "2.2.1 -> 2.7.0" -aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.smallvec]] -who = "Erich Gubler " -criteria = "safe-to-deploy" -delta = "1.14.0 -> 1.15.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.strsim]] -who = "Ben Dean-Kawamura " -criteria = "safe-to-deploy" -delta = "0.10.0 -> 0.11.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.strum]] -who = "Teodor Tanasoaia " -criteria = "safe-to-deploy" -delta = "0.25.0 -> 0.26.3" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.strum]] -who = "Erich Gubler " -criteria = "safe-to-deploy" -delta = "0.26.3 -> 0.27.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.strum_macros]] -who = "Teodor Tanasoaia " -criteria = "safe-to-deploy" -delta = "0.25.3 -> 0.26.4" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.strum_macros]] -who = "Erich Gubler " -criteria = "safe-to-deploy" -delta = "0.26.4 -> 0.27.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.subtle]] -who = "Simon Friedberger " -criteria = "safe-to-deploy" -version = "2.5.0" -notes = "The goal is to provide some constant-time correctness for cryptographic implementations. The approach is reasonable, it is known to be insufficient but this is pointed out in the documentation." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.synstructure]] -who = "Nika Layzell " -criteria = "safe-to-deploy" -version = "0.12.6" -notes = """ -I am the primary author of the `synstructure` crate, and its current -maintainer. The one use of `unsafe` is unnecessary, but documented and -harmless. It will be removed in the next version. -""" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.synstructure]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.12.6 -> 0.13.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.synstructure]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.13.0 -> 0.13.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.synstructure]] -who = "Nika Layzell " -criteria = "safe-to-deploy" -delta = "0.13.1 -> 0.13.2" -aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.textwrap]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -version = "0.15.0" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.textwrap]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.15.0 -> 0.15.2" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.textwrap]] -who = "Mike Hommey " -criteria = "safe-to-deploy" -delta = "0.15.2 -> 0.16.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.textwrap]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -delta = "0.16.0 -> 0.16.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.textwrap]] -who = "Nika Layzell " -criteria = "safe-to-deploy" -delta = "0.16.1 -> 0.16.2" -aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.time-core]] -who = "Kershaw Chang " -criteria = "safe-to-deploy" -version = "0.1.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.time-core]] -who = "Kershaw Chang " -criteria = "safe-to-deploy" -delta = "0.1.0 -> 0.1.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.time-core]] -who = "Alex Franchuk " -criteria = "safe-to-deploy" -delta = "0.1.1 -> 0.1.2" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.time-core]] -who = "Lars Eggert " -criteria = "safe-to-deploy" -delta = "0.1.2 -> 0.1.4" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.time-core]] -who = "Lars Eggert " -criteria = "safe-to-deploy" -delta = "0.1.4 -> 0.1.8" -notes = "No unsafe code" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.time-macros]] -who = "Kershaw Chang " -criteria = "safe-to-deploy" -version = "0.2.6" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.time-macros]] -who = "Kershaw Chang " -criteria = "safe-to-deploy" -delta = "0.2.6 -> 0.2.10" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.time-macros]] -who = "Alex Franchuk " -criteria = "safe-to-deploy" -delta = "0.2.10 -> 0.2.18" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.time-macros]] -who = "Lars Eggert " -criteria = "safe-to-deploy" -delta = "0.2.18 -> 0.2.22" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.time-macros]] -who = "Lars Eggert " -criteria = "safe-to-deploy" -delta = "0.2.22 -> 0.2.27" -notes = "Refactors some unsafe code, nothing new" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.tinyvec_macros]] -who = "Drew Willcoxon " -criteria = "safe-to-deploy" -delta = "0.1.0 -> 0.1.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.toml_datetime]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -version = "0.7.5+spec-1.1.0" -notes = "Pure data type crate with some datetime parsing. No unsafe." -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.unicode-linebreak]] -who = "Jan-Erik Rediger " -criteria = "safe-to-deploy" -version = "0.1.5" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.wasm-bindgen]] -who = "Lars Eggert " -criteria = "safe-to-deploy" -delta = "0.2.99 -> 0.2.100" -aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" - -[[audits.mozilla.audits.windows-link]] -who = "Mark Hammond " -criteria = "safe-to-deploy" -version = "0.1.1" -notes = "A microsoft crate allowing unsafe calls to windows apis." -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.windows-link]] -who = "Erich Gubler " -criteria = "safe-to-deploy" -delta = "0.1.1 -> 0.2.0" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.writeable]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "0.6.1 -> 0.6.2" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.zeroize]] -who = "Benjamin Beurdouche " -criteria = "safe-to-deploy" -version = "1.8.1" -notes = """ -This code DOES contain unsafe code required to internally call volatiles -for deleting data. This is expected and documented behavior. -""" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.zerovec-derive]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -version = "0.10.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.zerovec-derive]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "0.10.1 -> 0.10.2" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.zerovec-derive]] -who = "Max Inden " -criteria = "safe-to-deploy" -delta = "0.10.2 -> 0.10.3" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.mozilla.audits.zerovec-derive]] -who = "Makoto Kato " -criteria = "safe-to-deploy" -delta = "0.10.3 -> 0.11.1" -aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" - -[[audits.zcash.audits.autocfg]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "1.4.0 -> 1.5.0" -notes = "Filesystem change is to remove the generated LLVM IR output file after probing." -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.crunchy]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.2.3 -> 0.2.4" -notes = """ -Build script change is to fix a bug where a path separator for an included file -was being selected by the target OS instead of the host OS. -""" -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.dunce]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -version = "1.0.5" -notes = """ -Does what it says on the tin. No `unsafe`, and the only IO is `std::fs::canonicalize`. -Path and string handling looks plausibly correct. -""" -aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" - -[[audits.zcash.audits.errno]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.3.3 -> 0.3.8" -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.errno]] -who = "Daira-Emma Hopwood " -criteria = "safe-to-deploy" -delta = "0.3.8 -> 0.3.9" -aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" - -[[audits.zcash.audits.errno]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.3.10 -> 0.3.11" -notes = "The `__errno` location for vxworks and cygwin looks correct from a quick search." -aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" - -[[audits.zcash.audits.errno]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.3.11 -> 0.3.13" -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.errno]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.3.13 -> 0.3.14" -aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" - -[[audits.zcash.audits.glob]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.3.2 -> 0.3.3" -aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" - -[[audits.zcash.audits.group]] -who = "Kris Nuttycombe " -criteria = "safe-to-deploy" -delta = "0.12.0 -> 0.12.1" -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.group]] -who = "Sean Bowe " -criteria = "safe-to-deploy" -delta = "0.12.1 -> 0.13.0" -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.http-body]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "1.0.0 -> 1.0.1" -aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" - -[[audits.zcash.audits.inout]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.1.3 -> 0.1.4" -aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" - -[[audits.zcash.audits.litemap]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.8.0 -> 0.8.1" -aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" - -[[audits.zcash.audits.opaque-debug]] -who = "Daira-Emma Hopwood " -criteria = "safe-to-deploy" -delta = "0.3.0 -> 0.3.1" -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.quinn-udp]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.5.13 -> 0.5.14" -aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" - -[[audits.zcash.audits.rustc_version]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.4.0 -> 0.4.1" -notes = "Changes to `Command` usage are to add support for `RUSTC_WRAPPER`." -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.rustversion]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "1.0.20 -> 1.0.21" -notes = "Build script change is to fix building with `-Zfmt-debug=none`." -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.rustversion]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "1.0.21 -> 1.0.22" -notes = "Changes to generated code are to prepend a clippy annotation." -aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" - -[[audits.zcash.audits.signature]] -who = "Daira Emma Hopwood " -criteria = "safe-to-deploy" -version = "2.1.0" -notes = """ -This crate uses `#![forbid(unsafe_code)]`, has no build script, and only provides traits with some trivial default implementations. -I did not review whether implementing these APIs would present any undocumented cryptographic hazards. -""" -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.signature]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "2.1.0 -> 2.2.0" -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.strum]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.27.1 -> 0.27.2" -aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" - -[[audits.zcash.audits.strum_macros]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.27.1 -> 0.27.2" -aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" - -[[audits.zcash.audits.try-lock]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.2.4 -> 0.2.5" -notes = "Bumps MSRV to remove unsafe code block." -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.universal-hash]] -who = "Daira Hopwood " -criteria = "safe-to-deploy" -delta = "0.4.1 -> 0.5.0" -notes = "I checked correctness of to_blocks which uses unsafe code in a safe function." -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.valuable]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.1.0 -> 0.1.1" -notes = "Build script changes are for linting." -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.want]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.3.0 -> 0.3.1" -notes = """ -Migrates to `try-lock 0.2.4` to replace some unsafe APIs that were not marked -`unsafe` (but that were being used safely). -""" -aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" - -[[audits.zcash.audits.windows-link]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.2.0 -> 0.2.1" -notes = "No code changes at all." -aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" - -[[audits.zcash.audits.yoke-derive]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.8.0 -> 0.8.1" -notes = """ -Changes to generated `unsafe` code are to silence the `clippy::mem_forget` lint; -no actual code changes. -""" -aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" - -[[audits.zcash.audits.zeroize]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "1.8.1 -> 1.8.2" -notes = """ -Changes to `unsafe` code are to alter how `core::mem::size_of` is named; no actual changes -to the `unsafe` logic. -""" -aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" - -[[audits.zcash.audits.zerovec-derive]] -who = "Jack Grigg " -criteria = "safe-to-deploy" -delta = "0.11.1 -> 0.11.2" -notes = "Only changes to generated code are clippy lints." -aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" + +# cargo-vet imports lock + +[[publisher.addr2line]] +version = "0.25.1" +when = "2025-09-13" +user-id = 4415 +user-login = "philipc" +user-name = "Philip Craig" + +[[publisher.aho-corasick]] +version = "1.1.4" +when = "2025-10-28" +user-id = 189 +user-login = "BurntSushi" +user-name = "Andrew Gallant" + +[[publisher.anyhow]] +version = "1.0.102" +when = "2026-02-20" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.async-stream]] +version = "0.3.6" +when = "2024-10-01" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.async-stream-impl]] +version = "0.3.6" +when = "2024-10-01" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.async-trait]] +version = "0.1.89" +when = "2025-08-14" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.auto_impl]] +version = "1.3.0" +when = "2025-04-09" +user-id = 3204 +user-login = "KodrAus" +user-name = "Ashley Mannix" + +[[publisher.aws-lc-rs]] +version = "1.16.1" +when = "2026-03-02" +user-id = 156764 +user-login = "justsmth" +user-name = "Justin W Smith" + +[[publisher.aws-lc-sys]] +version = "0.38.0" +when = "2026-03-02" +user-id = 156764 +user-login = "justsmth" +user-name = "Justin W Smith" + +[[publisher.backtrace]] +version = "0.3.76" +when = "2025-09-26" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.bitflags]] +version = "2.11.0" +when = "2026-02-14" +user-id = 3204 +user-login = "KodrAus" +user-name = "Ashley Mannix" + +[[publisher.bumpalo]] +version = "3.20.2" +when = "2026-02-19" +user-id = 696 +user-login = "fitzgen" +user-name = "Nick Fitzgerald" + +[[publisher.bytes]] +version = "1.11.1" +when = "2026-02-03" +user-id = 6741 +user-login = "Darksonn" +user-name = "Alice Ryhl" + +[[publisher.cmake]] +version = "0.1.57" +when = "2025-12-17" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.core-foundation-sys]] +version = "0.8.4" +when = "2023-04-03" +user-id = 5946 +user-login = "jrmuizel" +user-name = "Jeff Muizelaar" + +[[publisher.crossbeam-utils]] +version = "0.8.21" +when = "2024-12-15" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.derive_more]] +version = "2.1.1" +when = "2025-12-22" +user-id = 3797 +user-login = "JelteF" +user-name = "Jelte Fennema-Nio" + +[[publisher.derive_more-impl]] +version = "2.1.1" +when = "2025-12-22" +user-id = 3797 +user-login = "JelteF" +user-name = "Jelte Fennema-Nio" + +[[publisher.dyn-clone]] +version = "1.0.20" +when = "2025-07-27" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.ff]] +version = "0.13.1" +when = "2025-03-09" +user-id = 6289 +user-login = "str4d" +user-name = "Jack Grigg" + +[[publisher.flate2]] +version = "1.1.9" +when = "2026-02-03" +user-id = 980 +user-login = "Byron" +user-name = "Sebastian Thiel" + +[[publisher.futures]] +version = "0.3.32" +when = "2026-02-15" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.futures-channel]] +version = "0.3.32" +when = "2026-02-15" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.futures-core]] +version = "0.3.32" +when = "2026-02-15" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.futures-executor]] +version = "0.3.32" +when = "2026-02-15" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.futures-io]] +version = "0.3.32" +when = "2026-02-15" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.futures-macro]] +version = "0.3.32" +when = "2026-02-15" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.futures-sink]] +version = "0.3.32" +when = "2026-02-15" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.futures-task]] +version = "0.3.32" +when = "2026-02-15" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.futures-util]] +version = "0.3.32" +when = "2026-02-15" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.group]] +version = "0.12.0" +when = "2022-05-04" +user-id = 1244 +user-login = "ebfull" + +[[publisher.h2]] +version = "0.4.13" +when = "2026-01-05" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.hashbrown]] +version = "0.14.5" +when = "2024-04-28" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.hashbrown]] +version = "0.15.5" +when = "2025-08-07" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.hashbrown]] +version = "0.16.1" +when = "2025-11-20" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.http]] +version = "1.4.0" +when = "2025-11-24" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.http-body-util]] +version = "0.1.3" +when = "2025-03-11" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.httparse]] +version = "1.10.1" +when = "2025-03-03" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.hyper]] +version = "1.8.1" +when = "2025-11-13" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.hyper-util]] +version = "0.1.20" +when = "2026-02-02" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.id-arena]] +version = "2.3.0" +when = "2026-01-14" +user-id = 696 +user-login = "fitzgen" +user-name = "Nick Fitzgerald" + +[[publisher.indexmap]] +version = "1.9.3" +when = "2023-03-24" +user-id = 539 +user-login = "cuviper" +user-name = "Josh Stone" + +[[publisher.indexmap]] +version = "2.13.0" +when = "2026-01-07" +user-id = 539 +user-login = "cuviper" +user-name = "Josh Stone" + +[[publisher.itoa]] +version = "1.0.17" +when = "2025-12-27" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.jobserver]] +version = "0.1.34" +when = "2025-08-23" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.libc]] +version = "0.2.183" +when = "2026-03-08" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.libm]] +version = "0.2.16" +when = "2026-01-24" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.linux-raw-sys]] +version = "0.12.1" +when = "2025-12-23" +user-id = 6825 +user-login = "sunfishcode" +user-name = "Dan Gohman" + +[[publisher.lock_api]] +version = "0.4.14" +when = "2025-10-03" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.log]] +version = "0.4.29" +when = "2025-12-02" +user-id = 3204 +user-login = "KodrAus" +user-name = "Ashley Mannix" + +[[publisher.macro-string]] +version = "0.1.4" +when = "2025-03-03" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.memchr]] +version = "2.8.0" +when = "2026-02-06" +user-id = 189 +user-login = "BurntSushi" +user-name = "Andrew Gallant" + +[[publisher.mime]] +version = "0.3.17" +when = "2023-03-20" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.mio]] +version = "1.1.1" +when = "2025-12-04" +user-id = 6025 +user-login = "Thomasdezeeuw" +user-name = "Thomas de Zeeuw" + +[[publisher.num-bigint]] +version = "0.4.6" +when = "2024-06-27" +user-id = 539 +user-login = "cuviper" +user-name = "Josh Stone" + +[[publisher.num_cpus]] +version = "1.17.0" +when = "2025-05-30" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.object]] +version = "0.37.3" +when = "2025-08-13" +user-id = 4415 +user-login = "philipc" +user-name = "Philip Craig" + +[[publisher.parking_lot]] +version = "0.12.5" +when = "2025-10-03" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.parking_lot_core]] +version = "0.9.12" +when = "2025-10-03" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.paste]] +version = "1.0.15" +when = "2024-05-07" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.portable-atomic]] +version = "1.13.1" +when = "2026-01-31" +user-id = 33035 +user-login = "taiki-e" +user-name = "Taiki Endo" + +[[publisher.prettyplease]] +version = "0.2.37" +when = "2025-08-19" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.proc-macro2]] +version = "1.0.106" +when = "2026-01-21" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.prost]] +version = "0.14.3" +when = "2026-01-10" +user-id = 3959 +user-login = "LucioFranco" +user-name = "Lucio Franco" + +[[publisher.prost-build]] +version = "0.14.3" +when = "2026-01-10" +user-id = 3959 +user-login = "LucioFranco" +user-name = "Lucio Franco" + +[[publisher.prost-derive]] +version = "0.14.3" +when = "2026-01-10" +user-id = 3959 +user-login = "LucioFranco" +user-name = "Lucio Franco" + +[[publisher.prost-types]] +version = "0.14.3" +when = "2026-01-10" +user-id = 3959 +user-login = "LucioFranco" +user-name = "Lucio Franco" + +[[publisher.protoc-bin-vendored-linux-aarch_64]] +version = "3.2.0" +when = "2025-07-21" +user-id = 220 +user-login = "stepancheg" +user-name = "Stepan Koltsov" + +[[publisher.protoc-bin-vendored-linux-ppcle_64]] +version = "3.2.0" +when = "2025-07-21" +user-id = 220 +user-login = "stepancheg" +user-name = "Stepan Koltsov" + +[[publisher.protoc-bin-vendored-linux-s390_64]] +version = "3.2.0" +when = "2025-07-21" +user-id = 220 +user-login = "stepancheg" +user-name = "Stepan Koltsov" + +[[publisher.protoc-bin-vendored-linux-x86_32]] +version = "3.2.0" +when = "2025-07-21" +user-id = 220 +user-login = "stepancheg" +user-name = "Stepan Koltsov" + +[[publisher.protoc-bin-vendored-linux-x86_64]] +version = "3.2.0" +when = "2025-07-21" +user-id = 220 +user-login = "stepancheg" +user-name = "Stepan Koltsov" + +[[publisher.protoc-bin-vendored-macos-aarch_64]] +version = "3.2.0" +when = "2025-07-21" +user-id = 220 +user-login = "stepancheg" +user-name = "Stepan Koltsov" + +[[publisher.protoc-bin-vendored-macos-x86_64]] +version = "3.2.0" +when = "2025-07-21" +user-id = 220 +user-login = "stepancheg" +user-name = "Stepan Koltsov" + +[[publisher.protoc-bin-vendored-win32]] +version = "3.2.0" +when = "2025-07-21" +user-id = 220 +user-login = "stepancheg" +user-name = "Stepan Koltsov" + +[[publisher.pulldown-cmark-to-cmark]] +version = "22.0.0" +when = "2025-12-23" +user-id = 980 +user-login = "Byron" +user-name = "Sebastian Thiel" + +[[publisher.quote]] +version = "1.0.45" +when = "2026-03-03" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.ref-cast]] +version = "1.0.25" +when = "2025-09-28" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.ref-cast-impl]] +version = "1.0.25" +when = "2025-09-28" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.regex]] +version = "1.12.3" +when = "2026-02-03" +user-id = 189 +user-login = "BurntSushi" +user-name = "Andrew Gallant" + +[[publisher.regex-automata]] +version = "0.4.14" +when = "2026-02-03" +user-id = 189 +user-login = "BurntSushi" +user-name = "Andrew Gallant" + +[[publisher.regex-syntax]] +version = "0.8.10" +when = "2026-02-24" +user-id = 189 +user-login = "BurntSushi" +user-name = "Andrew Gallant" + +[[publisher.reqwest]] +version = "0.12.28" +when = "2025-12-22" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.rustc-demangle]] +version = "0.1.27" +when = "2026-01-15" +user-id = 55123 +user-login = "rust-lang-owner" + +[[publisher.rustix]] +version = "1.1.4" +when = "2026-02-22" +user-id = 6825 +user-login = "sunfishcode" +user-name = "Dan Gohman" + +[[publisher.ryu]] +version = "1.0.23" +when = "2026-02-08" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.scopeguard]] +version = "1.2.0" +when = "2023-07-17" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.serde_json]] +version = "1.0.149" +when = "2026-01-06" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.slab]] +version = "0.4.12" +when = "2026-01-31" +user-id = 6741 +user-login = "Darksonn" +user-name = "Alice Ryhl" + +[[publisher.socket2]] +version = "0.6.3" +when = "2026-03-06" +user-id = 6025 +user-login = "Thomasdezeeuw" +user-name = "Thomas de Zeeuw" + +[[publisher.syn]] +version = "1.0.109" +when = "2023-02-24" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.syn]] +version = "2.0.117" +when = "2026-02-20" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.thread_local]] +version = "1.1.9" +when = "2025-06-12" +user-id = 2915 +user-login = "Amanieu" +user-name = "Amanieu d'Antras" + +[[publisher.time]] +version = "0.3.47" +when = "2026-02-05" +user-id = 15682 +user-login = "jhpratt" +user-name = "Jacob Pratt" + +[[publisher.tinystr]] +version = "0.8.2" +when = "2025-10-28" +user-id = 1139 +user-login = "Manishearth" +user-name = "Manish Goregaokar" + +[[publisher.tokio]] +version = "1.50.0" +when = "2026-03-03" +user-id = 6741 +user-login = "Darksonn" +user-name = "Alice Ryhl" + +[[publisher.tokio-macros]] +version = "2.6.1" +when = "2026-03-02" +user-id = 6741 +user-login = "Darksonn" +user-name = "Alice Ryhl" + +[[publisher.tokio-stream]] +version = "0.1.18" +when = "2026-01-04" +user-id = 6741 +user-login = "Darksonn" +user-name = "Alice Ryhl" + +[[publisher.tokio-util]] +version = "0.7.18" +when = "2026-01-04" +user-id = 6741 +user-login = "Darksonn" +user-name = "Alice Ryhl" + +[[publisher.toml]] +version = "0.9.12+spec-1.1.0" +when = "2026-02-10" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.toml_datetime]] +version = "1.0.0+spec-1.1.0" +when = "2026-02-11" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.toml_edit]] +version = "0.25.4+spec-1.1.0" +when = "2026-03-04" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.toml_parser]] +version = "1.0.9+spec-1.1.0" +when = "2026-02-16" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.tonic]] +version = "0.14.5" +when = "2026-02-19" +user-id = 3959 +user-login = "LucioFranco" +user-name = "Lucio Franco" + +[[publisher.tonic-build]] +version = "0.14.5" +when = "2026-02-19" +user-id = 3959 +user-login = "LucioFranco" +user-name = "Lucio Franco" + +[[publisher.tonic-prost]] +version = "0.14.5" +when = "2026-02-19" +user-id = 3959 +user-login = "LucioFranco" +user-name = "Lucio Franco" + +[[publisher.tonic-prost-build]] +version = "0.14.5" +when = "2026-02-19" +user-id = 3959 +user-login = "LucioFranco" +user-name = "Lucio Franco" + +[[publisher.tower]] +version = "0.5.3" +when = "2026-01-12" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.tower-http]] +version = "0.6.8" +when = "2025-12-08" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.tower-layer]] +version = "0.3.3" +when = "2024-08-13" +user-id = 3959 +user-login = "LucioFranco" +user-name = "Lucio Franco" + +[[publisher.tower-service]] +version = "0.3.3" +when = "2024-08-13" +user-id = 3959 +user-login = "LucioFranco" +user-name = "Lucio Franco" + +[[publisher.ucd-trie]] +version = "0.1.7" +when = "2024-09-29" +user-id = 189 +user-login = "BurntSushi" +user-name = "Andrew Gallant" + +[[publisher.unicase]] +version = "2.9.0" +when = "2026-01-06" +user-id = 359 +user-login = "seanmonstar" +user-name = "Sean McArthur" + +[[publisher.unicode-ident]] +version = "1.0.24" +when = "2026-02-16" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[publisher.unicode-segmentation]] +version = "1.12.0" +when = "2024-09-13" +user-id = 1139 +user-login = "Manishearth" +user-name = "Manish Goregaokar" + +[[publisher.unicode-width]] +version = "0.1.14" +when = "2024-09-19" +user-id = 1139 +user-login = "Manishearth" +user-name = "Manish Goregaokar" + +[[publisher.unicode-width]] +version = "0.2.2" +when = "2025-10-06" +user-id = 1139 +user-login = "Manishearth" +user-name = "Manish Goregaokar" + +[[publisher.unicode-xid]] +version = "0.2.6" +when = "2024-09-19" +user-id = 1139 +user-login = "Manishearth" +user-name = "Manish Goregaokar" + +[[publisher.url]] +version = "2.5.8" +when = "2026-01-05" +user-id = 1139 +user-login = "Manishearth" +user-name = "Manish Goregaokar" + +[[publisher.utf8_iter]] +version = "1.0.4" +when = "2023-12-01" +user-id = 4484 +user-login = "hsivonen" +user-name = "Henri Sivonen" + +[[publisher.uuid]] +version = "1.22.0" +when = "2026-03-05" +user-id = 3204 +user-login = "KodrAus" +user-name = "Ashley Mannix" + +[[publisher.valuable]] +version = "0.1.0" +when = "2022-01-03" +user-id = 10 +user-login = "carllerche" +user-name = "Carl Lerche" + +[[publisher.wait-timeout]] +version = "0.2.1" +when = "2025-02-03" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + +[[publisher.wasi]] +version = "0.11.1+wasi-snapshot-preview1" +when = "2025-06-10" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + +[[publisher.wasip2]] +version = "1.0.2+wasi-0.2.9" +when = "2026-01-15" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + +[[publisher.wasip3]] +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +when = "2026-01-15" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + +[[publisher.wasm-bindgen]] +version = "0.2.99" +when = "2024-12-07" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + +[[publisher.wasm-encoder]] +version = "0.244.0" +when = "2026-01-06" +trusted-publisher = "github:bytecodealliance/wasm-tools" + +[[publisher.wasm-metadata]] +version = "0.236.0" +when = "2025-07-28" +user-id = 73222 +user-login = "wasmtime-publish" + +[[publisher.wasmparser]] +version = "0.244.0" +when = "2026-01-06" +trusted-publisher = "github:bytecodealliance/wasm-tools" + +[[publisher.windows-core]] +version = "0.62.2" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows-implement]] +version = "0.60.2" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows-interface]] +version = "0.59.3" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows-result]] +version = "0.4.1" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows-strings]] +version = "0.5.1" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows-sys]] +version = "0.52.0" +when = "2023-11-15" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows-sys]] +version = "0.59.0" +when = "2024-07-30" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows-sys]] +version = "0.60.2" +when = "2025-06-12" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows-sys]] +version = "0.61.2" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows-targets]] +version = "0.52.6" +when = "2024-07-03" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows-targets]] +version = "0.53.5" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_aarch64_gnullvm]] +version = "0.52.6" +when = "2024-07-03" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_aarch64_gnullvm]] +version = "0.53.1" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_aarch64_msvc]] +version = "0.52.6" +when = "2024-07-03" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_aarch64_msvc]] +version = "0.53.1" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_i686_gnu]] +version = "0.52.6" +when = "2024-07-03" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_i686_gnu]] +version = "0.53.1" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_i686_gnullvm]] +version = "0.52.6" +when = "2024-07-03" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_i686_gnullvm]] +version = "0.53.1" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_i686_msvc]] +version = "0.52.6" +when = "2024-07-03" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_i686_msvc]] +version = "0.53.1" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_x86_64_gnu]] +version = "0.52.6" +when = "2024-07-03" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_x86_64_gnu]] +version = "0.53.1" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_x86_64_gnullvm]] +version = "0.52.6" +when = "2024-07-03" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_x86_64_gnullvm]] +version = "0.53.1" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_x86_64_msvc]] +version = "0.52.6" +when = "2024-07-03" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.windows_x86_64_msvc]] +version = "0.53.1" +when = "2025-10-06" +user-id = 64539 +user-login = "kennykerr" +user-name = "Kenny Kerr" + +[[publisher.winnow]] +version = "0.7.15" +when = "2026-03-05" +user-id = 6743 +user-login = "epage" +user-name = "Ed Page" + +[[publisher.wit-bindgen]] +version = "0.51.0" +when = "2026-01-12" +trusted-publisher = "github:bytecodealliance/wit-bindgen" + +[[publisher.wit-bindgen-core]] +version = "0.51.0" +when = "2026-01-12" +trusted-publisher = "github:bytecodealliance/wit-bindgen" + +[[publisher.wit-bindgen-rust]] +version = "0.51.0" +when = "2026-01-12" +trusted-publisher = "github:bytecodealliance/wit-bindgen" + +[[publisher.wit-bindgen-rust-macro]] +version = "0.51.0" +when = "2026-01-12" +trusted-publisher = "github:bytecodealliance/wit-bindgen" + +[[publisher.wit-component]] +version = "0.244.0" +when = "2026-01-06" +trusted-publisher = "github:bytecodealliance/wasm-tools" + +[[publisher.wit-parser]] +version = "0.244.0" +when = "2026-01-06" +trusted-publisher = "github:bytecodealliance/wasm-tools" + +[[publisher.yoke]] +version = "0.8.1" +when = "2025-10-28" +user-id = 1139 +user-login = "Manishearth" +user-name = "Manish Goregaokar" + +[[publisher.zerocopy]] +version = "0.8.42" +when = "2026-03-09" +user-id = 7178 +user-login = "joshlf" +user-name = "Joshua Liebow-Feeser" + +[[publisher.zerocopy-derive]] +version = "0.8.42" +when = "2026-03-09" +user-id = 7178 +user-login = "joshlf" +user-name = "Joshua Liebow-Feeser" + +[[publisher.zerotrie]] +version = "0.2.3" +when = "2025-10-28" +user-id = 1139 +user-login = "Manishearth" +user-name = "Manish Goregaokar" + +[[publisher.zerovec]] +version = "0.11.5" +when = "2025-10-28" +user-id = 1139 +user-login = "Manishearth" +user-name = "Manish Goregaokar" + +[[publisher.zmij]] +version = "1.0.21" +when = "2026-02-12" +user-id = 3618 +user-login = "dtolnay" +user-name = "David Tolnay" + +[[audits.OpenDevicePartnership.audits.num_enum]] +who = "Billy Price " +criteria = "safe-to-deploy" +version = "0.7.5" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embassy-imxrt/refs/heads/main/supply-chain/audits.toml" + +[[audits.OpenDevicePartnership.audits.num_enum_derive]] +who = "Billy Price " +criteria = "safe-to-deploy" +version = "0.7.5" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embassy-imxrt/refs/heads/main/supply-chain/audits.toml" + +[[audits.OpenDevicePartnership.audits.proc-macro-error]] +who = "Jerry Xie " +criteria = "safe-to-deploy" +version = "1.0.4" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" + +[[audits.OpenDevicePartnership.audits.rand_core]] +who = "Billy Price " +criteria = "safe-to-deploy" +delta = "0.6.4 -> 0.9.5" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" + +[[audits.OpenDevicePartnership.audits.rstest]] +who = "Billy Price " +criteria = "safe-to-run" +delta = "0.22.0 -> 0.26.1" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" + +[[audits.OpenDevicePartnership.audits.rstest_macros]] +who = "Billy Price " +criteria = "safe-to-run" +delta = "0.22.0 -> 0.26.1" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" + +[[audits.OpenDevicePartnership.audits.serde]] +who = "Robert Zieba " +criteria = "safe-to-deploy" +version = "1.0.228" +notes = "Changes are mostly a reorganization of the internal module structure" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" + +[[audits.OpenDevicePartnership.audits.serde_core]] +who = "Robert Zieba " +criteria = "safe-to-deploy" +version = "1.0.226" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" + +[[audits.OpenDevicePartnership.audits.serde_derive]] +who = "Robert Zieba " +criteria = "safe-to-deploy" +version = "1.0.228" +notes = "Diff is clean-up in proc macros" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/embedded-services/refs/heads/main/supply-chain/audits.toml" + +[[audits.OpenDevicePartnership.audits.thiserror]] +who = "Felipe Balbi " +criteria = "safe-to-deploy" +version = "2.0.17" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/mcxa-pac/refs/heads/main/supply-chain/audits.toml" + +[[audits.OpenDevicePartnership.audits.thiserror-impl]] +who = "Felipe Balbi " +criteria = "safe-to-deploy" +version = "2.0.17" +aggregated-from = "https://raw.githubusercontent.com/OpenDevicePartnership/mcxa-pac/refs/heads/main/supply-chain/audits.toml" + +[[audits.bytecode-alliance.wildcard-audits.bumpalo]] +who = "Nick Fitzgerald " +criteria = "safe-to-deploy" +user-id = 696 # Nick Fitzgerald (fitzgen) +start = "2019-03-16" +end = "2026-08-21" + +[[audits.bytecode-alliance.wildcard-audits.wasip2]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2025-08-10" +end = "2026-08-21" +notes = """ +This is a Bytecode Alliance authored crate. +""" + +[[audits.bytecode-alliance.wildcard-audits.wasip3]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +user-id = 1 # Alex Crichton (alexcrichton) +start = "2025-09-10" +end = "2026-08-21" +notes = """ +This is a Bytecode Alliance authored crate. +""" + +[[audits.bytecode-alliance.wildcard-audits.wasm-encoder]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +trusted-publisher = "github:bytecodealliance/wasm-tools" +start = "2025-08-14" +end = "2027-01-08" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.wildcard-audits.wasm-metadata]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +user-id = 73222 # wasmtime-publish +start = "2023-01-01" +end = "2026-06-03" +notes = """ +The Bytecode Alliance uses the `wasmtime-publish` crates.io account to automate +publication of this crate from CI. This repository requires all PRs are reviewed +by a Bytecode Alliance maintainer and it owned by the Bytecode Alliance itself. +""" + +[[audits.bytecode-alliance.wildcard-audits.wasmparser]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +trusted-publisher = "github:bytecodealliance/wasm-tools" +start = "2025-08-14" +end = "2027-01-08" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.wildcard-audits.wit-bindgen]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +trusted-publisher = "github:bytecodealliance/wit-bindgen" +start = "2025-08-13" +end = "2027-01-08" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.wildcard-audits.wit-bindgen-core]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +trusted-publisher = "github:bytecodealliance/wit-bindgen" +start = "2025-08-13" +end = "2027-01-08" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.wildcard-audits.wit-bindgen-rust]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +trusted-publisher = "github:bytecodealliance/wit-bindgen" +start = "2025-08-13" +end = "2027-01-12" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.wildcard-audits.wit-bindgen-rust-macro]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +trusted-publisher = "github:bytecodealliance/wit-bindgen" +start = "2025-08-13" +end = "2027-01-08" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.wildcard-audits.wit-component]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +trusted-publisher = "github:bytecodealliance/wasm-tools" +start = "2025-08-14" +end = "2027-01-08" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.wildcard-audits.wit-parser]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +trusted-publisher = "github:bytecodealliance/wasm-tools" +start = "2025-08-14" +end = "2027-01-08" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.audits.adler2]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "2.0.0" +notes = "Fork of the original `adler` crate, zero unsfae code, works in `no_std`, does what it says on th tin." + +[[audits.bytecode-alliance.audits.allocator-api2]] +who = "Chris Fallin " +criteria = "safe-to-deploy" +delta = "0.2.18 -> 0.2.20" +notes = """ +The changes appear to be reasonable updates from Rust's stdlib imported into +`allocator-api2`'s copy of this code. +""" + +[[audits.bytecode-alliance.audits.atomic-waker]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "1.1.2" +notes = "Contains `unsafe` code but it's well-documented and scoped to what it's intended to be doing. Otherwise a well-focused and straightforward crate." + +[[audits.bytecode-alliance.audits.cfg-if]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "1.0.0" +notes = "I am the author of this crate." + +[[audits.bytecode-alliance.audits.cipher]] +who = "Andrew Brown " +criteria = "safe-to-deploy" +version = "0.4.4" +notes = "Most unsafe is hidden by `inout` dependency; only remaining unsafe is raw-splitting a slice and an unreachable hint. Older versions of this regularly reach ~150k daily downloads." + +[[audits.bytecode-alliance.audits.core-foundation-sys]] +who = "Dan Gohman " +criteria = "safe-to-deploy" +delta = "0.8.4 -> 0.8.6" +notes = """ +The changes here are all typical bindings updates: new functions, types, and +constants. I have not audited all the bindings for ABI conformance. +""" + +[[audits.bytecode-alliance.audits.der]] +who = "Chris Fallin " +criteria = "safe-to-deploy" +version = "0.7.10" +notes = "No unsafe code aside from transmutes for transparent newtypes." + +[[audits.bytecode-alliance.audits.displaydoc]] +who = "Nick Fitzgerald " +criteria = "safe-to-deploy" +delta = "0.2.4 -> 0.2.5" + +[[audits.bytecode-alliance.audits.encode_unicode]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.3.6 -> 1.0.0" +notes = "Lots of updates, small edits to `unsafe` code, but all as expected." + +[[audits.bytecode-alliance.audits.errno]] +who = "Dan Gohman " +criteria = "safe-to-deploy" +version = "0.3.0" +notes = "This crate uses libc and windows-sys APIs to get and set the raw OS error value." + +[[audits.bytecode-alliance.audits.errno]] +who = "Dan Gohman " +criteria = "safe-to-deploy" +delta = "0.3.0 -> 0.3.1" +notes = "Just a dependency version bump and a bug fix for redox" + +[[audits.bytecode-alliance.audits.errno]] +who = "Dan Gohman " +criteria = "safe-to-deploy" +delta = "0.3.9 -> 0.3.10" + +[[audits.bytecode-alliance.audits.fastrand]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "2.0.0 -> 2.0.1" +notes = """ +This update had a few doc updates but no otherwise-substantial source code +updates. +""" + +[[audits.bytecode-alliance.audits.fastrand]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "2.1.1 -> 2.3.0" +notes = "Minor refactoring, nothing new." + +[[audits.bytecode-alliance.audits.foldhash]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.1.3" +notes = """ +Only a minor amount of `unsafe` code in this crate related to global per-process +initialization which looks correct to me. +""" + +[[audits.bytecode-alliance.audits.gimli]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.29.0 -> 0.31.0" +notes = "Various updates here and there, nothing too major, what you'd expect from a DWARF parsing crate." + +[[audits.bytecode-alliance.audits.gimli]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.31.0 -> 0.31.1" +notes = "No fundmanetally new `unsafe` code, some small refactoring of existing code. Lots of changes in tests, not as many changes in the rest of the crate. More dwarf!" + +[[audits.bytecode-alliance.audits.gimli]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.31.1 -> 0.32.0" +notes = "Ever more DWARF to parse, but also no new `unsafe` and everything looks like gimli." + +[[audits.bytecode-alliance.audits.gimli]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.32.0 -> 0.32.3" +notes = "Ever more dwarf, it never ends! (nothing out of the ordinary)" + +[[audits.bytecode-alliance.audits.heck]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.4.0" +notes = "Contains `forbid_unsafe` and only uses `std::fmt` from the standard library. Otherwise only contains string manipulation." + +[[audits.bytecode-alliance.audits.heck]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.4.1 -> 0.5.0" +notes = "Minor changes for a `no_std` upgrade but otherwise everything looks as expected." + +[[audits.bytecode-alliance.audits.http-body]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "1.0.0-rc.2" + +[[audits.bytecode-alliance.audits.http-body]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "1.0.0-rc.2 -> 1.0.0" +notes = "Only minor changes made for a stable release." + +[[audits.bytecode-alliance.audits.iana-time-zone-haiku]] +who = "Dan Gohman " +criteria = "safe-to-deploy" +version = "0.1.2" + +[[audits.bytecode-alliance.audits.idna]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.3.0" +notes = """ +This is a crate without unsafe code or usage of the standard library. The large +size of this crate comes from the large generated unicode tables file. This +crate is broadly used throughout the ecosystem and does not contain anything +suspicious. +""" + +[[audits.bytecode-alliance.audits.inout]] +who = "Andrew Brown " +criteria = "safe-to-deploy" +version = "0.1.3" +notes = "A part of RustCrypto/utils, this crate is designed to handle unsafe buffers and carefully documents the safety concerns throughout. Older versions of this tally up to ~130k daily downloads." + +[[audits.bytecode-alliance.audits.leb128fmt]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.1.0" +notes = "Well-scoped crate do doing LEB encoding with no `unsafe` code and does what it says on the tin." + +[[audits.bytecode-alliance.audits.matchers]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.1.0" + +[[audits.bytecode-alliance.audits.matchers]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.1.0 -> 0.2.0" +notes = "Some unsafe code, but not more than before. Nothing awry." + +[[audits.bytecode-alliance.audits.miniz_oxide]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.7.1" +notes = """ +This crate is a Rust implementation of zlib compression/decompression and has +been used by default by the Rust standard library for quite some time. It's also +a default dependency of the popular `backtrace` crate for decompressing debug +information. This crate forbids unsafe code and does not otherwise access system +resources. It's originally a port of the `miniz.c` library as well, and given +its own longevity should be relatively hardened against some of the more common +compression-related issues. +""" + +[[audits.bytecode-alliance.audits.miniz_oxide]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.7.1 -> 0.8.0" +notes = "Minor updates, using new Rust features like `const`, no major changes." + +[[audits.bytecode-alliance.audits.miniz_oxide]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.8.0 -> 0.8.5" +notes = """ +Lots of small updates here and there, for example around modernizing Rust +idioms. No new `unsafe` code and everything looks like what you'd expect a +compression library to be doing. +""" + +[[audits.bytecode-alliance.audits.miniz_oxide]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.8.5 -> 0.8.9" +notes = "No new unsafe code, just refactorings." + +[[audits.bytecode-alliance.audits.nu-ansi-term]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.46.0" +notes = "one use of unsafe to call windows specific api to get console handle." + +[[audits.bytecode-alliance.audits.nu-ansi-term]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.46.0 -> 0.50.1" +notes = "Lots of stylistic/rust-related chanegs, plus new features, but nothing out of the ordrinary." + +[[audits.bytecode-alliance.audits.nu-ansi-term]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.50.1 -> 0.50.3" +notes = "CI changes, Rust changes, nothing out of the ordinary." + +[[audits.bytecode-alliance.audits.num-traits]] +who = "Andrew Brown " +criteria = "safe-to-deploy" +version = "0.2.19" +notes = "As advertised: a numeric library. The only `unsafe` is from some float-to-int conversions, which seems expected." + +[[audits.bytecode-alliance.audits.pem-rfc7468]] +who = "Chris Fallin " +criteria = "safe-to-deploy" +version = "0.7.0" +notes = "Only `unsafe` around a `from_utf8_unchecked`, and no IO." + +[[audits.bytecode-alliance.audits.percent-encoding]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "2.2.0" +notes = """ +This crate is a single-file crate that does what it says on the tin. There are +a few `unsafe` blocks related to utf-8 validation which are locally verifiable +as correct and otherwise this crate is good to go. +""" + +[[audits.bytecode-alliance.audits.pin-project-lite]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.2.13 -> 0.2.14" +notes = "No substantive changes in this update" + +[[audits.bytecode-alliance.audits.pin-utils]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.1.0" + +[[audits.bytecode-alliance.audits.pkg-config]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.3.25" +notes = "This crate shells out to the pkg-config executable, but it appears to sanitize inputs reasonably." + +[[audits.bytecode-alliance.audits.pkg-config]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.3.26 -> 0.3.29" +notes = """ +No `unsafe` additions or anything outside of the purview of the crate in this +change. +""" + +[[audits.bytecode-alliance.audits.pkg-config]] +who = "Chris Fallin " +criteria = "safe-to-deploy" +delta = "0.3.29 -> 0.3.32" + +[[audits.bytecode-alliance.audits.sharded-slab]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.1.4" +notes = "I always really enjoy reading eliza's code, she left perfect comments at every use of unsafe." + +[[audits.bytecode-alliance.audits.shlex]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "1.1.0" +notes = "Only minor `unsafe` code blocks which look valid and otherwise does what it says on the tin." + +[[audits.bytecode-alliance.audits.smallvec]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "1.13.2 -> 1.14.0" +notes = "Minor new feature, nothing out of the ordinary." + +[[audits.bytecode-alliance.audits.static_assertions]] +who = "Andrew Brown " +criteria = "safe-to-deploy" +version = "1.1.0" +notes = "No dependencies and completely a compile-time crate as advertised. Uses `unsafe` in one module as a compile-time check only: `mem::transmute` and `ptr::write` are wrapped in an impossible-to-run closure." + +[[audits.bytecode-alliance.audits.test-log]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.2.11" + +[[audits.bytecode-alliance.audits.test-log]] +who = "Alex Crichton " +criteria = "safe-to-run" +delta = "0.2.11 -> 0.2.16" +notes = "Crate implementation was moved to a `*-macros` crate, crate is very small as a result." + +[[audits.bytecode-alliance.audits.test-log]] +who = "Alex Crichton " +criteria = "safe-to-run" +delta = "0.2.16 -> 0.2.18" +notes = "Minor updates, nothing changing unsafe" + +[[audits.bytecode-alliance.audits.test-log-macros]] +who = "Alex Crichton " +criteria = "safe-to-run" +version = "0.2.16" +notes = "Simple procedural macro copied from its previous source." + +[[audits.bytecode-alliance.audits.test-log-macros]] +who = "Alex Crichton " +criteria = "safe-to-run" +delta = "0.2.16 -> 0.2.18" +notes = "Standard macro changes, nothing out of place" + +[[audits.bytecode-alliance.audits.tinyvec_macros]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.1.0" +notes = """ +This is a trivial crate which only contains a singular macro definition which is +intended to multiplex across the internal representation of a tinyvec, +presumably. This trivially doesn't contain anything bad. +""" + +[[audits.bytecode-alliance.audits.tracing-log]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +version = "0.1.3" +notes = """ +This is a standard adapter between the `log` ecosystem and the `tracing` +ecosystem. There's one `unsafe` block in this crate and it's well-scoped. +""" + +[[audits.bytecode-alliance.audits.tracing-log]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.1.3 -> 0.2.0" +notes = "Nothing out of the ordinary, a typical major version update and nothing awry." + +[[audits.bytecode-alliance.audits.try-lock]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.2.4" +notes = "Implements a concurrency primitive with atomics, and is not obviously incorrect" + +[[audits.bytecode-alliance.audits.vcpkg]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.2.15" +notes = "no build.rs, no macros, no unsafe. It reads the filesystem and makes copies of DLLs into OUT_DIR." + +[[audits.bytecode-alliance.audits.want]] +who = "Pat Hickey " +criteria = "safe-to-deploy" +version = "0.3.0" + +[[audits.bytecode-alliance.audits.wasm-metadata]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.236.0 -> 0.237.0" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.audits.wasm-metadata]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.237.0 -> 0.238.1" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.audits.wasm-metadata]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.238.1 -> 0.239.0" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.audits.wasm-metadata]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.239.0 -> 0.240.0" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.audits.wasm-metadata]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.240.0 -> 0.241.2" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.audits.wasm-metadata]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.241.2 -> 0.242.0" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.audits.wasm-metadata]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.242.0 -> 0.243.0" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.bytecode-alliance.audits.wasm-metadata]] +who = "Alex Crichton " +criteria = "safe-to-deploy" +delta = "0.243.0 -> 0.244.0" +notes = "The Bytecode Alliance is the author of this crate" + +[[audits.embark-studios.audits.cfg_aliases]] +who = "Johan Andersson " +criteria = "safe-to-deploy" +version = "0.1.1" +notes = "No unsafe usage or ambient capabilities" + +[[audits.embark-studios.audits.ident_case]] +who = "Johan Andersson " +criteria = "safe-to-deploy" +version = "1.0.1" +notes = "No unsafe usage or ambient capabilities" + +[[audits.embark-studios.audits.idna]] +who = "Johan Andersson " +criteria = "safe-to-deploy" +delta = "0.3.0 -> 0.4.0" +notes = "No unsafe usage or ambient capabilities" + +[[audits.embark-studios.audits.tap]] +who = "Johan Andersson " +criteria = "safe-to-deploy" +version = "1.0.1" +notes = "No unsafe usage or ambient capabilities" + +[[audits.google.audits.arrayvec]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "0.7.6" +notes = ''' +Grepped for `-i cipher`, `-i crypto`, `'\bfs\b'`, `'\bnet\b'` and there were +no hits, except for some `net` usage in tests. + +The crate has quite a few bits of `unsafe` Rust. The audit comments can be +found in https://chromium-review.googlesource.com/c/chromium/src/+/6187726/2 +''' +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.autocfg]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "1.4.0" +notes = "Contains no unsafe" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.base64]] +who = "amarjotgill " +criteria = "safe-to-deploy" +version = "0.22.1" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.byteorder]] +who = "danakj " +criteria = "safe-to-deploy" +version = "1.5.0" +notes = "Unsafe review in https://crrev.com/c/5838022" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.either]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "1.13.0" +notes = "Unsafe code pertaining to wrapping Pin APIs. Mostly passes invariants down." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.either]] +who = "Daniel Cheng " +criteria = "safe-to-deploy" +delta = "1.13.0 -> 1.14.0" +notes = """ +Inheriting ub-risk-1 from the baseline review of 1.13.0. While the delta has some diffs in unsafe code, they are either: +- migrating code to use helper macros +- migrating match patterns to take advantage of default bindings mode from RFC 2005 +Either way, the result is code that does exactly the same thing and does not change the risk of UB. + +See https://crrev.com/c/6323164 for more audit details. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.either]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.14.0 -> 1.15.0" +notes = 'The delta in `lib.rs` only tweaks doc comments and `#[cfg(feature = "std")]`.' +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.equivalent]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +version = "1.0.1" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.equivalent]] +who = "Jonathan Hao " +criteria = "safe-to-deploy" +delta = "1.0.1 -> 1.0.2" +notes = "No changes to any .rs files or Rust code." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.fastrand]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +version = "1.9.0" +notes = """ +`does-not-implement-crypto` is certified because this crate explicitly says +that the RNG here is not cryptographically secure. +""" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.foldhash]] +who = "Adrian Taylor " +criteria = "safe-to-deploy" +delta = "0.1.3 -> 0.1.4" +notes = "No changes to safety-relevant code" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.foldhash]] +who = "Chris Palmer " +criteria = "safe-to-deploy" +delta = "0.1.4 -> 0.1.5" +notes = "No new `unsafe`." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.glob]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +version = "0.3.1" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.glob]] +who = "Dustin J. Mitchell " +criteria = "safe-to-deploy" +delta = "0.3.1 -> 0.3.2" +notes = "Still no unsafe" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.httpdate]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +version = "1.0.3" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.icu_collections]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "2.0.0-beta1" +notes = """ +Two instances of unsafe : + - Non-safety related unsafe API that imposes additional invariants + - `from_utf8` for known-UTF8 integer + +Comments added/improved in https://github.com/unicode-org/icu4x/pull/6056. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.icu_collections]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +delta = "2.0.0-beta1 -> 2.0.0-beta2" +notes = "from_utf8 unsafe removed. no new unsafe added" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.icu_locale_core]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "2.0.0-beta2" +notes = """ +All unsafe code commented (and improved from prior version): + - A checklisted ULE impl + - from-utf8 code on known-ASCII + - Some unchecked indexing around maintained invariants +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.icu_normalizer]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "2.0.0-beta2" +notes = """ +All unsafe is unchecked `char` and `str` conversion, mostly well-commented. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.icu_normalizer_data]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "2.0.0-beta1" +notes = "Contains codegenned unsafe only, using safe Bake impls from zerovec/zerotrie" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.icu_normalizer_data]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +delta = "2.0.0-beta1 -> 2.0.0-beta2" +notes = "Contains codegenned unsafe only, using safe Bake impls from zerovec/zerotrie" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.icu_properties]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "2.0.0-beta2" +notes = "All unsafe was removed" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.icu_properties_data]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "2.0.0-beta1" +notes = "Contains codegenned unsafe only, using safe Bake impls from zerovec/zerotrie" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.icu_properties_data]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +delta = "2.0.0-beta1 -> 2.0.0-beta2" +notes = "Contains codegenned unsafe only, using safe Bake impls from zerovec/zerotrie" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.icu_provider]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "2.0.0-beta1" +notes = """ +All unsafe code commented: + - Minor unsafe transmutes between types which are identical but not type-system-provably so. + - One unsafe EqULE impl + - Some repr(transparent) transmutes + - A from_utf8_unchecked for an ascii-validated string + +Comment improvements can be found in https://github.com/unicode-org/icu4x/pull/6056 +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.icu_provider]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +delta = "2.0.0-beta1 -> 2.0.0-beta2" +notes = "from_utf8_unchecked unsafe remove, all other unsafe not meaningfully changed" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.lazy_static]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "1.4.0" +notes = ''' +I grepped for \"crypt\", \"cipher\", \"fs\", \"net\" - there were no hits. + +There are two places where `unsafe` is used. Unsafe review notes can be found +in https://crrev.com/c/5347418. + +This crate has been added to Chromium in https://crrev.com/c/3321895. +''' +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.lazy_static]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +delta = "1.4.0 -> 1.5.0" +notes = "Unsafe review notes: https://crrev.com/c/5650836" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.litemap]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "0.7.4" +notes = "Contains no unsafe" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.litemap]] +who = "Daniel Cheng " +criteria = "safe-to-deploy" +delta = "0.7.4 -> 0.7.5" +notes = "Delta implements the entry API but doesn't add or change any unsafe code." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.nom]] +who = "danakj@chromium.org" +criteria = "safe-to-deploy" +version = "7.1.3" +notes = """ +Reviewed in https://chromium-review.googlesource.com/c/chromium/src/+/5046153 +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.num-integer]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "0.1.46" +notes = "Contains no unsafe" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.num-iter]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +version = "0.1.43" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.pin-project-lite]] +who = "David Koloski " +criteria = "safe-to-deploy" +version = "0.2.9" +notes = "Reviewed on https://fxrev.dev/824504" +aggregated-from = "https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/third_party/rust_crates/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.pin-project-lite]] +who = "David Koloski " +criteria = "safe-to-deploy" +delta = "0.2.9 -> 0.2.13" +notes = "Audited at https://fxrev.dev/946396" +aggregated-from = "https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/third_party/rust_crates/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.potential_utf]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "0.1.0" +notes = "Contains a handful of lines of from-UTF8 unsafety and some `repr(transparent)` casting unsafety. Reasonably well commented, could do with listing invariants explicitly." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.potential_utf]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +delta = "0.1.0 -> 0.1.2" +notes = "Addition of safe comparison APIs since last audit" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.proc-macro-error-attr]] +who = "George Burgess IV " +criteria = "safe-to-deploy" +version = "1.0.4" +aggregated-from = "https://chromium.googlesource.com/chromiumos/third_party/rust_crates/+/refs/heads/main/cargo-vet/audits.toml?format=TEXT" + +[[audits.google.audits.rand]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "0.8.5" +notes = """ +For more detailed unsafe review notes please see https://crrev.com/c/6362797 +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rand_chacha]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "0.3.1" +notes = """ +For more detailed unsafe review notes please see https://crrev.com/c/6362797 +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rand_core]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "0.6.4" +notes = """ +For more detailed unsafe review notes please see https://crrev.com/c/6362797 +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.relative-path]] +who = "danakj " +criteria = "safe-to-deploy" +version = "1.9.3" +notes = """ +There is no net or fs usage, no crypto. +There is unsafe to convert pointers from str to RelativePath, where the latter +is a transparent wrapper around str so the pointer will be to a valid +type/value always. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rstest]] +who = "danakj@chromium.org" +criteria = "safe-to-run" +version = "0.17.0" +notes = """ +Reviewed in https://crrev.com/c/5171063 + +Previously reviewed during security review and the audit is grandparented in. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rstest]] +who = "danakj " +criteria = "safe-to-run" +delta = "0.17.0 -> 0.22.0" +notes = "No new unsafe. fs and net usage, but only in its own tests." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rstest_macros]] +who = "danakj " +criteria = "safe-to-run" +version = "0.22.0" +notes = """ +There is no fs or net usage directly, though there is fs +usage through the glob crate to get lists of files if the user +asks for it in their macro. + +There is no unsafe. Scanned through all the code. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rustversion]] +who = "Lukasz Anforowicz " +criteria = "safe-to-deploy" +version = "1.0.14" +notes = """ +Grepped for `-i cipher`, `-i crypto`, `'\bfs\b'``, `'\bnet\b'``, `'\bunsafe\b'`` +and there were no hits except for: + +* Using trivially-safe `unsafe` in test code: + + ``` + tests/test_const.rs:unsafe fn _unsafe() {} + tests/test_const.rs:const _UNSAFE: () = unsafe { _unsafe() }; + ``` + +* Using `unsafe` in a string: + + ``` + src/constfn.rs: "unsafe" => Qualifiers::Unsafe, + ``` + +* Using `std::fs` in `build/build.rs` to write `${OUT_DIR}/version.expr` + which is later read back via `include!` used in `src/lib.rs`. + +Version `1.0.6` of this crate has been added to Chromium in +https://source.chromium.org/chromium/chromium/src/+/28841c33c77833cc30b286f9ae24c97e7a8f4057 +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rustversion]] +who = "Adrian Taylor " +criteria = "safe-to-deploy" +delta = "1.0.14 -> 1.0.15" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rustversion]] +who = "danakj " +criteria = "safe-to-deploy" +delta = "1.0.15 -> 1.0.16" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rustversion]] +who = "Dustin J. Mitchell " +criteria = "safe-to-deploy" +delta = "1.0.16 -> 1.0.17" +notes = "Just updates windows compat" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rustversion]] +who = "Liza Burakova " +criteria = "safe-to-deploy" +delta = "1.0.17 -> 1.0.18" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rustversion]] +who = "Dustin J. Mitchell " +criteria = "safe-to-deploy" +delta = "1.0.18 -> 1.0.19" +notes = "No unsafe, just doc changes" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.rustversion]] +who = "Daniel Cheng " +criteria = "safe-to-deploy" +delta = "1.0.19 -> 1.0.20" +notes = "Only minor updates to documentation and the mock today used for testing." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.smallvec]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "1.13.2" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.strsim]] +who = "danakj@chromium.org" +criteria = "safe-to-deploy" +version = "0.10.0" +notes = """ +Reviewed in https://crrev.com/c/5171063 + +Previously reviewed during security review and the audit is grandparented in. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.strum]] +who = "danakj@chromium.org" +criteria = "safe-to-deploy" +version = "0.25.0" +notes = """ +Reviewed in https://crrev.com/c/5171063 + +Previously reviewed during security review and the audit is grandparented in. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.strum_macros]] +who = "danakj@chromium.org" +criteria = "safe-to-deploy" +version = "0.25.3" +notes = """ +Reviewed in https://crrev.com/c/5171063 + +Previously reviewed during security review and the audit is grandparented in. +""" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.writeable]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "0.6.0" +notes = "Contains three lines of unsafe, thoroughly commented: one is for from-UTF8 on ASCII, the other two are for from-UTF8 on a datastructure that keeps track of a buffer with partial UTF8 validation. Relatively straigtforward." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.writeable]] +who = "Daniel Cheng " +criteria = "safe-to-deploy" +delta = "0.6.0 -> 0.6.1" +notes = "Minor comment/documentation updates and switch to a non-panicking alternative to split_at()." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.yoke-derive]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "0.7.5" +notes = "Custom derive implementing the `Yokeable` trait. Generally generates simple code that asserts covariance." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.yoke-derive]] +who = "Daniel Cheng " +criteria = "safe-to-deploy" +delta = "0.7.5 -> 0.8.0" +notes = "No code changes: only incrementing the version." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.zerofrom]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "0.1.5" +notes = "Contains no unsafe" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.zerofrom]] +who = "Daniel Cheng " +criteria = "safe-to-deploy" +delta = "0.1.5 -> 0.1.6" +notes = "Only minor cfg tweaks." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.zerofrom-derive]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +version = "0.1.5" +notes = "Contains no unsafe" +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.google.audits.zerofrom-derive]] +who = "Daniel Cheng " +criteria = "safe-to-deploy" +delta = "0.1.5 -> 0.1.6" +notes = "Only a minor clippy adjustment." +aggregated-from = "https://chromium.googlesource.com/chromium/src/+/main/third_party/rust/chromium_crates_io/supply-chain/audits.toml?format=TEXT" + +[[audits.isrg.audits.cfg-if]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "1.0.0 -> 1.0.1" + +[[audits.isrg.audits.cfg-if]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "1.0.1 -> 1.0.3" + +[[audits.isrg.audits.cfg-if]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "1.0.3 -> 1.0.4" + +[[audits.isrg.audits.cpufeatures]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.2.17 -> 0.3.0" + +[[audits.isrg.audits.fiat-crypto]] +who = "David Cook " +criteria = "safe-to-deploy" +version = "0.1.17" +notes = """ +This crate does not contain any unsafe code, and does not use any items from +the standard library or other crates, aside from operations backed by +`std::ops`. All paths with array indexing use integer literals for indexes, so +there are no panics due to indexes out of bounds (as rustc would catch an +out-of-bounds literal index). I did not check whether arithmetic overflows +could cause a panic, and I am relying on the Coq code having satisfied the +necessary preconditions to ensure panics due to overflows are unreachable. +""" + +[[audits.isrg.audits.fiat-crypto]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "0.1.17 -> 0.1.18" + +[[audits.isrg.audits.fiat-crypto]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.1.18 -> 0.1.19" +notes = """ +This release renames many items and adds a new module. The code in the new +module is entirely composed of arithmetic and array accesses. +""" + +[[audits.isrg.audits.fiat-crypto]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.1.19 -> 0.1.20" + +[[audits.isrg.audits.fiat-crypto]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.1.20 -> 0.2.0" + +[[audits.isrg.audits.fiat-crypto]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "0.2.0 -> 0.2.1" + +[[audits.isrg.audits.fiat-crypto]] +who = "Tim Geoghegan " +criteria = "safe-to-deploy" +delta = "0.2.1 -> 0.2.2" +notes = "No changes to `unsafe` code, or any functional changes that I can detect at all." + +[[audits.isrg.audits.fiat-crypto]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "0.2.2 -> 0.2.4" + +[[audits.isrg.audits.fiat-crypto]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.2.4 -> 0.2.5" + +[[audits.isrg.audits.fiat-crypto]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "0.2.5 -> 0.2.6" + +[[audits.isrg.audits.fiat-crypto]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "0.2.6 -> 0.2.7" + +[[audits.isrg.audits.fiat-crypto]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.2.7 -> 0.2.8" + +[[audits.isrg.audits.fiat-crypto]] +who = "Tim Geoghegan " +criteria = "safe-to-deploy" +delta = "0.2.8 -> 0.2.9" +notes = "No changes to Rust code between 0.2.8 and 0.2.9" + +[[audits.isrg.audits.fiat-crypto]] +who = "Tim Geoghegan " +criteria = "safe-to-deploy" +delta = "0.2.9 -> 0.3.0" +notes = "The diff is huge, but that's because it introduces a wrapper around indexing into arrays which is used in many many places. There is no new unsafe code and no change to build scripts I can detect." + +[[audits.isrg.audits.hmac]] +who = "David Cook " +criteria = "safe-to-deploy" +version = "0.12.1" + +[[audits.isrg.audits.num-iter]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.1.43 -> 0.1.44" + +[[audits.isrg.audits.num-iter]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.1.44 -> 0.1.45" + +[[audits.isrg.audits.once_cell]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "1.21.3 -> 1.21.4" +notes = "The addition is a safe while loop around prior behavior. I don't see any way for that to become malicious." + +[[audits.isrg.audits.opaque-debug]] +who = "David Cook " +criteria = "safe-to-deploy" +version = "0.3.0" + +[[audits.isrg.audits.rand]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.8.5 -> 0.9.1" + +[[audits.isrg.audits.rand]] +who = "Tim Geoghegan " +criteria = "safe-to-deploy" +delta = "0.9.1 -> 0.9.2" + +[[audits.isrg.audits.rand]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.9.2 -> 0.10.0" + +[[audits.isrg.audits.rand_chacha]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.3.1 -> 0.9.0" + +[[audits.isrg.audits.rand_core]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.9.5 -> 0.10.0" + +[[audits.isrg.audits.sha2]] +who = "David Cook " +criteria = "safe-to-deploy" +version = "0.10.2" + +[[audits.isrg.audits.sha2]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.10.8 -> 0.10.9" + +[[audits.isrg.audits.sha3]] +who = "David Cook " +criteria = "safe-to-deploy" +version = "0.10.6" + +[[audits.isrg.audits.sha3]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "0.10.6 -> 0.10.7" + +[[audits.isrg.audits.sha3]] +who = "Brandon Pitman " +criteria = "safe-to-deploy" +delta = "0.10.7 -> 0.10.8" + +[[audits.isrg.audits.subtle]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "2.5.0 -> 2.6.1" + +[[audits.isrg.audits.thiserror]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "2.0.17 -> 2.0.18" + +[[audits.isrg.audits.thiserror-impl]] +who = "J.C. Jones " +criteria = "safe-to-deploy" +delta = "2.0.17 -> 2.0.18" + +[[audits.isrg.audits.universal-hash]] +who = "David Cook " +criteria = "safe-to-deploy" +version = "0.4.1" + +[[audits.isrg.audits.universal-hash]] +who = "David Cook " +criteria = "safe-to-deploy" +delta = "0.5.0 -> 0.5.1" + +[[audits.isrg.audits.untrusted]] +who = "David Cook " +criteria = "safe-to-deploy" +version = "0.7.1" + +[[audits.mozilla.wildcard-audits.core-foundation-sys]] +who = "Bobby Holley " +criteria = "safe-to-deploy" +user-id = 5946 # Jeff Muizelaar (jrmuizel) +start = "2020-10-14" +end = "2023-05-04" +renew = false +notes = "I've reviewed every source contribution that was neither authored nor reviewed by Mozilla." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.wildcard-audits.unicode-segmentation]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +user-id = 1139 # Manish Goregaokar (Manishearth) +start = "2019-05-15" +end = "2026-02-01" +notes = "All code written or reviewed by Manish" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.wildcard-audits.unicode-width]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +user-id = 1139 # Manish Goregaokar (Manishearth) +start = "2019-12-05" +end = "2026-02-01" +notes = "All code written or reviewed by Manish" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.wildcard-audits.unicode-xid]] +who = "Manish Goregaokar " +criteria = "safe-to-deploy" +user-id = 1139 # Manish Goregaokar (Manishearth) +start = "2019-07-25" +end = "2026-02-01" +notes = "All code written or reviewed by Manish" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.wildcard-audits.utf8_iter]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +user-id = 4484 # Henri Sivonen (hsivonen) +start = "2022-04-19" +end = "2024-06-16" +notes = "Maintained by Henri Sivonen who works at Mozilla." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.adler2]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "2.0.0 -> 2.0.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.allocator-api2]] +who = "Nicolas Silva " +criteria = "safe-to-deploy" +version = "0.2.18" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.allocator-api2]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.2.20 -> 0.2.21" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.android_system_properties]] +who = "Nicolas Silva " +criteria = "safe-to-deploy" +version = "0.1.2" +notes = "I wrote this crate, reviewed by jimb. It is mostly a Rust port of some C++ code we already ship." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.android_system_properties]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.1.2 -> 0.1.4" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.android_system_properties]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.1.4 -> 0.1.5" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-set]] +who = "Aria Beingessner " +criteria = "safe-to-deploy" +version = "0.5.2" +notes = "Another crate I own via contain-rs that is ancient and maintenance mode, no known issues." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-set]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.5.2 -> 0.5.3" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-set]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.5.3 -> 0.6.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-set]] +who = "Jim Blandy " +criteria = "safe-to-deploy" +delta = "0.6.0 -> 0.8.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-vec]] +who = "Aria Beingessner " +criteria = "safe-to-deploy" +version = "0.6.3" +notes = "Another crate I own via contain-rs that is ancient and in maintenance mode but otherwise perfectly fine." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-vec]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.6.3 -> 0.7.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.bit-vec]] +who = "Jim Blandy " +criteria = "safe-to-deploy" +delta = "0.7.0 -> 0.8.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.cfg_aliases]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +delta = "0.1.1 -> 0.2.1" +notes = "Very minor changes." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.core-foundation-sys]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "0.8.6 -> 0.8.7" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.crunchy]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +version = "0.2.3" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.deranged]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +version = "0.3.11" +notes = """ +This crate contains a decent bit of `unsafe` code, however all internal +unsafety is verified with copious assertions (many are compile-time), and +otherwise the unsafety is documented and left to the caller to verify. +""" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.deranged]] +who = "Lars Eggert " +criteria = "safe-to-deploy" +delta = "0.3.11 -> 0.4.0" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.deranged]] +who = "Lars Eggert " +criteria = "safe-to-deploy" +delta = "0.4.0 -> 0.5.8" +notes = "New unsafe code is properly guarded" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.displaydoc]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +version = "0.2.3" +notes = """ +This crate is convenient macros to implement core::fmt::Display trait. +Although `unsafe` is used for test code to call `libc::abort()`, it has no `unsafe` code in this crate. And there is no file access. +It meets the criteria for safe-to-deploy. +""" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.displaydoc]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.2.3 -> 0.2.4" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.errno]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.3.1 -> 0.3.3" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.fastrand]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "1.9.0 -> 2.0.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.fastrand]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "2.0.1 -> 2.1.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.fastrand]] +who = "Chris Martin " +criteria = "safe-to-deploy" +delta = "2.1.0 -> 2.1.1" +notes = "Fairly trivial changes, no chance of security regression." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.fnv]] +who = "Bobby Holley " +criteria = "safe-to-deploy" +version = "1.0.7" +notes = "Simple hasher implementation with no unsafe code." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.foldhash]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "0.1.5 -> 0.2.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.form_urlencoded]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +version = "1.2.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.form_urlencoded]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +delta = "1.2.0 -> 1.2.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.form_urlencoded]] +who = "edgul " +criteria = "safe-to-deploy" +delta = "1.2.1 -> 1.2.2" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.gimli]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +version = "0.30.0" +notes = """ +Unsafe code blocks are sound. Minimal dependencies used. No use of +side-effectful std functions. +""" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.gimli]] +who = "Chris Martin " +criteria = "safe-to-deploy" +delta = "0.30.0 -> 0.29.0" +notes = "No unsafe code, mostly algorithms and parsing. Very unlikely to cause security issues." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.hashbrown]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +version = "0.12.3" +notes = "This version is used in rust's libstd, so effectively we're already trusting it" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.heck]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.4.0 -> 0.4.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.hex]] +who = "Simon Friedberger " +criteria = "safe-to-deploy" +version = "0.4.3" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_collections]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0-beta2 -> 2.0.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_collections]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0 -> 2.1.1" +notes = "Adding methods have unsafe code for faster, but these have the commnet why this is safe." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_locale_core]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0-beta2 -> 2.0.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_locale_core]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0 -> 2.1.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_normalizer]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0-beta2 -> 2.0.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_normalizer]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0 -> 2.1.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_normalizer_data]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0-beta2 -> 2.0.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_normalizer_data]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0 -> 2.1.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_properties]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0-beta2 -> 2.0.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_properties]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.1 -> 2.1.2" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_properties_data]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0-beta2 -> 2.0.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_properties_data]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.1 -> 2.1.2" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_provider]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0-beta2 -> 2.0.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.icu_provider]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "2.0.0 -> 2.1.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.idna]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +delta = "0.4.0 -> 0.5.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.idna]] +who = "Henri Sivonen " +criteria = "safe-to-deploy" +delta = "0.5.0 -> 1.0.2" +notes = "In the 0.5.0 to 1.0.2 delta, I, Henri Sivonen, rewrote the non-Punycode internals of the crate and made the changes to the Punycode code." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.idna]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +delta = "1.0.2 -> 1.0.3" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.idna]] +who = "edgul " +criteria = "safe-to-deploy" +delta = "1.0.3 -> 1.1.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.idna_adapter]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +version = "1.2.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.idna_adapter]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "1.2.0 -> 1.2.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.litemap]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "0.7.5 -> 0.8.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.num-conv]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +version = "0.1.0" +notes = """ +Very straightforward, simple crate. No dependencies, unsafe, extern, +side-effectful std functions, etc. +""" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.num-conv]] +who = "Lars Eggert " +criteria = "safe-to-deploy" +delta = "0.1.0 -> 0.2.0" +notes = "Revision only removes code" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.percent-encoding]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +delta = "2.2.0 -> 2.3.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.percent-encoding]] +who = "Valentin Gosu " +criteria = "safe-to-deploy" +delta = "2.3.0 -> 2.3.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.percent-encoding]] +who = "edgul " +criteria = "safe-to-deploy" +delta = "2.3.1 -> 2.3.2" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.pin-project-lite]] +who = "Nika Layzell " +criteria = "safe-to-deploy" +delta = "0.2.14 -> 0.2.16" +notes = """ +Only functional change is to work around a bug in the negative_impls feature +(https://github.com/taiki-e/pin-project/issues/340#issuecomment-2432146009) +""" +aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.pkg-config]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.3.25 -> 0.3.26" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.potential_utf]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "0.1.2 -> 0.1.4" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.powerfmt]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +version = "0.2.0" +notes = """ +A tiny bit of unsafe code to implement functionality that isn't in stable rust +yet, but it's all valid. Otherwise it's a pretty simple crate. +""" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.proc-macro-error-attr2]] +who = "Kagami Sascha Rosylight " +criteria = "safe-to-deploy" +version = "2.0.0" +notes = "No unsafe block." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.proc-macro-error2]] +who = "Kagami Sascha Rosylight " +criteria = "safe-to-deploy" +version = "2.0.1" +notes = "No unsafe block with a lovely `#![forbid(unsafe_code)]`." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.quinn-udp]] +who = "Max Inden " +criteria = "safe-to-deploy" +version = "0.5.4" +notes = "This is a small crate, providing safe wrappers around various low-level networking specific operating system features. Given that the Rust standard library does not provide safe wrappers for these low-level features, safe wrappers need to be build in the crate itself, i.e. `quinn-udp`, thus requiring `unsafe` code." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.quinn-udp]] +who = "Max Inden " +criteria = "safe-to-deploy" +delta = "0.5.4 -> 0.5.6" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.quinn-udp]] +who = "Max Inden " +criteria = "safe-to-deploy" +delta = "0.5.6 -> 0.5.8" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.quinn-udp]] +who = "Max Inden " +criteria = "safe-to-deploy" +delta = "0.5.8 -> 0.5.9" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.quinn-udp]] +who = "Max Leonard Inden " +criteria = "safe-to-deploy" +delta = "0.5.9 -> 0.5.10" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.quinn-udp]] +who = "Max Leonard Inden " +criteria = "safe-to-deploy" +delta = "0.5.10 -> 0.5.11" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.quinn-udp]] +who = "Max Leonard Inden " +criteria = "safe-to-deploy" +delta = "0.5.11 -> 0.5.12" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.quinn-udp]] +who = "Max Leonard Inden " +criteria = "safe-to-deploy" +delta = "0.5.12 -> 0.5.13" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.rustc-hash]] +who = "Bobby Holley " +criteria = "safe-to-deploy" +version = "1.1.0" +notes = "Straightforward crate with no unsafe code, does what it says on the tin." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.rustc-hash]] +who = "Ben Dean-Kawamura " +criteria = "safe-to-deploy" +delta = "1.1.0 -> 2.1.1" +notes = "Simple hashing crate, no unsafe code." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.rustc_version]] +who = "Nika Layzell " +criteria = "safe-to-deploy" +version = "0.4.0" +notes = """ +Use of powerful capabilities is limited to invoking `rustc -vV` to get version +information for parsing version information. +""" +aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.serde_core]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "1.0.226 -> 1.0.227" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.serde_core]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "1.0.227 -> 1.0.228" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.serde_spanned]] +who = "Ben Dean-Kawamura " +criteria = "safe-to-deploy" +version = "1.0.3" +notes = "Relatively simple Serde trait implementations. No IO or unsafe code." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.serde_spanned]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "1.0.3 -> 1.0.4" +notes = "Unchanged" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.sha2]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.10.2 -> 0.10.6" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.sha2]] +who = "Jeff Muizelaar " +criteria = "safe-to-deploy" +delta = "0.10.6 -> 0.10.8" +notes = """ +The bulk of this is https://github.com/RustCrypto/hashes/pull/490 which adds aarch64 support along with another PR adding longson. +I didn't check the implementation thoroughly but there wasn't anything obviously nefarious. 0.10.8 has been out for more than a year +which suggests no one else has found anything either. +""" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.sharded-slab]] +who = "Mark Hammond " +criteria = "safe-to-deploy" +delta = "0.1.4 -> 0.1.7" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.shlex]] +who = "Max Inden " +criteria = "safe-to-deploy" +delta = "1.1.0 -> 1.3.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.similar]] +who = "Nika Layzell " +criteria = "safe-to-deploy" +delta = "2.2.1 -> 2.7.0" +aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.smallvec]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "1.14.0 -> 1.15.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.strsim]] +who = "Ben Dean-Kawamura " +criteria = "safe-to-deploy" +delta = "0.10.0 -> 0.11.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.strum]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.25.0 -> 0.26.3" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.strum]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "0.26.3 -> 0.27.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.strum_macros]] +who = "Teodor Tanasoaia " +criteria = "safe-to-deploy" +delta = "0.25.3 -> 0.26.4" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.strum_macros]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "0.26.4 -> 0.27.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.subtle]] +who = "Simon Friedberger " +criteria = "safe-to-deploy" +version = "2.5.0" +notes = "The goal is to provide some constant-time correctness for cryptographic implementations. The approach is reasonable, it is known to be insufficient but this is pointed out in the documentation." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.synstructure]] +who = "Nika Layzell " +criteria = "safe-to-deploy" +version = "0.12.6" +notes = """ +I am the primary author of the `synstructure` crate, and its current +maintainer. The one use of `unsafe` is unnecessary, but documented and +harmless. It will be removed in the next version. +""" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.synstructure]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.12.6 -> 0.13.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.synstructure]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.13.0 -> 0.13.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.synstructure]] +who = "Nika Layzell " +criteria = "safe-to-deploy" +delta = "0.13.1 -> 0.13.2" +aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.textwrap]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +version = "0.15.0" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.textwrap]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.15.0 -> 0.15.2" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.textwrap]] +who = "Mike Hommey " +criteria = "safe-to-deploy" +delta = "0.15.2 -> 0.16.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.textwrap]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +delta = "0.16.0 -> 0.16.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.textwrap]] +who = "Nika Layzell " +criteria = "safe-to-deploy" +delta = "0.16.1 -> 0.16.2" +aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.time-core]] +who = "Kershaw Chang " +criteria = "safe-to-deploy" +version = "0.1.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.time-core]] +who = "Kershaw Chang " +criteria = "safe-to-deploy" +delta = "0.1.0 -> 0.1.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.time-core]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +delta = "0.1.1 -> 0.1.2" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.time-core]] +who = "Lars Eggert " +criteria = "safe-to-deploy" +delta = "0.1.2 -> 0.1.4" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.time-core]] +who = "Lars Eggert " +criteria = "safe-to-deploy" +delta = "0.1.4 -> 0.1.8" +notes = "No unsafe code" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.time-macros]] +who = "Kershaw Chang " +criteria = "safe-to-deploy" +version = "0.2.6" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.time-macros]] +who = "Kershaw Chang " +criteria = "safe-to-deploy" +delta = "0.2.6 -> 0.2.10" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.time-macros]] +who = "Alex Franchuk " +criteria = "safe-to-deploy" +delta = "0.2.10 -> 0.2.18" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.time-macros]] +who = "Lars Eggert " +criteria = "safe-to-deploy" +delta = "0.2.18 -> 0.2.22" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.time-macros]] +who = "Lars Eggert " +criteria = "safe-to-deploy" +delta = "0.2.22 -> 0.2.27" +notes = "Refactors some unsafe code, nothing new" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.tinyvec_macros]] +who = "Drew Willcoxon " +criteria = "safe-to-deploy" +delta = "0.1.0 -> 0.1.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.toml_datetime]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +version = "0.7.5+spec-1.1.0" +notes = "Pure data type crate with some datetime parsing. No unsafe." +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.unicode-linebreak]] +who = "Jan-Erik Rediger " +criteria = "safe-to-deploy" +version = "0.1.5" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.wasm-bindgen]] +who = "Lars Eggert " +criteria = "safe-to-deploy" +delta = "0.2.99 -> 0.2.100" +aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml" + +[[audits.mozilla.audits.windows-link]] +who = "Mark Hammond " +criteria = "safe-to-deploy" +version = "0.1.1" +notes = "A microsoft crate allowing unsafe calls to windows apis." +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.windows-link]] +who = "Erich Gubler " +criteria = "safe-to-deploy" +delta = "0.1.1 -> 0.2.0" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.writeable]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "0.6.1 -> 0.6.2" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.zeroize]] +who = "Benjamin Beurdouche " +criteria = "safe-to-deploy" +version = "1.8.1" +notes = """ +This code DOES contain unsafe code required to internally call volatiles +for deleting data. This is expected and documented behavior. +""" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.zerovec-derive]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +version = "0.10.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.zerovec-derive]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "0.10.1 -> 0.10.2" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.zerovec-derive]] +who = "Max Inden " +criteria = "safe-to-deploy" +delta = "0.10.2 -> 0.10.3" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.mozilla.audits.zerovec-derive]] +who = "Makoto Kato " +criteria = "safe-to-deploy" +delta = "0.10.3 -> 0.11.1" +aggregated-from = "https://hg.mozilla.org/mozilla-central/raw-file/tip/supply-chain/audits.toml" + +[[audits.zcash.audits.autocfg]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.4.0 -> 1.5.0" +notes = "Filesystem change is to remove the generated LLVM IR output file after probing." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.crunchy]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.2.3 -> 0.2.4" +notes = """ +Build script change is to fix a bug where a path separator for an included file +was being selected by the target OS instead of the host OS. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.dunce]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +version = "1.0.5" +notes = """ +Does what it says on the tin. No `unsafe`, and the only IO is `std::fs::canonicalize`. +Path and string handling looks plausibly correct. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.3 -> 0.3.8" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Daira-Emma Hopwood " +criteria = "safe-to-deploy" +delta = "0.3.8 -> 0.3.9" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.10 -> 0.3.11" +notes = "The `__errno` location for vxworks and cygwin looks correct from a quick search." +aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.11 -> 0.3.13" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.errno]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.13 -> 0.3.14" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.glob]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.2 -> 0.3.3" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.group]] +who = "Kris Nuttycombe " +criteria = "safe-to-deploy" +delta = "0.12.0 -> 0.12.1" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.group]] +who = "Sean Bowe " +criteria = "safe-to-deploy" +delta = "0.12.1 -> 0.13.0" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.http-body]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.0.0 -> 1.0.1" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.inout]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.1.3 -> 0.1.4" +aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" + +[[audits.zcash.audits.litemap]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.8.0 -> 0.8.1" +aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" + +[[audits.zcash.audits.opaque-debug]] +who = "Daira-Emma Hopwood " +criteria = "safe-to-deploy" +delta = "0.3.0 -> 0.3.1" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.quinn-udp]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.5.13 -> 0.5.14" +aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" + +[[audits.zcash.audits.rustc_version]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.4.0 -> 0.4.1" +notes = "Changes to `Command` usage are to add support for `RUSTC_WRAPPER`." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.rustversion]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.0.20 -> 1.0.21" +notes = "Build script change is to fix building with `-Zfmt-debug=none`." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.rustversion]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.0.21 -> 1.0.22" +notes = "Changes to generated code are to prepend a clippy annotation." +aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" + +[[audits.zcash.audits.signature]] +who = "Daira Emma Hopwood " +criteria = "safe-to-deploy" +version = "2.1.0" +notes = """ +This crate uses `#![forbid(unsafe_code)]`, has no build script, and only provides traits with some trivial default implementations. +I did not review whether implementing these APIs would present any undocumented cryptographic hazards. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.signature]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "2.1.0 -> 2.2.0" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.strum]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.27.1 -> 0.27.2" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.strum_macros]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.27.1 -> 0.27.2" +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.try-lock]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.2.4 -> 0.2.5" +notes = "Bumps MSRV to remove unsafe code block." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.universal-hash]] +who = "Daira Hopwood " +criteria = "safe-to-deploy" +delta = "0.4.1 -> 0.5.0" +notes = "I checked correctness of to_blocks which uses unsafe code in a safe function." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.valuable]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.1.0 -> 0.1.1" +notes = "Build script changes are for linting." +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.want]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.3.0 -> 0.3.1" +notes = """ +Migrates to `try-lock 0.2.4` to replace some unsafe APIs that were not marked +`unsafe` (but that were being used safely). +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/zcash/master/qa/supply-chain/audits.toml" + +[[audits.zcash.audits.windows-link]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.2.0 -> 0.2.1" +notes = "No code changes at all." +aggregated-from = "https://raw.githubusercontent.com/zcash/librustzcash/main/supply-chain/audits.toml" + +[[audits.zcash.audits.yoke-derive]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.8.0 -> 0.8.1" +notes = """ +Changes to generated `unsafe` code are to silence the `clippy::mem_forget` lint; +no actual code changes. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" + +[[audits.zcash.audits.zeroize]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "1.8.1 -> 1.8.2" +notes = """ +Changes to `unsafe` code are to alter how `core::mem::size_of` is named; no actual changes +to the `unsafe` logic. +""" +aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" + +[[audits.zcash.audits.zerovec-derive]] +who = "Jack Grigg " +criteria = "safe-to-deploy" +delta = "0.11.1 -> 0.11.2" +notes = "Only changes to generated code are clippy lints." +aggregated-from = "https://raw.githubusercontent.com/zcash/wallet/main/supply-chain/audits.toml" diff --git a/useragent/.gitignore b/useragent/.gitignore index 3820a95..6f0d006 100644 --- a/useragent/.gitignore +++ b/useragent/.gitignore @@ -1,45 +1,45 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/useragent/.metadata b/useragent/.metadata index 63668b8..0cbde92 100644 --- a/useragent/.metadata +++ b/useragent/.metadata @@ -1,39 +1,39 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "67323de285b00232883f53b84095eb72be97d35c" - channel: "stable" - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: 67323de285b00232883f53b84095eb72be97d35c - base_revision: 67323de285b00232883f53b84095eb72be97d35c - - platform: android - create_revision: 67323de285b00232883f53b84095eb72be97d35c - base_revision: 67323de285b00232883f53b84095eb72be97d35c - - platform: macos - create_revision: 67323de285b00232883f53b84095eb72be97d35c - base_revision: 67323de285b00232883f53b84095eb72be97d35c - - platform: web - create_revision: 67323de285b00232883f53b84095eb72be97d35c - base_revision: 67323de285b00232883f53b84095eb72be97d35c - - platform: windows - create_revision: 67323de285b00232883f53b84095eb72be97d35c - base_revision: 67323de285b00232883f53b84095eb72be97d35c - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "67323de285b00232883f53b84095eb72be97d35c" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 67323de285b00232883f53b84095eb72be97d35c + base_revision: 67323de285b00232883f53b84095eb72be97d35c + - platform: android + create_revision: 67323de285b00232883f53b84095eb72be97d35c + base_revision: 67323de285b00232883f53b84095eb72be97d35c + - platform: macos + create_revision: 67323de285b00232883f53b84095eb72be97d35c + base_revision: 67323de285b00232883f53b84095eb72be97d35c + - platform: web + create_revision: 67323de285b00232883f53b84095eb72be97d35c + base_revision: 67323de285b00232883f53b84095eb72be97d35c + - platform: windows + create_revision: 67323de285b00232883f53b84095eb72be97d35c + base_revision: 67323de285b00232883f53b84095eb72be97d35c + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/useragent/README.md b/useragent/README.md index cfb1511..70de8d7 100644 --- a/useragent/README.md +++ b/useragent/README.md @@ -1,16 +1,16 @@ -# useragent - -A new Flutter project. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +# useragent + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/useragent/analysis_options.yaml b/useragent/analysis_options.yaml index 0d29021..d4e0f0c 100644 --- a/useragent/analysis_options.yaml +++ b/useragent/analysis_options.yaml @@ -1,28 +1,28 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/useragent/android/.gitignore b/useragent/android/.gitignore index be3943c..c908258 100644 --- a/useragent/android/.gitignore +++ b/useragent/android/.gitignore @@ -1,14 +1,14 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java -.cxx/ - -# Remember to never publicly share your keystore. -# See https://flutter.dev/to/reference-keystore -key.properties -**/*.keystore -**/*.jks +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java +.cxx/ + +# Remember to never publicly share your keystore. +# See https://flutter.dev/to/reference-keystore +key.properties +**/*.keystore +**/*.jks diff --git a/useragent/android/app/build.gradle.kts b/useragent/android/app/build.gradle.kts index 3199895..9923697 100644 --- a/useragent/android/app/build.gradle.kts +++ b/useragent/android/app/build.gradle.kts @@ -1,44 +1,44 @@ -plugins { - id("com.android.application") - id("kotlin-android") - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id("dev.flutter.flutter-gradle-plugin") -} - -android { - namespace = "com.example.useragent" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.example.useragent" - // You can update the following values to match your application needs. - // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode = flutter.versionCode - versionName = flutter.versionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.getByName("debug") - } - } -} - -flutter { - source = "../.." -} +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.example.useragent" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.example.useragent" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/useragent/android/app/src/debug/AndroidManifest.xml b/useragent/android/app/src/debug/AndroidManifest.xml index 399f698..8ffe024 100644 --- a/useragent/android/app/src/debug/AndroidManifest.xml +++ b/useragent/android/app/src/debug/AndroidManifest.xml @@ -1,7 +1,7 @@ - - - - + + + + diff --git a/useragent/android/app/src/main/AndroidManifest.xml b/useragent/android/app/src/main/AndroidManifest.xml index 435af81..f1ff4e1 100644 --- a/useragent/android/app/src/main/AndroidManifest.xml +++ b/useragent/android/app/src/main/AndroidManifest.xml @@ -1,45 +1,45 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/useragent/android/app/src/main/kotlin/com/example/useragent/MainActivity.kt b/useragent/android/app/src/main/kotlin/com/example/useragent/MainActivity.kt index abbe9cf..062177e 100644 --- a/useragent/android/app/src/main/kotlin/com/example/useragent/MainActivity.kt +++ b/useragent/android/app/src/main/kotlin/com/example/useragent/MainActivity.kt @@ -1,5 +1,5 @@ -package com.example.useragent - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity : FlutterActivity() +package com.example.useragent + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/useragent/android/app/src/main/res/drawable-v21/launch_background.xml b/useragent/android/app/src/main/res/drawable-v21/launch_background.xml index f74085f..1cb7aa2 100644 --- a/useragent/android/app/src/main/res/drawable-v21/launch_background.xml +++ b/useragent/android/app/src/main/res/drawable-v21/launch_background.xml @@ -1,12 +1,12 @@ - - - - - - - - + + + + + + + + diff --git a/useragent/android/app/src/main/res/drawable/launch_background.xml b/useragent/android/app/src/main/res/drawable/launch_background.xml index 304732f..8403758 100644 --- a/useragent/android/app/src/main/res/drawable/launch_background.xml +++ b/useragent/android/app/src/main/res/drawable/launch_background.xml @@ -1,12 +1,12 @@ - - - - - - - - + + + + + + + + diff --git a/useragent/android/app/src/main/res/values-night/styles.xml b/useragent/android/app/src/main/res/values-night/styles.xml index 06952be..360a160 100644 --- a/useragent/android/app/src/main/res/values-night/styles.xml +++ b/useragent/android/app/src/main/res/values-night/styles.xml @@ -1,18 +1,18 @@ - - - - - - - + + + + + + + diff --git a/useragent/android/app/src/main/res/values/styles.xml b/useragent/android/app/src/main/res/values/styles.xml index cb1ef88..5fac679 100644 --- a/useragent/android/app/src/main/res/values/styles.xml +++ b/useragent/android/app/src/main/res/values/styles.xml @@ -1,18 +1,18 @@ - - - - - - - + + + + + + + diff --git a/useragent/android/app/src/profile/AndroidManifest.xml b/useragent/android/app/src/profile/AndroidManifest.xml index 399f698..8ffe024 100644 --- a/useragent/android/app/src/profile/AndroidManifest.xml +++ b/useragent/android/app/src/profile/AndroidManifest.xml @@ -1,7 +1,7 @@ - - - - + + + + diff --git a/useragent/android/build.gradle.kts b/useragent/android/build.gradle.kts index dbee657..1f88145 100644 --- a/useragent/android/build.gradle.kts +++ b/useragent/android/build.gradle.kts @@ -1,24 +1,24 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -val newBuildDir: Directory = - rootProject.layout.buildDirectory - .dir("../../build") - .get() -rootProject.layout.buildDirectory.value(newBuildDir) - -subprojects { - val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) - project.layout.buildDirectory.value(newSubprojectBuildDir) -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean") { - delete(rootProject.layout.buildDirectory) -} +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/useragent/android/gradle.properties b/useragent/android/gradle.properties index fbee1d8..21dbfa5 100644 --- a/useragent/android/gradle.properties +++ b/useragent/android/gradle.properties @@ -1,2 +1,2 @@ -org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError -android.useAndroidX=true +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true diff --git a/useragent/android/gradle/wrapper/gradle-wrapper.properties b/useragent/android/gradle/wrapper/gradle-wrapper.properties index e4ef43f..db3f453 100644 --- a/useragent/android/gradle/wrapper/gradle-wrapper.properties +++ b/useragent/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/useragent/android/settings.gradle.kts b/useragent/android/settings.gradle.kts index ca7fe06..4dcef4b 100644 --- a/useragent/android/settings.gradle.kts +++ b/useragent/android/settings.gradle.kts @@ -1,26 +1,26 @@ -pluginManagement { - val flutterSdkPath = - run { - val properties = java.util.Properties() - file("local.properties").inputStream().use { properties.load(it) } - val flutterSdkPath = properties.getProperty("flutter.sdk") - require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } - flutterSdkPath - } - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.11.1" apply false - id("org.jetbrains.kotlin.android") version "2.2.20" apply false -} - -include(":app") +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.11.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false +} + +include(":app") diff --git a/useragent/flutter_rust_bridge.yaml b/useragent/flutter_rust_bridge.yaml index e15ed91..054dcf2 100644 --- a/useragent/flutter_rust_bridge.yaml +++ b/useragent/flutter_rust_bridge.yaml @@ -1,3 +1,3 @@ -rust_input: crate::api -rust_root: rust/ +rust_input: crate::api +rust_root: rust/ dart_output: lib/src/rust \ No newline at end of file diff --git a/useragent/lib/features/callouts/active_callout.dart b/useragent/lib/features/callouts/active_callout.dart index 7d4ef83..bc509b7 100644 --- a/useragent/lib/features/callouts/active_callout.dart +++ b/useragent/lib/features/callouts/active_callout.dart @@ -1,16 +1,16 @@ -import 'package:arbiter/features/callouts/callout_event.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; - -part 'active_callout.freezed.dart'; - -@freezed -abstract class ActiveCallout with _$ActiveCallout { - const factory ActiveCallout({ - required String id, - required String title, - required String description, - String? iconUrl, - required DateTime addedAt, - required CalloutData data, - }) = _ActiveCallout; -} +import 'package:arbiter/features/callouts/callout_event.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'active_callout.freezed.dart'; + +@freezed +abstract class ActiveCallout with _$ActiveCallout { + const factory ActiveCallout({ + required String id, + required String title, + required String description, + String? iconUrl, + required DateTime addedAt, + required CalloutData data, + }) = _ActiveCallout; +} diff --git a/useragent/lib/features/callouts/active_callout.freezed.dart b/useragent/lib/features/callouts/active_callout.freezed.dart index eb25ff6..f93b2fc 100644 --- a/useragent/lib/features/callouts/active_callout.freezed.dart +++ b/useragent/lib/features/callouts/active_callout.freezed.dart @@ -1,304 +1,304 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND -// coverage:ignore-file -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'active_callout.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -// dart format off -T _$identity(T value) => value; -/// @nodoc -mixin _$ActiveCallout { - - String get id; String get title; String get description; String? get iconUrl; DateTime get addedAt; CalloutData get data; -/// Create a copy of ActiveCallout -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$ActiveCalloutCopyWith get copyWith => _$ActiveCalloutCopyWithImpl(this as ActiveCallout, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is ActiveCallout&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.iconUrl, iconUrl) || other.iconUrl == iconUrl)&&(identical(other.addedAt, addedAt) || other.addedAt == addedAt)&&(identical(other.data, data) || other.data == data)); -} - - -@override -int get hashCode => Object.hash(runtimeType,id,title,description,iconUrl,addedAt,data); - -@override -String toString() { - return 'ActiveCallout(id: $id, title: $title, description: $description, iconUrl: $iconUrl, addedAt: $addedAt, data: $data)'; -} - - -} - -/// @nodoc -abstract mixin class $ActiveCalloutCopyWith<$Res> { - factory $ActiveCalloutCopyWith(ActiveCallout value, $Res Function(ActiveCallout) _then) = _$ActiveCalloutCopyWithImpl; -@useResult -$Res call({ - String id, String title, String description, String? iconUrl, DateTime addedAt, CalloutData data -}); - - -$CalloutDataCopyWith<$Res> get data; - -} -/// @nodoc -class _$ActiveCalloutCopyWithImpl<$Res> - implements $ActiveCalloutCopyWith<$Res> { - _$ActiveCalloutCopyWithImpl(this._self, this._then); - - final ActiveCallout _self; - final $Res Function(ActiveCallout) _then; - -/// Create a copy of ActiveCallout -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = null,Object? description = null,Object? iconUrl = freezed,Object? addedAt = null,Object? data = null,}) { - return _then(_self.copyWith( -id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable -as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable -as String,iconUrl: freezed == iconUrl ? _self.iconUrl : iconUrl // ignore: cast_nullable_to_non_nullable -as String?,addedAt: null == addedAt ? _self.addedAt : addedAt // ignore: cast_nullable_to_non_nullable -as DateTime,data: null == data ? _self.data : data // ignore: cast_nullable_to_non_nullable -as CalloutData, - )); -} -/// Create a copy of ActiveCallout -/// with the given fields replaced by the non-null parameter values. -@override -@pragma('vm:prefer-inline') -$CalloutDataCopyWith<$Res> get data { - - return $CalloutDataCopyWith<$Res>(_self.data, (value) { - return _then(_self.copyWith(data: value)); - }); -} -} - - -/// Adds pattern-matching-related methods to [ActiveCallout]. -extension ActiveCalloutPatterns on ActiveCallout { -/// A variant of `map` that fallback to returning `orElse`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeMap(TResult Function( _ActiveCallout value)? $default,{required TResult orElse(),}){ -final _that = this; -switch (_that) { -case _ActiveCallout() when $default != null: -return $default(_that);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// Callbacks receives the raw object, upcasted. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case final Subclass2 value: -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult map(TResult Function( _ActiveCallout value) $default,){ -final _that = this; -switch (_that) { -case _ActiveCallout(): -return $default(_that);case _: - throw StateError('Unexpected subclass'); - -} -} -/// A variant of `map` that fallback to returning `null`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ActiveCallout value)? $default,){ -final _that = this; -switch (_that) { -case _ActiveCallout() when $default != null: -return $default(_that);case _: - return null; - -} -} -/// A variant of `when` that fallback to an `orElse` callback. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String title, String description, String? iconUrl, DateTime addedAt, CalloutData data)? $default,{required TResult orElse(),}) {final _that = this; -switch (_that) { -case _ActiveCallout() when $default != null: -return $default(_that.id,_that.title,_that.description,_that.iconUrl,_that.addedAt,_that.data);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// As opposed to `map`, this offers destructuring. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case Subclass2(:final field2): -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult when(TResult Function( String id, String title, String description, String? iconUrl, DateTime addedAt, CalloutData data) $default,) {final _that = this; -switch (_that) { -case _ActiveCallout(): -return $default(_that.id,_that.title,_that.description,_that.iconUrl,_that.addedAt,_that.data);case _: - throw StateError('Unexpected subclass'); - -} -} -/// A variant of `when` that fallback to returning `null` -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String title, String description, String? iconUrl, DateTime addedAt, CalloutData data)? $default,) {final _that = this; -switch (_that) { -case _ActiveCallout() when $default != null: -return $default(_that.id,_that.title,_that.description,_that.iconUrl,_that.addedAt,_that.data);case _: - return null; - -} -} - -} - -/// @nodoc - - -class _ActiveCallout implements ActiveCallout { - const _ActiveCallout({required this.id, required this.title, required this.description, this.iconUrl, required this.addedAt, required this.data}); - - -@override final String id; -@override final String title; -@override final String description; -@override final String? iconUrl; -@override final DateTime addedAt; -@override final CalloutData data; - -/// Create a copy of ActiveCallout -/// with the given fields replaced by the non-null parameter values. -@override @JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -_$ActiveCalloutCopyWith<_ActiveCallout> get copyWith => __$ActiveCalloutCopyWithImpl<_ActiveCallout>(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _ActiveCallout&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.iconUrl, iconUrl) || other.iconUrl == iconUrl)&&(identical(other.addedAt, addedAt) || other.addedAt == addedAt)&&(identical(other.data, data) || other.data == data)); -} - - -@override -int get hashCode => Object.hash(runtimeType,id,title,description,iconUrl,addedAt,data); - -@override -String toString() { - return 'ActiveCallout(id: $id, title: $title, description: $description, iconUrl: $iconUrl, addedAt: $addedAt, data: $data)'; -} - - -} - -/// @nodoc -abstract mixin class _$ActiveCalloutCopyWith<$Res> implements $ActiveCalloutCopyWith<$Res> { - factory _$ActiveCalloutCopyWith(_ActiveCallout value, $Res Function(_ActiveCallout) _then) = __$ActiveCalloutCopyWithImpl; -@override @useResult -$Res call({ - String id, String title, String description, String? iconUrl, DateTime addedAt, CalloutData data -}); - - -@override $CalloutDataCopyWith<$Res> get data; - -} -/// @nodoc -class __$ActiveCalloutCopyWithImpl<$Res> - implements _$ActiveCalloutCopyWith<$Res> { - __$ActiveCalloutCopyWithImpl(this._self, this._then); - - final _ActiveCallout _self; - final $Res Function(_ActiveCallout) _then; - -/// Create a copy of ActiveCallout -/// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = null,Object? description = null,Object? iconUrl = freezed,Object? addedAt = null,Object? data = null,}) { - return _then(_ActiveCallout( -id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable -as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable -as String,iconUrl: freezed == iconUrl ? _self.iconUrl : iconUrl // ignore: cast_nullable_to_non_nullable -as String?,addedAt: null == addedAt ? _self.addedAt : addedAt // ignore: cast_nullable_to_non_nullable -as DateTime,data: null == data ? _self.data : data // ignore: cast_nullable_to_non_nullable -as CalloutData, - )); -} - -/// Create a copy of ActiveCallout -/// with the given fields replaced by the non-null parameter values. -@override -@pragma('vm:prefer-inline') -$CalloutDataCopyWith<$Res> get data { - - return $CalloutDataCopyWith<$Res>(_self.data, (value) { - return _then(_self.copyWith(data: value)); - }); -} -} - -// dart format on +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'active_callout.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$ActiveCallout { + + String get id; String get title; String get description; String? get iconUrl; DateTime get addedAt; CalloutData get data; +/// Create a copy of ActiveCallout +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ActiveCalloutCopyWith get copyWith => _$ActiveCalloutCopyWithImpl(this as ActiveCallout, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ActiveCallout&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.iconUrl, iconUrl) || other.iconUrl == iconUrl)&&(identical(other.addedAt, addedAt) || other.addedAt == addedAt)&&(identical(other.data, data) || other.data == data)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,title,description,iconUrl,addedAt,data); + +@override +String toString() { + return 'ActiveCallout(id: $id, title: $title, description: $description, iconUrl: $iconUrl, addedAt: $addedAt, data: $data)'; +} + + +} + +/// @nodoc +abstract mixin class $ActiveCalloutCopyWith<$Res> { + factory $ActiveCalloutCopyWith(ActiveCallout value, $Res Function(ActiveCallout) _then) = _$ActiveCalloutCopyWithImpl; +@useResult +$Res call({ + String id, String title, String description, String? iconUrl, DateTime addedAt, CalloutData data +}); + + +$CalloutDataCopyWith<$Res> get data; + +} +/// @nodoc +class _$ActiveCalloutCopyWithImpl<$Res> + implements $ActiveCalloutCopyWith<$Res> { + _$ActiveCalloutCopyWithImpl(this._self, this._then); + + final ActiveCallout _self; + final $Res Function(ActiveCallout) _then; + +/// Create a copy of ActiveCallout +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = null,Object? description = null,Object? iconUrl = freezed,Object? addedAt = null,Object? data = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable +as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String,iconUrl: freezed == iconUrl ? _self.iconUrl : iconUrl // ignore: cast_nullable_to_non_nullable +as String?,addedAt: null == addedAt ? _self.addedAt : addedAt // ignore: cast_nullable_to_non_nullable +as DateTime,data: null == data ? _self.data : data // ignore: cast_nullable_to_non_nullable +as CalloutData, + )); +} +/// Create a copy of ActiveCallout +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$CalloutDataCopyWith<$Res> get data { + + return $CalloutDataCopyWith<$Res>(_self.data, (value) { + return _then(_self.copyWith(data: value)); + }); +} +} + + +/// Adds pattern-matching-related methods to [ActiveCallout]. +extension ActiveCalloutPatterns on ActiveCallout { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _ActiveCallout value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _ActiveCallout() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _ActiveCallout value) $default,){ +final _that = this; +switch (_that) { +case _ActiveCallout(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _ActiveCallout value)? $default,){ +final _that = this; +switch (_that) { +case _ActiveCallout() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String title, String description, String? iconUrl, DateTime addedAt, CalloutData data)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _ActiveCallout() when $default != null: +return $default(_that.id,_that.title,_that.description,_that.iconUrl,_that.addedAt,_that.data);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( String id, String title, String description, String? iconUrl, DateTime addedAt, CalloutData data) $default,) {final _that = this; +switch (_that) { +case _ActiveCallout(): +return $default(_that.id,_that.title,_that.description,_that.iconUrl,_that.addedAt,_that.data);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String title, String description, String? iconUrl, DateTime addedAt, CalloutData data)? $default,) {final _that = this; +switch (_that) { +case _ActiveCallout() when $default != null: +return $default(_that.id,_that.title,_that.description,_that.iconUrl,_that.addedAt,_that.data);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _ActiveCallout implements ActiveCallout { + const _ActiveCallout({required this.id, required this.title, required this.description, this.iconUrl, required this.addedAt, required this.data}); + + +@override final String id; +@override final String title; +@override final String description; +@override final String? iconUrl; +@override final DateTime addedAt; +@override final CalloutData data; + +/// Create a copy of ActiveCallout +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$ActiveCalloutCopyWith<_ActiveCallout> get copyWith => __$ActiveCalloutCopyWithImpl<_ActiveCallout>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ActiveCallout&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.iconUrl, iconUrl) || other.iconUrl == iconUrl)&&(identical(other.addedAt, addedAt) || other.addedAt == addedAt)&&(identical(other.data, data) || other.data == data)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,title,description,iconUrl,addedAt,data); + +@override +String toString() { + return 'ActiveCallout(id: $id, title: $title, description: $description, iconUrl: $iconUrl, addedAt: $addedAt, data: $data)'; +} + + +} + +/// @nodoc +abstract mixin class _$ActiveCalloutCopyWith<$Res> implements $ActiveCalloutCopyWith<$Res> { + factory _$ActiveCalloutCopyWith(_ActiveCallout value, $Res Function(_ActiveCallout) _then) = __$ActiveCalloutCopyWithImpl; +@override @useResult +$Res call({ + String id, String title, String description, String? iconUrl, DateTime addedAt, CalloutData data +}); + + +@override $CalloutDataCopyWith<$Res> get data; + +} +/// @nodoc +class __$ActiveCalloutCopyWithImpl<$Res> + implements _$ActiveCalloutCopyWith<$Res> { + __$ActiveCalloutCopyWithImpl(this._self, this._then); + + final _ActiveCallout _self; + final $Res Function(_ActiveCallout) _then; + +/// Create a copy of ActiveCallout +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = null,Object? description = null,Object? iconUrl = freezed,Object? addedAt = null,Object? data = null,}) { + return _then(_ActiveCallout( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable +as String,description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable +as String,iconUrl: freezed == iconUrl ? _self.iconUrl : iconUrl // ignore: cast_nullable_to_non_nullable +as String?,addedAt: null == addedAt ? _self.addedAt : addedAt // ignore: cast_nullable_to_non_nullable +as DateTime,data: null == data ? _self.data : data // ignore: cast_nullable_to_non_nullable +as CalloutData, + )); +} + +/// Create a copy of ActiveCallout +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$CalloutDataCopyWith<$Res> get data { + + return $CalloutDataCopyWith<$Res>(_self.data, (value) { + return _then(_self.copyWith(data: value)); + }); +} +} + +// dart format on diff --git a/useragent/lib/features/callouts/callout_event.dart b/useragent/lib/features/callouts/callout_event.dart index 99e943b..3087292 100644 --- a/useragent/lib/features/callouts/callout_event.dart +++ b/useragent/lib/features/callouts/callout_event.dart @@ -1,23 +1,23 @@ -import 'package:arbiter/proto/shared/client.pb.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; - -part 'callout_event.freezed.dart'; - -@freezed -sealed class CalloutData with _$CalloutData { - const factory CalloutData.connectApproval({ - required String pubkey, - required ClientInfo clientInfo, - }) = ConnectApprovalData; -} - -@freezed -sealed class CalloutEvent with _$CalloutEvent { - const factory CalloutEvent.added({ - required String id, - required CalloutData data, - }) = CalloutEventAdded; - - const factory CalloutEvent.cancelled({required String id}) = - CalloutEventCancelled; -} +import 'package:arbiter/proto/shared/client.pb.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'callout_event.freezed.dart'; + +@freezed +sealed class CalloutData with _$CalloutData { + const factory CalloutData.connectApproval({ + required String pubkey, + required ClientInfo clientInfo, + }) = ConnectApprovalData; +} + +@freezed +sealed class CalloutEvent with _$CalloutEvent { + const factory CalloutEvent.added({ + required String id, + required CalloutData data, + }) = CalloutEventAdded; + + const factory CalloutEvent.cancelled({required String id}) = + CalloutEventCancelled; +} diff --git a/useragent/lib/features/callouts/callout_event.freezed.dart b/useragent/lib/features/callouts/callout_event.freezed.dart index 5e97fad..667d383 100644 --- a/useragent/lib/features/callouts/callout_event.freezed.dart +++ b/useragent/lib/features/callouts/callout_event.freezed.dart @@ -1,602 +1,602 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND -// coverage:ignore-file -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'callout_event.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -// dart format off -T _$identity(T value) => value; -/// @nodoc -mixin _$CalloutData { - - String get pubkey; ClientInfo get clientInfo; -/// Create a copy of CalloutData -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$CalloutDataCopyWith get copyWith => _$CalloutDataCopyWithImpl(this as CalloutData, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalloutData&&(identical(other.pubkey, pubkey) || other.pubkey == pubkey)&&(identical(other.clientInfo, clientInfo) || other.clientInfo == clientInfo)); -} - - -@override -int get hashCode => Object.hash(runtimeType,pubkey,clientInfo); - -@override -String toString() { - return 'CalloutData(pubkey: $pubkey, clientInfo: $clientInfo)'; -} - - -} - -/// @nodoc -abstract mixin class $CalloutDataCopyWith<$Res> { - factory $CalloutDataCopyWith(CalloutData value, $Res Function(CalloutData) _then) = _$CalloutDataCopyWithImpl; -@useResult -$Res call({ - String pubkey, ClientInfo clientInfo -}); - - - - -} -/// @nodoc -class _$CalloutDataCopyWithImpl<$Res> - implements $CalloutDataCopyWith<$Res> { - _$CalloutDataCopyWithImpl(this._self, this._then); - - final CalloutData _self; - final $Res Function(CalloutData) _then; - -/// Create a copy of CalloutData -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? pubkey = null,Object? clientInfo = null,}) { - return _then(_self.copyWith( -pubkey: null == pubkey ? _self.pubkey : pubkey // ignore: cast_nullable_to_non_nullable -as String,clientInfo: null == clientInfo ? _self.clientInfo : clientInfo // ignore: cast_nullable_to_non_nullable -as ClientInfo, - )); -} - -} - - -/// Adds pattern-matching-related methods to [CalloutData]. -extension CalloutDataPatterns on CalloutData { -/// A variant of `map` that fallback to returning `orElse`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeMap({TResult Function( ConnectApprovalData value)? connectApproval,required TResult orElse(),}){ -final _that = this; -switch (_that) { -case ConnectApprovalData() when connectApproval != null: -return connectApproval(_that);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// Callbacks receives the raw object, upcasted. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case final Subclass2 value: -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult map({required TResult Function( ConnectApprovalData value) connectApproval,}){ -final _that = this; -switch (_that) { -case ConnectApprovalData(): -return connectApproval(_that);} -} -/// A variant of `map` that fallback to returning `null`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? mapOrNull({TResult? Function( ConnectApprovalData value)? connectApproval,}){ -final _that = this; -switch (_that) { -case ConnectApprovalData() when connectApproval != null: -return connectApproval(_that);case _: - return null; - -} -} -/// A variant of `when` that fallback to an `orElse` callback. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeWhen({TResult Function( String pubkey, ClientInfo clientInfo)? connectApproval,required TResult orElse(),}) {final _that = this; -switch (_that) { -case ConnectApprovalData() when connectApproval != null: -return connectApproval(_that.pubkey,_that.clientInfo);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// As opposed to `map`, this offers destructuring. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case Subclass2(:final field2): -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult when({required TResult Function( String pubkey, ClientInfo clientInfo) connectApproval,}) {final _that = this; -switch (_that) { -case ConnectApprovalData(): -return connectApproval(_that.pubkey,_that.clientInfo);} -} -/// A variant of `when` that fallback to returning `null` -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? whenOrNull({TResult? Function( String pubkey, ClientInfo clientInfo)? connectApproval,}) {final _that = this; -switch (_that) { -case ConnectApprovalData() when connectApproval != null: -return connectApproval(_that.pubkey,_that.clientInfo);case _: - return null; - -} -} - -} - -/// @nodoc - - -class ConnectApprovalData implements CalloutData { - const ConnectApprovalData({required this.pubkey, required this.clientInfo}); - - -@override final String pubkey; -@override final ClientInfo clientInfo; - -/// Create a copy of CalloutData -/// with the given fields replaced by the non-null parameter values. -@override @JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$ConnectApprovalDataCopyWith get copyWith => _$ConnectApprovalDataCopyWithImpl(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is ConnectApprovalData&&(identical(other.pubkey, pubkey) || other.pubkey == pubkey)&&(identical(other.clientInfo, clientInfo) || other.clientInfo == clientInfo)); -} - - -@override -int get hashCode => Object.hash(runtimeType,pubkey,clientInfo); - -@override -String toString() { - return 'CalloutData.connectApproval(pubkey: $pubkey, clientInfo: $clientInfo)'; -} - - -} - -/// @nodoc -abstract mixin class $ConnectApprovalDataCopyWith<$Res> implements $CalloutDataCopyWith<$Res> { - factory $ConnectApprovalDataCopyWith(ConnectApprovalData value, $Res Function(ConnectApprovalData) _then) = _$ConnectApprovalDataCopyWithImpl; -@override @useResult -$Res call({ - String pubkey, ClientInfo clientInfo -}); - - - - -} -/// @nodoc -class _$ConnectApprovalDataCopyWithImpl<$Res> - implements $ConnectApprovalDataCopyWith<$Res> { - _$ConnectApprovalDataCopyWithImpl(this._self, this._then); - - final ConnectApprovalData _self; - final $Res Function(ConnectApprovalData) _then; - -/// Create a copy of CalloutData -/// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? pubkey = null,Object? clientInfo = null,}) { - return _then(ConnectApprovalData( -pubkey: null == pubkey ? _self.pubkey : pubkey // ignore: cast_nullable_to_non_nullable -as String,clientInfo: null == clientInfo ? _self.clientInfo : clientInfo // ignore: cast_nullable_to_non_nullable -as ClientInfo, - )); -} - - -} - -/// @nodoc -mixin _$CalloutEvent { - - String get id; -/// Create a copy of CalloutEvent -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$CalloutEventCopyWith get copyWith => _$CalloutEventCopyWithImpl(this as CalloutEvent, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalloutEvent&&(identical(other.id, id) || other.id == id)); -} - - -@override -int get hashCode => Object.hash(runtimeType,id); - -@override -String toString() { - return 'CalloutEvent(id: $id)'; -} - - -} - -/// @nodoc -abstract mixin class $CalloutEventCopyWith<$Res> { - factory $CalloutEventCopyWith(CalloutEvent value, $Res Function(CalloutEvent) _then) = _$CalloutEventCopyWithImpl; -@useResult -$Res call({ - String id -}); - - - - -} -/// @nodoc -class _$CalloutEventCopyWithImpl<$Res> - implements $CalloutEventCopyWith<$Res> { - _$CalloutEventCopyWithImpl(this._self, this._then); - - final CalloutEvent _self; - final $Res Function(CalloutEvent) _then; - -/// Create a copy of CalloutEvent -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,}) { - return _then(_self.copyWith( -id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String, - )); -} - -} - - -/// Adds pattern-matching-related methods to [CalloutEvent]. -extension CalloutEventPatterns on CalloutEvent { -/// A variant of `map` that fallback to returning `orElse`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeMap({TResult Function( CalloutEventAdded value)? added,TResult Function( CalloutEventCancelled value)? cancelled,required TResult orElse(),}){ -final _that = this; -switch (_that) { -case CalloutEventAdded() when added != null: -return added(_that);case CalloutEventCancelled() when cancelled != null: -return cancelled(_that);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// Callbacks receives the raw object, upcasted. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case final Subclass2 value: -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult map({required TResult Function( CalloutEventAdded value) added,required TResult Function( CalloutEventCancelled value) cancelled,}){ -final _that = this; -switch (_that) { -case CalloutEventAdded(): -return added(_that);case CalloutEventCancelled(): -return cancelled(_that);} -} -/// A variant of `map` that fallback to returning `null`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? mapOrNull({TResult? Function( CalloutEventAdded value)? added,TResult? Function( CalloutEventCancelled value)? cancelled,}){ -final _that = this; -switch (_that) { -case CalloutEventAdded() when added != null: -return added(_that);case CalloutEventCancelled() when cancelled != null: -return cancelled(_that);case _: - return null; - -} -} -/// A variant of `when` that fallback to an `orElse` callback. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeWhen({TResult Function( String id, CalloutData data)? added,TResult Function( String id)? cancelled,required TResult orElse(),}) {final _that = this; -switch (_that) { -case CalloutEventAdded() when added != null: -return added(_that.id,_that.data);case CalloutEventCancelled() when cancelled != null: -return cancelled(_that.id);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// As opposed to `map`, this offers destructuring. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case Subclass2(:final field2): -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult when({required TResult Function( String id, CalloutData data) added,required TResult Function( String id) cancelled,}) {final _that = this; -switch (_that) { -case CalloutEventAdded(): -return added(_that.id,_that.data);case CalloutEventCancelled(): -return cancelled(_that.id);} -} -/// A variant of `when` that fallback to returning `null` -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? whenOrNull({TResult? Function( String id, CalloutData data)? added,TResult? Function( String id)? cancelled,}) {final _that = this; -switch (_that) { -case CalloutEventAdded() when added != null: -return added(_that.id,_that.data);case CalloutEventCancelled() when cancelled != null: -return cancelled(_that.id);case _: - return null; - -} -} - -} - -/// @nodoc - - -class CalloutEventAdded implements CalloutEvent { - const CalloutEventAdded({required this.id, required this.data}); - - -@override final String id; - final CalloutData data; - -/// Create a copy of CalloutEvent -/// with the given fields replaced by the non-null parameter values. -@override @JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$CalloutEventAddedCopyWith get copyWith => _$CalloutEventAddedCopyWithImpl(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalloutEventAdded&&(identical(other.id, id) || other.id == id)&&(identical(other.data, data) || other.data == data)); -} - - -@override -int get hashCode => Object.hash(runtimeType,id,data); - -@override -String toString() { - return 'CalloutEvent.added(id: $id, data: $data)'; -} - - -} - -/// @nodoc -abstract mixin class $CalloutEventAddedCopyWith<$Res> implements $CalloutEventCopyWith<$Res> { - factory $CalloutEventAddedCopyWith(CalloutEventAdded value, $Res Function(CalloutEventAdded) _then) = _$CalloutEventAddedCopyWithImpl; -@override @useResult -$Res call({ - String id, CalloutData data -}); - - -$CalloutDataCopyWith<$Res> get data; - -} -/// @nodoc -class _$CalloutEventAddedCopyWithImpl<$Res> - implements $CalloutEventAddedCopyWith<$Res> { - _$CalloutEventAddedCopyWithImpl(this._self, this._then); - - final CalloutEventAdded _self; - final $Res Function(CalloutEventAdded) _then; - -/// Create a copy of CalloutEvent -/// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? data = null,}) { - return _then(CalloutEventAdded( -id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String,data: null == data ? _self.data : data // ignore: cast_nullable_to_non_nullable -as CalloutData, - )); -} - -/// Create a copy of CalloutEvent -/// with the given fields replaced by the non-null parameter values. -@override -@pragma('vm:prefer-inline') -$CalloutDataCopyWith<$Res> get data { - - return $CalloutDataCopyWith<$Res>(_self.data, (value) { - return _then(_self.copyWith(data: value)); - }); -} -} - -/// @nodoc - - -class CalloutEventCancelled implements CalloutEvent { - const CalloutEventCancelled({required this.id}); - - -@override final String id; - -/// Create a copy of CalloutEvent -/// with the given fields replaced by the non-null parameter values. -@override @JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$CalloutEventCancelledCopyWith get copyWith => _$CalloutEventCancelledCopyWithImpl(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalloutEventCancelled&&(identical(other.id, id) || other.id == id)); -} - - -@override -int get hashCode => Object.hash(runtimeType,id); - -@override -String toString() { - return 'CalloutEvent.cancelled(id: $id)'; -} - - -} - -/// @nodoc -abstract mixin class $CalloutEventCancelledCopyWith<$Res> implements $CalloutEventCopyWith<$Res> { - factory $CalloutEventCancelledCopyWith(CalloutEventCancelled value, $Res Function(CalloutEventCancelled) _then) = _$CalloutEventCancelledCopyWithImpl; -@override @useResult -$Res call({ - String id -}); - - - - -} -/// @nodoc -class _$CalloutEventCancelledCopyWithImpl<$Res> - implements $CalloutEventCancelledCopyWith<$Res> { - _$CalloutEventCancelledCopyWithImpl(this._self, this._then); - - final CalloutEventCancelled _self; - final $Res Function(CalloutEventCancelled) _then; - -/// Create a copy of CalloutEvent -/// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,}) { - return _then(CalloutEventCancelled( -id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String, - )); -} - - -} - -// dart format on +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'callout_event.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$CalloutData { + + String get pubkey; ClientInfo get clientInfo; +/// Create a copy of CalloutData +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CalloutDataCopyWith get copyWith => _$CalloutDataCopyWithImpl(this as CalloutData, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CalloutData&&(identical(other.pubkey, pubkey) || other.pubkey == pubkey)&&(identical(other.clientInfo, clientInfo) || other.clientInfo == clientInfo)); +} + + +@override +int get hashCode => Object.hash(runtimeType,pubkey,clientInfo); + +@override +String toString() { + return 'CalloutData(pubkey: $pubkey, clientInfo: $clientInfo)'; +} + + +} + +/// @nodoc +abstract mixin class $CalloutDataCopyWith<$Res> { + factory $CalloutDataCopyWith(CalloutData value, $Res Function(CalloutData) _then) = _$CalloutDataCopyWithImpl; +@useResult +$Res call({ + String pubkey, ClientInfo clientInfo +}); + + + + +} +/// @nodoc +class _$CalloutDataCopyWithImpl<$Res> + implements $CalloutDataCopyWith<$Res> { + _$CalloutDataCopyWithImpl(this._self, this._then); + + final CalloutData _self; + final $Res Function(CalloutData) _then; + +/// Create a copy of CalloutData +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? pubkey = null,Object? clientInfo = null,}) { + return _then(_self.copyWith( +pubkey: null == pubkey ? _self.pubkey : pubkey // ignore: cast_nullable_to_non_nullable +as String,clientInfo: null == clientInfo ? _self.clientInfo : clientInfo // ignore: cast_nullable_to_non_nullable +as ClientInfo, + )); +} + +} + + +/// Adds pattern-matching-related methods to [CalloutData]. +extension CalloutDataPatterns on CalloutData { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap({TResult Function( ConnectApprovalData value)? connectApproval,required TResult orElse(),}){ +final _that = this; +switch (_that) { +case ConnectApprovalData() when connectApproval != null: +return connectApproval(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map({required TResult Function( ConnectApprovalData value) connectApproval,}){ +final _that = this; +switch (_that) { +case ConnectApprovalData(): +return connectApproval(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull({TResult? Function( ConnectApprovalData value)? connectApproval,}){ +final _that = this; +switch (_that) { +case ConnectApprovalData() when connectApproval != null: +return connectApproval(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen({TResult Function( String pubkey, ClientInfo clientInfo)? connectApproval,required TResult orElse(),}) {final _that = this; +switch (_that) { +case ConnectApprovalData() when connectApproval != null: +return connectApproval(_that.pubkey,_that.clientInfo);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when({required TResult Function( String pubkey, ClientInfo clientInfo) connectApproval,}) {final _that = this; +switch (_that) { +case ConnectApprovalData(): +return connectApproval(_that.pubkey,_that.clientInfo);} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull({TResult? Function( String pubkey, ClientInfo clientInfo)? connectApproval,}) {final _that = this; +switch (_that) { +case ConnectApprovalData() when connectApproval != null: +return connectApproval(_that.pubkey,_that.clientInfo);case _: + return null; + +} +} + +} + +/// @nodoc + + +class ConnectApprovalData implements CalloutData { + const ConnectApprovalData({required this.pubkey, required this.clientInfo}); + + +@override final String pubkey; +@override final ClientInfo clientInfo; + +/// Create a copy of CalloutData +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$ConnectApprovalDataCopyWith get copyWith => _$ConnectApprovalDataCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is ConnectApprovalData&&(identical(other.pubkey, pubkey) || other.pubkey == pubkey)&&(identical(other.clientInfo, clientInfo) || other.clientInfo == clientInfo)); +} + + +@override +int get hashCode => Object.hash(runtimeType,pubkey,clientInfo); + +@override +String toString() { + return 'CalloutData.connectApproval(pubkey: $pubkey, clientInfo: $clientInfo)'; +} + + +} + +/// @nodoc +abstract mixin class $ConnectApprovalDataCopyWith<$Res> implements $CalloutDataCopyWith<$Res> { + factory $ConnectApprovalDataCopyWith(ConnectApprovalData value, $Res Function(ConnectApprovalData) _then) = _$ConnectApprovalDataCopyWithImpl; +@override @useResult +$Res call({ + String pubkey, ClientInfo clientInfo +}); + + + + +} +/// @nodoc +class _$ConnectApprovalDataCopyWithImpl<$Res> + implements $ConnectApprovalDataCopyWith<$Res> { + _$ConnectApprovalDataCopyWithImpl(this._self, this._then); + + final ConnectApprovalData _self; + final $Res Function(ConnectApprovalData) _then; + +/// Create a copy of CalloutData +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? pubkey = null,Object? clientInfo = null,}) { + return _then(ConnectApprovalData( +pubkey: null == pubkey ? _self.pubkey : pubkey // ignore: cast_nullable_to_non_nullable +as String,clientInfo: null == clientInfo ? _self.clientInfo : clientInfo // ignore: cast_nullable_to_non_nullable +as ClientInfo, + )); +} + + +} + +/// @nodoc +mixin _$CalloutEvent { + + String get id; +/// Create a copy of CalloutEvent +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CalloutEventCopyWith get copyWith => _$CalloutEventCopyWithImpl(this as CalloutEvent, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CalloutEvent&&(identical(other.id, id) || other.id == id)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id); + +@override +String toString() { + return 'CalloutEvent(id: $id)'; +} + + +} + +/// @nodoc +abstract mixin class $CalloutEventCopyWith<$Res> { + factory $CalloutEventCopyWith(CalloutEvent value, $Res Function(CalloutEvent) _then) = _$CalloutEventCopyWithImpl; +@useResult +$Res call({ + String id +}); + + + + +} +/// @nodoc +class _$CalloutEventCopyWithImpl<$Res> + implements $CalloutEventCopyWith<$Res> { + _$CalloutEventCopyWithImpl(this._self, this._then); + + final CalloutEvent _self; + final $Res Function(CalloutEvent) _then; + +/// Create a copy of CalloutEvent +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,}) { + return _then(_self.copyWith( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String, + )); +} + +} + + +/// Adds pattern-matching-related methods to [CalloutEvent]. +extension CalloutEventPatterns on CalloutEvent { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap({TResult Function( CalloutEventAdded value)? added,TResult Function( CalloutEventCancelled value)? cancelled,required TResult orElse(),}){ +final _that = this; +switch (_that) { +case CalloutEventAdded() when added != null: +return added(_that);case CalloutEventCancelled() when cancelled != null: +return cancelled(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map({required TResult Function( CalloutEventAdded value) added,required TResult Function( CalloutEventCancelled value) cancelled,}){ +final _that = this; +switch (_that) { +case CalloutEventAdded(): +return added(_that);case CalloutEventCancelled(): +return cancelled(_that);} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull({TResult? Function( CalloutEventAdded value)? added,TResult? Function( CalloutEventCancelled value)? cancelled,}){ +final _that = this; +switch (_that) { +case CalloutEventAdded() when added != null: +return added(_that);case CalloutEventCancelled() when cancelled != null: +return cancelled(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen({TResult Function( String id, CalloutData data)? added,TResult Function( String id)? cancelled,required TResult orElse(),}) {final _that = this; +switch (_that) { +case CalloutEventAdded() when added != null: +return added(_that.id,_that.data);case CalloutEventCancelled() when cancelled != null: +return cancelled(_that.id);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when({required TResult Function( String id, CalloutData data) added,required TResult Function( String id) cancelled,}) {final _that = this; +switch (_that) { +case CalloutEventAdded(): +return added(_that.id,_that.data);case CalloutEventCancelled(): +return cancelled(_that.id);} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull({TResult? Function( String id, CalloutData data)? added,TResult? Function( String id)? cancelled,}) {final _that = this; +switch (_that) { +case CalloutEventAdded() when added != null: +return added(_that.id,_that.data);case CalloutEventCancelled() when cancelled != null: +return cancelled(_that.id);case _: + return null; + +} +} + +} + +/// @nodoc + + +class CalloutEventAdded implements CalloutEvent { + const CalloutEventAdded({required this.id, required this.data}); + + +@override final String id; + final CalloutData data; + +/// Create a copy of CalloutEvent +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CalloutEventAddedCopyWith get copyWith => _$CalloutEventAddedCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CalloutEventAdded&&(identical(other.id, id) || other.id == id)&&(identical(other.data, data) || other.data == data)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id,data); + +@override +String toString() { + return 'CalloutEvent.added(id: $id, data: $data)'; +} + + +} + +/// @nodoc +abstract mixin class $CalloutEventAddedCopyWith<$Res> implements $CalloutEventCopyWith<$Res> { + factory $CalloutEventAddedCopyWith(CalloutEventAdded value, $Res Function(CalloutEventAdded) _then) = _$CalloutEventAddedCopyWithImpl; +@override @useResult +$Res call({ + String id, CalloutData data +}); + + +$CalloutDataCopyWith<$Res> get data; + +} +/// @nodoc +class _$CalloutEventAddedCopyWithImpl<$Res> + implements $CalloutEventAddedCopyWith<$Res> { + _$CalloutEventAddedCopyWithImpl(this._self, this._then); + + final CalloutEventAdded _self; + final $Res Function(CalloutEventAdded) _then; + +/// Create a copy of CalloutEvent +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? data = null,}) { + return _then(CalloutEventAdded( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String,data: null == data ? _self.data : data // ignore: cast_nullable_to_non_nullable +as CalloutData, + )); +} + +/// Create a copy of CalloutEvent +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$CalloutDataCopyWith<$Res> get data { + + return $CalloutDataCopyWith<$Res>(_self.data, (value) { + return _then(_self.copyWith(data: value)); + }); +} +} + +/// @nodoc + + +class CalloutEventCancelled implements CalloutEvent { + const CalloutEventCancelled({required this.id}); + + +@override final String id; + +/// Create a copy of CalloutEvent +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$CalloutEventCancelledCopyWith get copyWith => _$CalloutEventCancelledCopyWithImpl(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is CalloutEventCancelled&&(identical(other.id, id) || other.id == id)); +} + + +@override +int get hashCode => Object.hash(runtimeType,id); + +@override +String toString() { + return 'CalloutEvent.cancelled(id: $id)'; +} + + +} + +/// @nodoc +abstract mixin class $CalloutEventCancelledCopyWith<$Res> implements $CalloutEventCopyWith<$Res> { + factory $CalloutEventCancelledCopyWith(CalloutEventCancelled value, $Res Function(CalloutEventCancelled) _then) = _$CalloutEventCancelledCopyWithImpl; +@override @useResult +$Res call({ + String id +}); + + + + +} +/// @nodoc +class _$CalloutEventCancelledCopyWithImpl<$Res> + implements $CalloutEventCancelledCopyWith<$Res> { + _$CalloutEventCancelledCopyWithImpl(this._self, this._then); + + final CalloutEventCancelled _self; + final $Res Function(CalloutEventCancelled) _then; + +/// Create a copy of CalloutEvent +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,}) { + return _then(CalloutEventCancelled( +id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable +as String, + )); +} + + +} + +// dart format on diff --git a/useragent/lib/features/callouts/callout_manager.dart b/useragent/lib/features/callouts/callout_manager.dart index ad85023..6e8e42b 100644 --- a/useragent/lib/features/callouts/callout_manager.dart +++ b/useragent/lib/features/callouts/callout_manager.dart @@ -1,57 +1,57 @@ -import 'package:arbiter/features/callouts/active_callout.dart'; -import 'package:arbiter/features/callouts/callout_event.dart'; -import 'package:arbiter/features/callouts/types/sdk_connect_approve.dart' - as connect_approve; -import 'package:arbiter/proto/shared/client.pb.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'callout_manager.g.dart'; - -@Riverpod(keepAlive: true) -class CalloutManager extends _$CalloutManager { - @override - Map build() { - ref.listen(connect_approve.connectApproveEventsProvider, (_, next) { - next.whenData(_processEvent); - }); - return {}; - } - - void _processEvent(CalloutEvent event) { - switch (event) { - case CalloutEventAdded(:final id, :final data): - state = {...state, id: _toActiveCallout(id, data)}; - case CalloutEventCancelled(:final id): - state = {...state}..remove(id); - } - } - - Future sendDecision(String id, bool approved) async { - final callout = state[id]; - if (callout == null) return; - switch (callout.data) { - case ConnectApprovalData(:final pubkey): - await connect_approve.sendDecision(ref, pubkey, approved); - } - dismiss(id); - } - - void dismiss(String id) { - state = {...state}..remove(id); - } -} - -ActiveCallout _toActiveCallout(String id, CalloutData data) => switch (data) { - ConnectApprovalData(:final clientInfo) => ActiveCallout( - id: id, - title: 'Connection Request', - description: _clientDisplayName(clientInfo) != null - ? '${_clientDisplayName(clientInfo)} is requesting a connection.' - : 'An SDK client is requesting a connection.', - addedAt: DateTime.now(), - data: data, - ), -}; - -String? _clientDisplayName(ClientInfo info) => - info.hasName() && info.name.isNotEmpty ? info.name : null; +import 'package:arbiter/features/callouts/active_callout.dart'; +import 'package:arbiter/features/callouts/callout_event.dart'; +import 'package:arbiter/features/callouts/types/sdk_connect_approve.dart' + as connect_approve; +import 'package:arbiter/proto/shared/client.pb.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'callout_manager.g.dart'; + +@Riverpod(keepAlive: true) +class CalloutManager extends _$CalloutManager { + @override + Map build() { + ref.listen(connect_approve.connectApproveEventsProvider, (_, next) { + next.whenData(_processEvent); + }); + return {}; + } + + void _processEvent(CalloutEvent event) { + switch (event) { + case CalloutEventAdded(:final id, :final data): + state = {...state, id: _toActiveCallout(id, data)}; + case CalloutEventCancelled(:final id): + state = {...state}..remove(id); + } + } + + Future sendDecision(String id, bool approved) async { + final callout = state[id]; + if (callout == null) return; + switch (callout.data) { + case ConnectApprovalData(:final pubkey): + await connect_approve.sendDecision(ref, pubkey, approved); + } + dismiss(id); + } + + void dismiss(String id) { + state = {...state}..remove(id); + } +} + +ActiveCallout _toActiveCallout(String id, CalloutData data) => switch (data) { + ConnectApprovalData(:final clientInfo) => ActiveCallout( + id: id, + title: 'Connection Request', + description: _clientDisplayName(clientInfo) != null + ? '${_clientDisplayName(clientInfo)} is requesting a connection.' + : 'An SDK client is requesting a connection.', + addedAt: DateTime.now(), + data: data, + ), +}; + +String? _clientDisplayName(ClientInfo info) => + info.hasName() && info.name.isNotEmpty ? info.name : null; diff --git a/useragent/lib/features/callouts/callout_manager.g.dart b/useragent/lib/features/callouts/callout_manager.g.dart index 2f20330..595fa07 100644 --- a/useragent/lib/features/callouts/callout_manager.g.dart +++ b/useragent/lib/features/callouts/callout_manager.g.dart @@ -1,67 +1,67 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'callout_manager.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(CalloutManager) -final calloutManagerProvider = CalloutManagerProvider._(); - -final class CalloutManagerProvider - extends $NotifierProvider> { - CalloutManagerProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'calloutManagerProvider', - isAutoDispose: false, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$calloutManagerHash(); - - @$internal - @override - CalloutManager create() => CalloutManager(); - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(Map value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider>(value), - ); - } -} - -String _$calloutManagerHash() => r'ff8c9a03a6bbbca822242eb497c503b18240a289'; - -abstract class _$CalloutManager extends $Notifier> { - Map build(); - @$mustCallSuper - @override - void runBuild() { - final ref = - this.ref - as $Ref, Map>; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier< - Map, - Map - >, - Map, - Object?, - Object? - >; - element.handleCreate(ref, build); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'callout_manager.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(CalloutManager) +final calloutManagerProvider = CalloutManagerProvider._(); + +final class CalloutManagerProvider + extends $NotifierProvider> { + CalloutManagerProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'calloutManagerProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$calloutManagerHash(); + + @$internal + @override + CalloutManager create() => CalloutManager(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(Map value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider>(value), + ); + } +} + +String _$calloutManagerHash() => r'ff8c9a03a6bbbca822242eb497c503b18240a289'; + +abstract class _$CalloutManager extends $Notifier> { + Map build(); + @$mustCallSuper + @override + void runBuild() { + final ref = + this.ref + as $Ref, Map>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier< + Map, + Map + >, + Map, + Object?, + Object? + >; + element.handleCreate(ref, build); + } +} diff --git a/useragent/lib/features/callouts/show_callout.dart b/useragent/lib/features/callouts/show_callout.dart index 77e3a48..a51e571 100644 --- a/useragent/lib/features/callouts/show_callout.dart +++ b/useragent/lib/features/callouts/show_callout.dart @@ -1,99 +1,99 @@ -import 'package:arbiter/features/callouts/callout_event.dart'; -import 'package:arbiter/features/callouts/callout_manager.dart'; -import 'package:arbiter/screens/callouts/sdk_connect.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -Future showCallout(BuildContext context, WidgetRef ref, String id) async { - final data = ref.read(calloutManagerProvider)[id]?.data; - if (data == null) return; - - await showGeneralDialog( - context: context, - barrierDismissible: false, - barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, - barrierColor: Colors.transparent, - transitionDuration: const Duration(milliseconds: 320), - pageBuilder: (_, animation, _) => - _CalloutOverlay(id: id, data: data, animation: animation), - ); -} - -class _CalloutOverlay extends ConsumerWidget { - const _CalloutOverlay({ - required this.id, - required this.data, - required this.animation, - }); - - final String id; - final CalloutData data; - final Animation animation; - - @override - Widget build(BuildContext context, WidgetRef ref) { - ref.listen(calloutManagerProvider.select((map) => map.containsKey(id)), ( - wasPresent, - isPresent, - ) { - if (wasPresent == true && !isPresent && context.mounted) { - Navigator.of(context).pop(); - } - }); - - final content = switch (data) { - ConnectApprovalData(:final pubkey, :final clientInfo) => - SdkConnectCallout( - pubkey: pubkey, - clientInfo: clientInfo, - onAccept: () => - ref.read(calloutManagerProvider.notifier).sendDecision(id, true), - onDecline: () => - ref.read(calloutManagerProvider.notifier).sendDecision(id, false), - ), - }; - - final barrierAnim = CurvedAnimation( - parent: animation, - curve: const Interval(0, 0.3125, curve: Curves.easeOut), - ); - final popupAnim = CurvedAnimation( - parent: animation, - curve: const Interval(0.3125, 1, curve: Curves.easeOutCubic), - ); - - return Material( - type: MaterialType.transparency, - child: Stack( - children: [ - Positioned.fill( - child: AnimatedBuilder( - animation: barrierAnim, - builder: (_, __) => ColoredBox( - color: Colors.black.withValues(alpha: 0.35 * barrierAnim.value), - ), - ), - ), - SafeArea( - child: Align( - alignment: Alignment.bottomCenter, - child: Padding( - padding: const EdgeInsets.all(16), - child: FadeTransition( - opacity: popupAnim, - child: SlideTransition( - position: Tween( - begin: const Offset(0, 0.08), - end: Offset.zero, - ).animate(popupAnim), - child: content, - ), - ), - ), - ), - ), - ], - ), - ); - } -} +import 'package:arbiter/features/callouts/callout_event.dart'; +import 'package:arbiter/features/callouts/callout_manager.dart'; +import 'package:arbiter/screens/callouts/sdk_connect.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +Future showCallout(BuildContext context, WidgetRef ref, String id) async { + final data = ref.read(calloutManagerProvider)[id]?.data; + if (data == null) return; + + await showGeneralDialog( + context: context, + barrierDismissible: false, + barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, + barrierColor: Colors.transparent, + transitionDuration: const Duration(milliseconds: 320), + pageBuilder: (_, animation, _) => + _CalloutOverlay(id: id, data: data, animation: animation), + ); +} + +class _CalloutOverlay extends ConsumerWidget { + const _CalloutOverlay({ + required this.id, + required this.data, + required this.animation, + }); + + final String id; + final CalloutData data; + final Animation animation; + + @override + Widget build(BuildContext context, WidgetRef ref) { + ref.listen(calloutManagerProvider.select((map) => map.containsKey(id)), ( + wasPresent, + isPresent, + ) { + if (wasPresent == true && !isPresent && context.mounted) { + Navigator.of(context).pop(); + } + }); + + final content = switch (data) { + ConnectApprovalData(:final pubkey, :final clientInfo) => + SdkConnectCallout( + pubkey: pubkey, + clientInfo: clientInfo, + onAccept: () => + ref.read(calloutManagerProvider.notifier).sendDecision(id, true), + onDecline: () => + ref.read(calloutManagerProvider.notifier).sendDecision(id, false), + ), + }; + + final barrierAnim = CurvedAnimation( + parent: animation, + curve: const Interval(0, 0.3125, curve: Curves.easeOut), + ); + final popupAnim = CurvedAnimation( + parent: animation, + curve: const Interval(0.3125, 1, curve: Curves.easeOutCubic), + ); + + return Material( + type: MaterialType.transparency, + child: Stack( + children: [ + Positioned.fill( + child: AnimatedBuilder( + animation: barrierAnim, + builder: (_, __) => ColoredBox( + color: Colors.black.withValues(alpha: 0.35 * barrierAnim.value), + ), + ), + ), + SafeArea( + child: Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.all(16), + child: FadeTransition( + opacity: popupAnim, + child: SlideTransition( + position: Tween( + begin: const Offset(0, 0.08), + end: Offset.zero, + ).animate(popupAnim), + child: content, + ), + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/useragent/lib/features/callouts/show_callout_list.dart b/useragent/lib/features/callouts/show_callout_list.dart index 2e72491..b88df7f 100644 --- a/useragent/lib/features/callouts/show_callout_list.dart +++ b/useragent/lib/features/callouts/show_callout_list.dart @@ -1,221 +1,221 @@ -import 'package:arbiter/features/callouts/active_callout.dart'; -import 'package:arbiter/features/callouts/callout_manager.dart'; -import 'package:arbiter/features/callouts/show_callout.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; -import 'package:timeago/timeago.dart' as timeago; - -Future showCalloutList(BuildContext context, WidgetRef ref) async { - final selectedId = await showGeneralDialog( - context: context, - barrierDismissible: true, - barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, - barrierColor: Colors.transparent, - transitionDuration: const Duration(milliseconds: 280), - pageBuilder: (_, animation, __) => - _CalloutListOverlay(animation: animation), - ); - - if (selectedId != null && context.mounted) { - await showCallout(context, ref, selectedId); - } -} - -class _CalloutListOverlay extends ConsumerWidget { - const _CalloutListOverlay({required this.animation}); - - final Animation animation; - - @override - Widget build(BuildContext context, WidgetRef ref) { - final callouts = ref.watch(calloutManagerProvider); - - final barrierAnim = CurvedAnimation( - parent: animation, - curve: const Interval(0, 0.3, curve: Curves.easeOut), - ); - final panelAnim = CurvedAnimation( - parent: animation, - curve: const Interval(0.3, 1, curve: Curves.easeOutCubic), - ); - - return Material( - type: MaterialType.transparency, - child: Stack( - children: [ - Positioned.fill( - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () => Navigator.of(context).pop(), - child: AnimatedBuilder( - animation: barrierAnim, - builder: (_, __) => ColoredBox( - color: Colors.black.withValues( - alpha: 0.35 * barrierAnim.value, - ), - ), - ), - ), - ), - SafeArea( - child: Align( - alignment: Alignment.bottomCenter, - child: Padding( - padding: EdgeInsets.all(1.6.h), - child: FadeTransition( - opacity: panelAnim, - child: SlideTransition( - position: Tween( - begin: const Offset(0, 0.08), - end: Offset.zero, - ).animate(panelAnim), - child: GestureDetector( - onTap: () {}, - child: _CalloutListPanel(callouts: callouts), - ), - ), - ), - ), - ), - ), - ], - ), - ); - } -} - -class _CalloutListPanel extends StatelessWidget { - const _CalloutListPanel({required this.callouts}); - - final Map callouts; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - return Container( - width: double.infinity, - constraints: BoxConstraints(maxHeight: 48.h), - decoration: BoxDecoration( - color: Palette.cream, - borderRadius: BorderRadius.circular(24), - border: Border.all(color: Palette.line), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: EdgeInsets.fromLTRB(2.h, 2.h, 2.h, 1.2.h), - child: Text( - 'Notifications', - style: theme.textTheme.titleMedium?.copyWith( - color: Palette.ink, - fontWeight: FontWeight.w800, - ), - ), - ), - if (callouts.isEmpty) - Padding( - padding: EdgeInsets.fromLTRB(2.h, 0, 2.h, 2.h), - child: Text( - 'No pending notifications.', - style: theme.textTheme.bodyMedium?.copyWith( - color: Palette.ink.withValues(alpha: 0.50), - ), - ), - ) - else - Flexible( - child: SingleChildScrollView( - padding: EdgeInsets.fromLTRB(1.2.h, 0, 1.2.h, 1.2.h), - child: Column( - spacing: 0.5.h, - children: [ - for (final entry in callouts.values) - _CalloutListEntry( - callout: entry, - onTap: () => Navigator.of(context).pop(entry.id), - ), - ], - ), - ), - ), - ], - ), - ); - } -} - -class _CalloutListEntry extends StatelessWidget { - const _CalloutListEntry({required this.callout, required this.onTap}); - - final ActiveCallout callout; - final VoidCallback onTap; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - return InkWell( - borderRadius: BorderRadius.circular(16), - onTap: onTap, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 1.2.h, vertical: 1.2.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), - border: Border.all(color: Palette.line), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - spacing: 1.2.h, - children: [ - if (callout.iconUrl != null) - CircleAvatar( - radius: 2.2.h, - backgroundColor: Palette.line, - backgroundImage: NetworkImage(callout.iconUrl!), - ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - spacing: 0.3.h, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Text( - callout.title, - style: theme.textTheme.bodyMedium?.copyWith( - color: Palette.ink, - fontWeight: FontWeight.w700, - ), - ), - ), - Text( - timeago.format(callout.addedAt), - style: theme.textTheme.bodySmall?.copyWith( - color: Palette.ink.withValues(alpha: 0.45), - ), - ), - ], - ), - Text( - callout.description, - style: theme.textTheme.bodySmall?.copyWith( - color: Palette.ink.withValues(alpha: 0.65), - height: 1.4, - ), - ), - ], - ), - ), - ], - ), - ), - ); - } -} +import 'package:arbiter/features/callouts/active_callout.dart'; +import 'package:arbiter/features/callouts/callout_manager.dart'; +import 'package:arbiter/features/callouts/show_callout.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; +import 'package:timeago/timeago.dart' as timeago; + +Future showCalloutList(BuildContext context, WidgetRef ref) async { + final selectedId = await showGeneralDialog( + context: context, + barrierDismissible: true, + barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, + barrierColor: Colors.transparent, + transitionDuration: const Duration(milliseconds: 280), + pageBuilder: (_, animation, __) => + _CalloutListOverlay(animation: animation), + ); + + if (selectedId != null && context.mounted) { + await showCallout(context, ref, selectedId); + } +} + +class _CalloutListOverlay extends ConsumerWidget { + const _CalloutListOverlay({required this.animation}); + + final Animation animation; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final callouts = ref.watch(calloutManagerProvider); + + final barrierAnim = CurvedAnimation( + parent: animation, + curve: const Interval(0, 0.3, curve: Curves.easeOut), + ); + final panelAnim = CurvedAnimation( + parent: animation, + curve: const Interval(0.3, 1, curve: Curves.easeOutCubic), + ); + + return Material( + type: MaterialType.transparency, + child: Stack( + children: [ + Positioned.fill( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => Navigator.of(context).pop(), + child: AnimatedBuilder( + animation: barrierAnim, + builder: (_, __) => ColoredBox( + color: Colors.black.withValues( + alpha: 0.35 * barrierAnim.value, + ), + ), + ), + ), + ), + SafeArea( + child: Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: EdgeInsets.all(1.6.h), + child: FadeTransition( + opacity: panelAnim, + child: SlideTransition( + position: Tween( + begin: const Offset(0, 0.08), + end: Offset.zero, + ).animate(panelAnim), + child: GestureDetector( + onTap: () {}, + child: _CalloutListPanel(callouts: callouts), + ), + ), + ), + ), + ), + ), + ], + ), + ); + } +} + +class _CalloutListPanel extends StatelessWidget { + const _CalloutListPanel({required this.callouts}); + + final Map callouts; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Container( + width: double.infinity, + constraints: BoxConstraints(maxHeight: 48.h), + decoration: BoxDecoration( + color: Palette.cream, + borderRadius: BorderRadius.circular(24), + border: Border.all(color: Palette.line), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.fromLTRB(2.h, 2.h, 2.h, 1.2.h), + child: Text( + 'Notifications', + style: theme.textTheme.titleMedium?.copyWith( + color: Palette.ink, + fontWeight: FontWeight.w800, + ), + ), + ), + if (callouts.isEmpty) + Padding( + padding: EdgeInsets.fromLTRB(2.h, 0, 2.h, 2.h), + child: Text( + 'No pending notifications.', + style: theme.textTheme.bodyMedium?.copyWith( + color: Palette.ink.withValues(alpha: 0.50), + ), + ), + ) + else + Flexible( + child: SingleChildScrollView( + padding: EdgeInsets.fromLTRB(1.2.h, 0, 1.2.h, 1.2.h), + child: Column( + spacing: 0.5.h, + children: [ + for (final entry in callouts.values) + _CalloutListEntry( + callout: entry, + onTap: () => Navigator.of(context).pop(entry.id), + ), + ], + ), + ), + ), + ], + ), + ); + } +} + +class _CalloutListEntry extends StatelessWidget { + const _CalloutListEntry({required this.callout, required this.onTap}); + + final ActiveCallout callout; + final VoidCallback onTap; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return InkWell( + borderRadius: BorderRadius.circular(16), + onTap: onTap, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 1.2.h, vertical: 1.2.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + border: Border.all(color: Palette.line), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 1.2.h, + children: [ + if (callout.iconUrl != null) + CircleAvatar( + radius: 2.2.h, + backgroundColor: Palette.line, + backgroundImage: NetworkImage(callout.iconUrl!), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 0.3.h, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + callout.title, + style: theme.textTheme.bodyMedium?.copyWith( + color: Palette.ink, + fontWeight: FontWeight.w700, + ), + ), + ), + Text( + timeago.format(callout.addedAt), + style: theme.textTheme.bodySmall?.copyWith( + color: Palette.ink.withValues(alpha: 0.45), + ), + ), + ], + ), + Text( + callout.description, + style: theme.textTheme.bodySmall?.copyWith( + color: Palette.ink.withValues(alpha: 0.65), + height: 1.4, + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/useragent/lib/features/callouts/types/sdk_connect_approve.dart b/useragent/lib/features/callouts/types/sdk_connect_approve.dart index c8e9db6..bed28eb 100644 --- a/useragent/lib/features/callouts/types/sdk_connect_approve.dart +++ b/useragent/lib/features/callouts/types/sdk_connect_approve.dart @@ -1,62 +1,62 @@ -import 'dart:convert'; - -import 'package:arbiter/features/callouts/callout_event.dart'; -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/proto/user_agent.pb.dart'; -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'sdk_connect_approve.g.dart'; - -@riverpod -Stream connectApproveEvents(Ref ref) async* { - final connection = await ref.watch(connectionManagerProvider.future); - if (connection == null) return; - - await for (final message in connection.outOfBandMessages) { - switch (message.whichPayload()) { - case UserAgentResponse_Payload.sdkClient: - final sdkClientMessage = message.sdkClient; - switch (sdkClientMessage.whichPayload()) { - case ua_sdk.Response_Payload.connectionRequest: - final body = sdkClientMessage.connectionRequest; - final id = base64Encode(body.pubkey); - yield CalloutEvent.added( - id: 'connect_approve:$id', - data: CalloutData.connectApproval( - pubkey: id, - clientInfo: body.info, - ), - ); - - case ua_sdk.Response_Payload.connectionCancel: - final id = base64Encode(sdkClientMessage.connectionCancel.pubkey); - yield CalloutEvent.cancelled(id: 'connect_approve:$id'); - - default: - break; - } - - default: - break; - } - } -} - -Future sendDecision(Ref ref, String pubkey, bool approved) async { - final connection = await ref.watch(connectionManagerProvider.future); - if (connection == null) return; - - final bytes = base64Decode(pubkey); - - final req = UserAgentRequest( - sdkClient: ua_sdk.Request( - connectionResponse: ua_sdk.ConnectionResponse( - approved: approved, - pubkey: bytes, - ), - ), - ); - - await connection.tell(req); -} +import 'dart:convert'; + +import 'package:arbiter/features/callouts/callout_event.dart'; +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/proto/user_agent.pb.dart'; +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'sdk_connect_approve.g.dart'; + +@riverpod +Stream connectApproveEvents(Ref ref) async* { + final connection = await ref.watch(connectionManagerProvider.future); + if (connection == null) return; + + await for (final message in connection.outOfBandMessages) { + switch (message.whichPayload()) { + case UserAgentResponse_Payload.sdkClient: + final sdkClientMessage = message.sdkClient; + switch (sdkClientMessage.whichPayload()) { + case ua_sdk.Response_Payload.connectionRequest: + final body = sdkClientMessage.connectionRequest; + final id = base64Encode(body.pubkey); + yield CalloutEvent.added( + id: 'connect_approve:$id', + data: CalloutData.connectApproval( + pubkey: id, + clientInfo: body.info, + ), + ); + + case ua_sdk.Response_Payload.connectionCancel: + final id = base64Encode(sdkClientMessage.connectionCancel.pubkey); + yield CalloutEvent.cancelled(id: 'connect_approve:$id'); + + default: + break; + } + + default: + break; + } + } +} + +Future sendDecision(Ref ref, String pubkey, bool approved) async { + final connection = await ref.watch(connectionManagerProvider.future); + if (connection == null) return; + + final bytes = base64Decode(pubkey); + + final req = UserAgentRequest( + sdkClient: ua_sdk.Request( + connectionResponse: ua_sdk.ConnectionResponse( + approved: approved, + pubkey: bytes, + ), + ), + ); + + await connection.tell(req); +} diff --git a/useragent/lib/features/callouts/types/sdk_connect_approve.g.dart b/useragent/lib/features/callouts/types/sdk_connect_approve.g.dart index 226eb6a..1a2e289 100644 --- a/useragent/lib/features/callouts/types/sdk_connect_approve.g.dart +++ b/useragent/lib/features/callouts/types/sdk_connect_approve.g.dart @@ -1,50 +1,50 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'sdk_connect_approve.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(connectApproveEvents) -final connectApproveEventsProvider = ConnectApproveEventsProvider._(); - -final class ConnectApproveEventsProvider - extends - $FunctionalProvider< - AsyncValue, - CalloutEvent, - Stream - > - with $FutureModifier, $StreamProvider { - ConnectApproveEventsProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'connectApproveEventsProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$connectApproveEventsHash(); - - @$internal - @override - $StreamProviderElement $createElement( - $ProviderPointer pointer, - ) => $StreamProviderElement(pointer); - - @override - Stream create(Ref ref) { - return connectApproveEvents(ref); - } -} - -String _$connectApproveEventsHash() => - r'abab87cc875a9a4834f836c2c0eba4aa7671d82e'; +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'sdk_connect_approve.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(connectApproveEvents) +final connectApproveEventsProvider = ConnectApproveEventsProvider._(); + +final class ConnectApproveEventsProvider + extends + $FunctionalProvider< + AsyncValue, + CalloutEvent, + Stream + > + with $FutureModifier, $StreamProvider { + ConnectApproveEventsProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'connectApproveEventsProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$connectApproveEventsHash(); + + @$internal + @override + $StreamProviderElement $createElement( + $ProviderPointer pointer, + ) => $StreamProviderElement(pointer); + + @override + Stream create(Ref ref) { + return connectApproveEvents(ref); + } +} + +String _$connectApproveEventsHash() => + r'abab87cc875a9a4834f836c2c0eba4aa7671d82e'; diff --git a/useragent/lib/features/connection/arbiter_url.dart b/useragent/lib/features/connection/arbiter_url.dart index b6edbdf..856d50b 100644 --- a/useragent/lib/features/connection/arbiter_url.dart +++ b/useragent/lib/features/connection/arbiter_url.dart @@ -1,58 +1,58 @@ -import 'dart:convert'; - -class ArbiterUrl { - const ArbiterUrl({ - required this.host, - required this.port, - required this.caCert, - this.bootstrapToken, - }); - - final String host; - final int port; - final List caCert; - final String? bootstrapToken; - - static const _scheme = 'arbiter'; - static const _certQueryKey = 'cert'; - static const _bootstrapTokenQueryKey = 'bootstrap_token'; - - static ArbiterUrl parse(String value) { - final uri = Uri.tryParse(value); - if (uri == null || uri.scheme != _scheme) { - throw const FormatException("Invalid URL scheme, expected 'arbiter://'"); - } - - if (uri.host.isEmpty) { - throw const FormatException('Missing host in URL'); - } - - if (!uri.hasPort) { - throw const FormatException('Missing port in URL'); - } - - final cert = uri.queryParameters[_certQueryKey]; - if (cert == null || cert.isEmpty) { - throw const FormatException("Missing 'cert' query parameter in URL"); - } - - final decodedCert = _decodeCert(cert); - - return ArbiterUrl( - host: uri.host, - port: uri.port, - caCert: decodedCert, - bootstrapToken: uri.queryParameters[_bootstrapTokenQueryKey], - ); - } - - static List _decodeCert(String cert) { - try { - return base64Url.decode(base64Url.normalize(cert)); - } on FormatException catch (error) { - throw FormatException( - "Invalid base64 in 'cert' query parameter: ${error.message}", - ); - } - } -} +import 'dart:convert'; + +class ArbiterUrl { + const ArbiterUrl({ + required this.host, + required this.port, + required this.caCert, + this.bootstrapToken, + }); + + final String host; + final int port; + final List caCert; + final String? bootstrapToken; + + static const _scheme = 'arbiter'; + static const _certQueryKey = 'cert'; + static const _bootstrapTokenQueryKey = 'bootstrap_token'; + + static ArbiterUrl parse(String value) { + final uri = Uri.tryParse(value); + if (uri == null || uri.scheme != _scheme) { + throw const FormatException("Invalid URL scheme, expected 'arbiter://'"); + } + + if (uri.host.isEmpty) { + throw const FormatException('Missing host in URL'); + } + + if (!uri.hasPort) { + throw const FormatException('Missing port in URL'); + } + + final cert = uri.queryParameters[_certQueryKey]; + if (cert == null || cert.isEmpty) { + throw const FormatException("Missing 'cert' query parameter in URL"); + } + + final decodedCert = _decodeCert(cert); + + return ArbiterUrl( + host: uri.host, + port: uri.port, + caCert: decodedCert, + bootstrapToken: uri.queryParameters[_bootstrapTokenQueryKey], + ); + } + + static List _decodeCert(String cert) { + try { + return base64Url.decode(base64Url.normalize(cert)); + } on FormatException catch (error) { + throw FormatException( + "Invalid base64 in 'cert' query parameter: ${error.message}", + ); + } + } +} diff --git a/useragent/lib/features/connection/auth.dart b/useragent/lib/features/connection/auth.dart index 84cb3d9..3b54cf2 100644 --- a/useragent/lib/features/connection/auth.dart +++ b/useragent/lib/features/connection/auth.dart @@ -1,170 +1,170 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'package:arbiter/features/connection/connection.dart'; -import 'package:arbiter/features/connection/server_info_storage.dart'; -import 'package:arbiter/features/identity/pk_manager.dart'; -import 'package:arbiter/proto/arbiter.pbgrpc.dart'; -import 'package:arbiter/proto/user_agent/auth.pb.dart' as ua_auth; -import 'package:arbiter/proto/user_agent.pb.dart'; -import 'package:arbiter/src/rust/api.dart'; -import 'package:grpc/grpc.dart'; -import 'package:mtcore/markettakers.dart'; - -class AuthorizationException implements Exception { - const AuthorizationException(this.result); - - final ua_auth.AuthResult result; - - String get message => switch (result) { - ua_auth.AuthResult.AUTH_RESULT_INVALID_KEY => - 'Authentication failed: this device key is not registered on the server.', - ua_auth.AuthResult.AUTH_RESULT_INVALID_SIGNATURE => - 'Authentication failed: the server rejected the signature for this device key.', - ua_auth.AuthResult.AUTH_RESULT_BOOTSTRAP_REQUIRED => - 'Authentication failed: the server requires bootstrap before this device can connect.', - ua_auth.AuthResult.AUTH_RESULT_TOKEN_INVALID => - 'Authentication failed: the bootstrap token is invalid.', - ua_auth.AuthResult.AUTH_RESULT_INTERNAL => - 'Authentication failed: the server hit an internal error.', - ua_auth.AuthResult.AUTH_RESULT_UNSPECIFIED => - 'Authentication failed: the server returned an unspecified auth error.', - ua_auth.AuthResult.AUTH_RESULT_SUCCESS => 'Authentication succeeded.', - _ => 'Authentication failed: ${result.name}.', - }; - - @override - String toString() => message; -} - -class ConnectionException implements Exception { - const ConnectionException(this.message); - - final String message; - - @override - String toString() => message; -} - -Future connectAndAuthorize( - StoredServerInfo serverInfo, - KeyHandle key, { - String? bootstrapToken, -}) async { - Connection? connection; - try { - connection = await _connect(serverInfo); - talker.info( - 'Connected to server at ${serverInfo.address}:${serverInfo.port}', - ); - final pubkey = await key.getPublicKey(); - - final req = ua_auth.AuthChallengeRequest( - pubkey: pubkey, - bootstrapToken: bootstrapToken, - ); - final response = await connection.ask( - UserAgentRequest(auth: ua_auth.Request(challengeRequest: req)), - ); - talker.info( - "Sent auth challenge request with pubkey ${base64Encode(pubkey)}", - ); - talker.info('Received response from server, checking auth flow...'); - - if (!response.hasAuth()) { - throw ConnectionException( - 'Expected auth response, got ${response.whichPayload()}', - ); - } - - final authResponse = response.auth; - - if (authResponse.hasResult()) { - if (authResponse.result != ua_auth.AuthResult.AUTH_RESULT_SUCCESS) { - throw AuthorizationException(authResponse.result); - } - talker.info('Authentication successful, connection established'); - return connection; - } - - if (!authResponse.hasChallenge()) { - throw ConnectionException( - 'Expected auth challenge response, got ${authResponse.whichPayload()}', - ); - } - - final challenge = await formatChallenge( - random: authResponse.challenge.random, - timestamp: authResponse.challenge.timestampNanos.toInt(), - ); - talker.info( - 'Received auth challenge, signing with key ${base64Encode(pubkey)}', - ); - - final signature = await key.sign(challenge); - final solutionResponse = await connection.ask( - UserAgentRequest( - auth: ua_auth.Request( - challengeSolution: ua_auth.AuthChallengeSolution( - signature: signature, - ), - ), - ), - ); - - talker.info('Sent auth challenge solution, waiting for server response...'); - - if (!solutionResponse.hasAuth()) { - throw ConnectionException( - 'Expected auth solution response, got ${solutionResponse.whichPayload()}', - ); - } - - final authSolutionResponse = solutionResponse.auth; - - if (!authSolutionResponse.hasResult()) { - throw ConnectionException( - 'Expected auth solution result, got ${authSolutionResponse.whichPayload()}', - ); - } - if (authSolutionResponse.result != ua_auth.AuthResult.AUTH_RESULT_SUCCESS) { - throw AuthorizationException(authSolutionResponse.result); - } - - talker.info('Authentication successful, connection established'); - return connection; - } on AuthorizationException { - await connection?.close(); - rethrow; - } on GrpcError catch (error) { - await connection?.close(); - throw ConnectionException('Failed to connect to server: ${error.message}'); - } catch (e) { - await connection?.close(); - if (e is ConnectionException) { - rethrow; - } - throw ConnectionException('Failed to connect to server: $e'); - } -} - -Future _connect(StoredServerInfo serverInfo) async { - final channel = ClientChannel( - serverInfo.address, - port: serverInfo.port, - options: ChannelOptions( - connectTimeout: const Duration(seconds: 10), - credentials: ChannelCredentials.secure( - onBadCertificate: (cert, host) { - return true; - }, - ), - ), - ); - - final client = ArbiterServiceClient(channel); - final tx = StreamController(); - final rx = client.userAgent(tx.stream); - - return Connection(channel: channel, tx: tx, rx: rx); -} +import 'dart:async'; +import 'dart:convert'; + +import 'package:arbiter/features/connection/connection.dart'; +import 'package:arbiter/features/connection/server_info_storage.dart'; +import 'package:arbiter/features/identity/pk_manager.dart'; +import 'package:arbiter/proto/arbiter.pbgrpc.dart'; +import 'package:arbiter/proto/user_agent/auth.pb.dart' as ua_auth; +import 'package:arbiter/proto/user_agent.pb.dart'; +import 'package:arbiter/src/rust/api.dart'; +import 'package:grpc/grpc.dart'; +import 'package:mtcore/markettakers.dart'; + +class AuthorizationException implements Exception { + const AuthorizationException(this.result); + + final ua_auth.AuthResult result; + + String get message => switch (result) { + ua_auth.AuthResult.AUTH_RESULT_INVALID_KEY => + 'Authentication failed: this device key is not registered on the server.', + ua_auth.AuthResult.AUTH_RESULT_INVALID_SIGNATURE => + 'Authentication failed: the server rejected the signature for this device key.', + ua_auth.AuthResult.AUTH_RESULT_BOOTSTRAP_REQUIRED => + 'Authentication failed: the server requires bootstrap before this device can connect.', + ua_auth.AuthResult.AUTH_RESULT_TOKEN_INVALID => + 'Authentication failed: the bootstrap token is invalid.', + ua_auth.AuthResult.AUTH_RESULT_INTERNAL => + 'Authentication failed: the server hit an internal error.', + ua_auth.AuthResult.AUTH_RESULT_UNSPECIFIED => + 'Authentication failed: the server returned an unspecified auth error.', + ua_auth.AuthResult.AUTH_RESULT_SUCCESS => 'Authentication succeeded.', + _ => 'Authentication failed: ${result.name}.', + }; + + @override + String toString() => message; +} + +class ConnectionException implements Exception { + const ConnectionException(this.message); + + final String message; + + @override + String toString() => message; +} + +Future connectAndAuthorize( + StoredServerInfo serverInfo, + KeyHandle key, { + String? bootstrapToken, +}) async { + Connection? connection; + try { + connection = await _connect(serverInfo); + talker.info( + 'Connected to server at ${serverInfo.address}:${serverInfo.port}', + ); + final pubkey = await key.getPublicKey(); + + final req = ua_auth.AuthChallengeRequest( + pubkey: pubkey, + bootstrapToken: bootstrapToken, + ); + final response = await connection.ask( + UserAgentRequest(auth: ua_auth.Request(challengeRequest: req)), + ); + talker.info( + "Sent auth challenge request with pubkey ${base64Encode(pubkey)}", + ); + talker.info('Received response from server, checking auth flow...'); + + if (!response.hasAuth()) { + throw ConnectionException( + 'Expected auth response, got ${response.whichPayload()}', + ); + } + + final authResponse = response.auth; + + if (authResponse.hasResult()) { + if (authResponse.result != ua_auth.AuthResult.AUTH_RESULT_SUCCESS) { + throw AuthorizationException(authResponse.result); + } + talker.info('Authentication successful, connection established'); + return connection; + } + + if (!authResponse.hasChallenge()) { + throw ConnectionException( + 'Expected auth challenge response, got ${authResponse.whichPayload()}', + ); + } + + final challenge = await formatChallenge( + random: authResponse.challenge.random, + timestamp: authResponse.challenge.timestampNanos.toInt(), + ); + talker.info( + 'Received auth challenge, signing with key ${base64Encode(pubkey)}', + ); + + final signature = await key.sign(challenge); + final solutionResponse = await connection.ask( + UserAgentRequest( + auth: ua_auth.Request( + challengeSolution: ua_auth.AuthChallengeSolution( + signature: signature, + ), + ), + ), + ); + + talker.info('Sent auth challenge solution, waiting for server response...'); + + if (!solutionResponse.hasAuth()) { + throw ConnectionException( + 'Expected auth solution response, got ${solutionResponse.whichPayload()}', + ); + } + + final authSolutionResponse = solutionResponse.auth; + + if (!authSolutionResponse.hasResult()) { + throw ConnectionException( + 'Expected auth solution result, got ${authSolutionResponse.whichPayload()}', + ); + } + if (authSolutionResponse.result != ua_auth.AuthResult.AUTH_RESULT_SUCCESS) { + throw AuthorizationException(authSolutionResponse.result); + } + + talker.info('Authentication successful, connection established'); + return connection; + } on AuthorizationException { + await connection?.close(); + rethrow; + } on GrpcError catch (error) { + await connection?.close(); + throw ConnectionException('Failed to connect to server: ${error.message}'); + } catch (e) { + await connection?.close(); + if (e is ConnectionException) { + rethrow; + } + throw ConnectionException('Failed to connect to server: $e'); + } +} + +Future _connect(StoredServerInfo serverInfo) async { + final channel = ClientChannel( + serverInfo.address, + port: serverInfo.port, + options: ChannelOptions( + connectTimeout: const Duration(seconds: 10), + credentials: ChannelCredentials.secure( + onBadCertificate: (cert, host) { + return true; + }, + ), + ), + ); + + final client = ArbiterServiceClient(channel); + final tx = StreamController(); + final rx = client.userAgent(tx.stream); + + return Connection(channel: channel, tx: tx, rx: rx); +} diff --git a/useragent/lib/features/connection/connection.dart b/useragent/lib/features/connection/connection.dart index 245bb30..cbfce83 100644 --- a/useragent/lib/features/connection/connection.dart +++ b/useragent/lib/features/connection/connection.dart @@ -1,136 +1,136 @@ -import 'dart:async'; - -import 'package:arbiter/proto/user_agent.pb.dart'; -import 'package:grpc/grpc.dart'; -import 'package:mtcore/markettakers.dart'; - -class Connection { - Connection({ - required this.channel, - required StreamController tx, - required ResponseStream rx, - }) : _tx = tx { - _rxSubscription = rx.listen( - _handleResponse, - onError: _handleError, - onDone: _handleDone, - cancelOnError: true, - ); - } - - final ClientChannel channel; - final StreamController _tx; - final Map> _pendingRequests = {}; - final StreamController _outOfBandMessages = - StreamController.broadcast(); - - StreamSubscription? _rxSubscription; - int _nextRequestId = 0; - - Stream get outOfBandMessages => _outOfBandMessages.stream; - - Future ask(UserAgentRequest message) async { - _ensureOpen(); - - final requestId = _nextRequestId++; - final completer = Completer(); - _pendingRequests[requestId] = completer; - - message.id = requestId; - talker.debug('Sending request: ${message.toDebugString()}'); - - try { - _tx.add(message); - } catch (error, stackTrace) { - _pendingRequests.remove(requestId); - completer.completeError(error, stackTrace); - } - - return completer.future; - } - - Future tell(UserAgentRequest message) async { - _ensureOpen(); - - final requestId = _nextRequestId++; - message.id = requestId; - - talker.debug('Sending message: ${message.toDebugString()}'); - - try { - _tx.add(message); - } catch (error, stackTrace) { - talker.error('Failed to send message: $error', error, stackTrace); - } - } - - Future close() async { - talker.debug('Closing connection...'); - final rxSubscription = _rxSubscription; - if (rxSubscription == null) { - return; - } - - _rxSubscription = null; - await rxSubscription.cancel(); - _failPendingRequests(Exception('Connection closed.')); - await _outOfBandMessages.close(); - await _tx.close(); - await channel.shutdown(); - } - - void _handleResponse(UserAgentResponse response) { - talker.debug('Received response: ${response.toDebugString()}'); - - if (response.hasId()) { - final completer = _pendingRequests.remove(response.id); - if (completer == null) { - talker.warning( - 'Received response for unknown request id ${response.id}', - ); - return; - } - completer.complete(response); - return; - } - - _outOfBandMessages.add(response); - } - - void _handleError(Object error, StackTrace stackTrace) { - _rxSubscription = null; - _failPendingRequests(error, stackTrace); - _outOfBandMessages.addError(error, stackTrace); - } - - void _handleDone() { - talker.debug('Connection closed by server.'); - if (_rxSubscription == null) { - return; - } - - _rxSubscription = null; - final error = Exception( - 'Connection closed while waiting for server response.', - ); - _failPendingRequests(error); - _outOfBandMessages.close(); - } - - void _failPendingRequests(Object error, [StackTrace? stackTrace]) { - final pendingRequests = _pendingRequests.values.toList(growable: false); - _pendingRequests.clear(); - - for (final completer in pendingRequests) { - if (!completer.isCompleted) { - completer.completeError(error, stackTrace); - } - } - } - - void _ensureOpen() { - if (_rxSubscription == null) { - throw StateError('Connection is closed.'); - } - } -} +import 'dart:async'; + +import 'package:arbiter/proto/user_agent.pb.dart'; +import 'package:grpc/grpc.dart'; +import 'package:mtcore/markettakers.dart'; + +class Connection { + Connection({ + required this.channel, + required StreamController tx, + required ResponseStream rx, + }) : _tx = tx { + _rxSubscription = rx.listen( + _handleResponse, + onError: _handleError, + onDone: _handleDone, + cancelOnError: true, + ); + } + + final ClientChannel channel; + final StreamController _tx; + final Map> _pendingRequests = {}; + final StreamController _outOfBandMessages = + StreamController.broadcast(); + + StreamSubscription? _rxSubscription; + int _nextRequestId = 0; + + Stream get outOfBandMessages => _outOfBandMessages.stream; + + Future ask(UserAgentRequest message) async { + _ensureOpen(); + + final requestId = _nextRequestId++; + final completer = Completer(); + _pendingRequests[requestId] = completer; + + message.id = requestId; + talker.debug('Sending request: ${message.toDebugString()}'); + + try { + _tx.add(message); + } catch (error, stackTrace) { + _pendingRequests.remove(requestId); + completer.completeError(error, stackTrace); + } + + return completer.future; + } + + Future tell(UserAgentRequest message) async { + _ensureOpen(); + + final requestId = _nextRequestId++; + message.id = requestId; + + talker.debug('Sending message: ${message.toDebugString()}'); + + try { + _tx.add(message); + } catch (error, stackTrace) { + talker.error('Failed to send message: $error', error, stackTrace); + } + } + + Future close() async { + talker.debug('Closing connection...'); + final rxSubscription = _rxSubscription; + if (rxSubscription == null) { + return; + } + + _rxSubscription = null; + await rxSubscription.cancel(); + _failPendingRequests(Exception('Connection closed.')); + await _outOfBandMessages.close(); + await _tx.close(); + await channel.shutdown(); + } + + void _handleResponse(UserAgentResponse response) { + talker.debug('Received response: ${response.toDebugString()}'); + + if (response.hasId()) { + final completer = _pendingRequests.remove(response.id); + if (completer == null) { + talker.warning( + 'Received response for unknown request id ${response.id}', + ); + return; + } + completer.complete(response); + return; + } + + _outOfBandMessages.add(response); + } + + void _handleError(Object error, StackTrace stackTrace) { + _rxSubscription = null; + _failPendingRequests(error, stackTrace); + _outOfBandMessages.addError(error, stackTrace); + } + + void _handleDone() { + talker.debug('Connection closed by server.'); + if (_rxSubscription == null) { + return; + } + + _rxSubscription = null; + final error = Exception( + 'Connection closed while waiting for server response.', + ); + _failPendingRequests(error); + _outOfBandMessages.close(); + } + + void _failPendingRequests(Object error, [StackTrace? stackTrace]) { + final pendingRequests = _pendingRequests.values.toList(growable: false); + _pendingRequests.clear(); + + for (final completer in pendingRequests) { + if (!completer.isCompleted) { + completer.completeError(error, stackTrace); + } + } + } + + void _ensureOpen() { + if (_rxSubscription == null) { + throw StateError('Connection is closed.'); + } + } +} diff --git a/useragent/lib/features/connection/evm.dart b/useragent/lib/features/connection/evm.dart index 0b645c0..1159c98 100644 --- a/useragent/lib/features/connection/evm.dart +++ b/useragent/lib/features/connection/evm.dart @@ -1,67 +1,67 @@ -import 'package:arbiter/features/connection/connection.dart'; -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/proto/user_agent/evm.pb.dart' as ua_evm; -import 'package:arbiter/proto/user_agent.pb.dart'; -import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart'; - -Future> listEvmWallets(Connection connection) async { - final response = await connection.ask( - UserAgentRequest(evm: ua_evm.Request(walletList: Empty())), - ); - if (!response.hasEvm()) { - throw Exception('Expected EVM response, got ${response.whichPayload()}'); - } - - final evmResponse = response.evm; - if (!evmResponse.hasWalletList()) { - throw Exception( - 'Expected EVM wallet list response, got ${evmResponse.whichPayload()}', - ); - } - - final result = evmResponse.walletList; - switch (result.whichResult()) { - case WalletListResponse_Result.wallets: - return result.wallets.wallets.toList(growable: false); - case WalletListResponse_Result.error: - throw Exception(_describeEvmError(result.error)); - case WalletListResponse_Result.notSet: - throw Exception('EVM wallet list response was empty.'); - } -} - -Future createEvmWallet(Connection connection) async { - final response = await connection.ask( - UserAgentRequest(evm: ua_evm.Request(walletCreate: Empty())), - ); - if (!response.hasEvm()) { - throw Exception('Expected EVM response, got ${response.whichPayload()}'); - } - - final evmResponse = response.evm; - if (!evmResponse.hasWalletCreate()) { - throw Exception( - 'Expected EVM wallet create response, got ${evmResponse.whichPayload()}', - ); - } - - final result = evmResponse.walletCreate; - switch (result.whichResult()) { - case WalletCreateResponse_Result.wallet: - return; - case WalletCreateResponse_Result.error: - throw Exception(_describeEvmError(result.error)); - case WalletCreateResponse_Result.notSet: - throw Exception('Wallet creation returned no result.'); - } -} - -String _describeEvmError(EvmError error) { - return switch (error) { - EvmError.EVM_ERROR_VAULT_SEALED => - 'The vault is sealed. Unseal it before using EVM wallets.', - EvmError.EVM_ERROR_INTERNAL || EvmError.EVM_ERROR_UNSPECIFIED => - 'The server failed to process the EVM request.', - _ => 'The server failed to process the EVM request.', - }; -} +import 'package:arbiter/features/connection/connection.dart'; +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/proto/user_agent/evm.pb.dart' as ua_evm; +import 'package:arbiter/proto/user_agent.pb.dart'; +import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart'; + +Future> listEvmWallets(Connection connection) async { + final response = await connection.ask( + UserAgentRequest(evm: ua_evm.Request(walletList: Empty())), + ); + if (!response.hasEvm()) { + throw Exception('Expected EVM response, got ${response.whichPayload()}'); + } + + final evmResponse = response.evm; + if (!evmResponse.hasWalletList()) { + throw Exception( + 'Expected EVM wallet list response, got ${evmResponse.whichPayload()}', + ); + } + + final result = evmResponse.walletList; + switch (result.whichResult()) { + case WalletListResponse_Result.wallets: + return result.wallets.wallets.toList(growable: false); + case WalletListResponse_Result.error: + throw Exception(_describeEvmError(result.error)); + case WalletListResponse_Result.notSet: + throw Exception('EVM wallet list response was empty.'); + } +} + +Future createEvmWallet(Connection connection) async { + final response = await connection.ask( + UserAgentRequest(evm: ua_evm.Request(walletCreate: Empty())), + ); + if (!response.hasEvm()) { + throw Exception('Expected EVM response, got ${response.whichPayload()}'); + } + + final evmResponse = response.evm; + if (!evmResponse.hasWalletCreate()) { + throw Exception( + 'Expected EVM wallet create response, got ${evmResponse.whichPayload()}', + ); + } + + final result = evmResponse.walletCreate; + switch (result.whichResult()) { + case WalletCreateResponse_Result.wallet: + return; + case WalletCreateResponse_Result.error: + throw Exception(_describeEvmError(result.error)); + case WalletCreateResponse_Result.notSet: + throw Exception('Wallet creation returned no result.'); + } +} + +String _describeEvmError(EvmError error) { + return switch (error) { + EvmError.EVM_ERROR_VAULT_SEALED => + 'The vault is sealed. Unseal it before using EVM wallets.', + EvmError.EVM_ERROR_INTERNAL || EvmError.EVM_ERROR_UNSPECIFIED => + 'The server failed to process the EVM request.', + _ => 'The server failed to process the EVM request.', + }; +} diff --git a/useragent/lib/features/connection/evm/grants.dart b/useragent/lib/features/connection/evm/grants.dart index 7790e83..e1bf03c 100644 --- a/useragent/lib/features/connection/evm/grants.dart +++ b/useragent/lib/features/connection/evm/grants.dart @@ -1,102 +1,102 @@ -import 'package:arbiter/features/connection/connection.dart'; -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/proto/user_agent/evm.pb.dart' as ua_evm; -import 'package:arbiter/proto/user_agent.pb.dart'; - -Future> listEvmGrants(Connection connection) async { - final request = EvmGrantListRequest(); - - final response = await connection.ask( - UserAgentRequest(evm: ua_evm.Request(grantList: request)), - ); - if (!response.hasEvm()) { - throw Exception('Expected EVM response, got ${response.whichPayload()}'); - } - - final evmResponse = response.evm; - if (!evmResponse.hasGrantList()) { - throw Exception( - 'Expected EVM grant list response, got ${evmResponse.whichPayload()}', - ); - } - - final result = evmResponse.grantList; - switch (result.whichResult()) { - case EvmGrantListResponse_Result.grants: - return result.grants.grants.toList(growable: false); - case EvmGrantListResponse_Result.error: - throw Exception(_describeGrantError(result.error)); - case EvmGrantListResponse_Result.notSet: - throw Exception('EVM grant list response was empty.'); - } -} - -Future createEvmGrant( - Connection connection, { - required SharedSettings sharedSettings, - required SpecificGrant specific, -}) async { - final request = UserAgentRequest( - evm: ua_evm.Request( - grantCreate: EvmGrantCreateRequest( - shared: sharedSettings, - specific: specific, - ), - ), - ); - - final resp = await connection.ask(request); - - if (!resp.hasEvm()) { - throw Exception('Expected EVM response, got ${resp.whichPayload()}'); - } - - final evmResponse = resp.evm; - if (!evmResponse.hasGrantCreate()) { - throw Exception( - 'Expected EVM grant create response, got ${evmResponse.whichPayload()}', - ); - } - - final result = evmResponse.grantCreate; - - return result.grantId; -} - -Future deleteEvmGrant(Connection connection, int grantId) async { - final response = await connection.ask( - UserAgentRequest( - evm: ua_evm.Request(grantDelete: EvmGrantDeleteRequest(grantId: grantId)), - ), - ); - if (!response.hasEvm()) { - throw Exception('Expected EVM response, got ${response.whichPayload()}'); - } - - final evmResponse = response.evm; - if (!evmResponse.hasGrantDelete()) { - throw Exception( - 'Expected EVM grant delete response, got ${evmResponse.whichPayload()}', - ); - } - - final result = evmResponse.grantDelete; - switch (result.whichResult()) { - case EvmGrantDeleteResponse_Result.ok: - return; - case EvmGrantDeleteResponse_Result.error: - throw Exception(_describeGrantError(result.error)); - case EvmGrantDeleteResponse_Result.notSet: - throw Exception('Grant revoke returned no result.'); - } -} - -String _describeGrantError(EvmError error) { - return switch (error) { - EvmError.EVM_ERROR_VAULT_SEALED => - 'The vault is sealed. Unseal it before using EVM grants.', - EvmError.EVM_ERROR_INTERNAL || EvmError.EVM_ERROR_UNSPECIFIED => - 'The server failed to process the EVM grant request.', - _ => 'The server failed to process the EVM grant request.', - }; -} +import 'package:arbiter/features/connection/connection.dart'; +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/proto/user_agent/evm.pb.dart' as ua_evm; +import 'package:arbiter/proto/user_agent.pb.dart'; + +Future> listEvmGrants(Connection connection) async { + final request = EvmGrantListRequest(); + + final response = await connection.ask( + UserAgentRequest(evm: ua_evm.Request(grantList: request)), + ); + if (!response.hasEvm()) { + throw Exception('Expected EVM response, got ${response.whichPayload()}'); + } + + final evmResponse = response.evm; + if (!evmResponse.hasGrantList()) { + throw Exception( + 'Expected EVM grant list response, got ${evmResponse.whichPayload()}', + ); + } + + final result = evmResponse.grantList; + switch (result.whichResult()) { + case EvmGrantListResponse_Result.grants: + return result.grants.grants.toList(growable: false); + case EvmGrantListResponse_Result.error: + throw Exception(_describeGrantError(result.error)); + case EvmGrantListResponse_Result.notSet: + throw Exception('EVM grant list response was empty.'); + } +} + +Future createEvmGrant( + Connection connection, { + required SharedSettings sharedSettings, + required SpecificGrant specific, +}) async { + final request = UserAgentRequest( + evm: ua_evm.Request( + grantCreate: EvmGrantCreateRequest( + shared: sharedSettings, + specific: specific, + ), + ), + ); + + final resp = await connection.ask(request); + + if (!resp.hasEvm()) { + throw Exception('Expected EVM response, got ${resp.whichPayload()}'); + } + + final evmResponse = resp.evm; + if (!evmResponse.hasGrantCreate()) { + throw Exception( + 'Expected EVM grant create response, got ${evmResponse.whichPayload()}', + ); + } + + final result = evmResponse.grantCreate; + + return result.grantId; +} + +Future deleteEvmGrant(Connection connection, int grantId) async { + final response = await connection.ask( + UserAgentRequest( + evm: ua_evm.Request(grantDelete: EvmGrantDeleteRequest(grantId: grantId)), + ), + ); + if (!response.hasEvm()) { + throw Exception('Expected EVM response, got ${response.whichPayload()}'); + } + + final evmResponse = response.evm; + if (!evmResponse.hasGrantDelete()) { + throw Exception( + 'Expected EVM grant delete response, got ${evmResponse.whichPayload()}', + ); + } + + final result = evmResponse.grantDelete; + switch (result.whichResult()) { + case EvmGrantDeleteResponse_Result.ok: + return; + case EvmGrantDeleteResponse_Result.error: + throw Exception(_describeGrantError(result.error)); + case EvmGrantDeleteResponse_Result.notSet: + throw Exception('Grant revoke returned no result.'); + } +} + +String _describeGrantError(EvmError error) { + return switch (error) { + EvmError.EVM_ERROR_VAULT_SEALED => + 'The vault is sealed. Unseal it before using EVM grants.', + EvmError.EVM_ERROR_INTERNAL || EvmError.EVM_ERROR_UNSPECIFIED => + 'The server failed to process the EVM grant request.', + _ => 'The server failed to process the EVM grant request.', + }; +} diff --git a/useragent/lib/features/connection/evm/wallet_access.dart b/useragent/lib/features/connection/evm/wallet_access.dart index 235948a..07895fe 100644 --- a/useragent/lib/features/connection/evm/wallet_access.dart +++ b/useragent/lib/features/connection/evm/wallet_access.dart @@ -1,86 +1,86 @@ -import 'package:arbiter/features/connection/connection.dart'; -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/proto/user_agent.pb.dart'; -import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart'; - -Future> readClientWalletAccess( - Connection connection, { - required int clientId, -}) async { - final response = await connection.ask( - UserAgentRequest(sdkClient: ua_sdk.Request(listWalletAccess: Empty())), - ); - if (!response.hasSdkClient()) { - throw Exception( - 'Expected SDK client response, got ${response.whichPayload()}', - ); - } - final sdkClientResponse = response.sdkClient; - if (!sdkClientResponse.hasListWalletAccess()) { - throw Exception( - 'Expected list wallet access response, got ${sdkClientResponse.whichPayload()}', - ); - } - return { - for (final entry in sdkClientResponse.listWalletAccess.accesses) - if (entry.access.sdkClientId == clientId) entry.access.walletId, - }; -} - -Future> listAllWalletAccesses( - Connection connection, -) async { - final response = await connection.ask( - UserAgentRequest(sdkClient: ua_sdk.Request(listWalletAccess: Empty())), - ); - if (!response.hasSdkClient()) { - throw Exception( - 'Expected SDK client response, got ${response.whichPayload()}', - ); - } - final sdkClientResponse = response.sdkClient; - if (!sdkClientResponse.hasListWalletAccess()) { - throw Exception( - 'Expected list wallet access response, got ${sdkClientResponse.whichPayload()}', - ); - } - return sdkClientResponse.listWalletAccess.accesses.toList(growable: false); -} - -Future writeClientWalletAccess( - Connection connection, { - required int clientId, - required Set walletIds, -}) async { - final current = await readClientWalletAccess(connection, clientId: clientId); - - final toGrant = walletIds.difference(current); - final toRevoke = current.difference(walletIds); - - if (toGrant.isNotEmpty) { - await connection.tell( - UserAgentRequest( - sdkClient: ua_sdk.Request( - grantWalletAccess: ua_sdk.GrantWalletAccess( - accesses: [ - for (final walletId in toGrant) - ua_sdk.WalletAccess(sdkClientId: clientId, walletId: walletId), - ], - ), - ), - ), - ); - } - - if (toRevoke.isNotEmpty) { - await connection.tell( - UserAgentRequest( - sdkClient: ua_sdk.Request( - revokeWalletAccess: ua_sdk.RevokeWalletAccess( - accesses: [for (final walletId in toRevoke) walletId], - ), - ), - ), - ); - } -} +import 'package:arbiter/features/connection/connection.dart'; +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/proto/user_agent.pb.dart'; +import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart'; + +Future> readClientWalletAccess( + Connection connection, { + required int clientId, +}) async { + final response = await connection.ask( + UserAgentRequest(sdkClient: ua_sdk.Request(listWalletAccess: Empty())), + ); + if (!response.hasSdkClient()) { + throw Exception( + 'Expected SDK client response, got ${response.whichPayload()}', + ); + } + final sdkClientResponse = response.sdkClient; + if (!sdkClientResponse.hasListWalletAccess()) { + throw Exception( + 'Expected list wallet access response, got ${sdkClientResponse.whichPayload()}', + ); + } + return { + for (final entry in sdkClientResponse.listWalletAccess.accesses) + if (entry.access.sdkClientId == clientId) entry.access.walletId, + }; +} + +Future> listAllWalletAccesses( + Connection connection, +) async { + final response = await connection.ask( + UserAgentRequest(sdkClient: ua_sdk.Request(listWalletAccess: Empty())), + ); + if (!response.hasSdkClient()) { + throw Exception( + 'Expected SDK client response, got ${response.whichPayload()}', + ); + } + final sdkClientResponse = response.sdkClient; + if (!sdkClientResponse.hasListWalletAccess()) { + throw Exception( + 'Expected list wallet access response, got ${sdkClientResponse.whichPayload()}', + ); + } + return sdkClientResponse.listWalletAccess.accesses.toList(growable: false); +} + +Future writeClientWalletAccess( + Connection connection, { + required int clientId, + required Set walletIds, +}) async { + final current = await readClientWalletAccess(connection, clientId: clientId); + + final toGrant = walletIds.difference(current); + final toRevoke = current.difference(walletIds); + + if (toGrant.isNotEmpty) { + await connection.tell( + UserAgentRequest( + sdkClient: ua_sdk.Request( + grantWalletAccess: ua_sdk.GrantWalletAccess( + accesses: [ + for (final walletId in toGrant) + ua_sdk.WalletAccess(sdkClientId: clientId, walletId: walletId), + ], + ), + ), + ), + ); + } + + if (toRevoke.isNotEmpty) { + await connection.tell( + UserAgentRequest( + sdkClient: ua_sdk.Request( + revokeWalletAccess: ua_sdk.RevokeWalletAccess( + accesses: [for (final walletId in toRevoke) walletId], + ), + ), + ), + ); + } +} diff --git a/useragent/lib/features/connection/server_info_storage.dart b/useragent/lib/features/connection/server_info_storage.dart index 27ed5ad..b86f984 100644 --- a/useragent/lib/features/connection/server_info_storage.dart +++ b/useragent/lib/features/connection/server_info_storage.dart @@ -1,62 +1,62 @@ -import 'dart:convert'; - -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:json_annotation/json_annotation.dart'; - -part 'server_info_storage.g.dart'; - -@JsonSerializable() -class StoredServerInfo { - const StoredServerInfo({ - required this.address, - required this.port, - required this.caCertFingerprint, - }); - - final String address; - final int port; - final String caCertFingerprint; - - factory StoredServerInfo.fromJson(Map json) => - _$StoredServerInfoFromJson(json); - Map toJson() => _$StoredServerInfoToJson(this); -} - -abstract class ServerInfoStorage { - Future load(); - Future save(StoredServerInfo serverInfo); - Future clear(); -} - -class SecureServerInfoStorage implements ServerInfoStorage { - static const _storageKey = 'server_info'; - - const SecureServerInfoStorage(); - - static const _storage = FlutterSecureStorage(); - - @override - Future load() async { - return null; - final rawValue = await _storage.read(key: _storageKey); - if (rawValue == null) { - return null; - } - - final decoded = jsonDecode(rawValue) as Map; - return StoredServerInfo.fromJson(decoded); - } - - @override - Future save(StoredServerInfo serverInfo) { - return _storage.write( - key: _storageKey, - value: jsonEncode(serverInfo.toJson()), - ); - } - - @override - Future clear() { - return _storage.delete(key: _storageKey); - } -} +import 'dart:convert'; + +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'server_info_storage.g.dart'; + +@JsonSerializable() +class StoredServerInfo { + const StoredServerInfo({ + required this.address, + required this.port, + required this.caCertFingerprint, + }); + + final String address; + final int port; + final String caCertFingerprint; + + factory StoredServerInfo.fromJson(Map json) => + _$StoredServerInfoFromJson(json); + Map toJson() => _$StoredServerInfoToJson(this); +} + +abstract class ServerInfoStorage { + Future load(); + Future save(StoredServerInfo serverInfo); + Future clear(); +} + +class SecureServerInfoStorage implements ServerInfoStorage { + static const _storageKey = 'server_info'; + + const SecureServerInfoStorage(); + + static const _storage = FlutterSecureStorage(); + + @override + Future load() async { + return null; + final rawValue = await _storage.read(key: _storageKey); + if (rawValue == null) { + return null; + } + + final decoded = jsonDecode(rawValue) as Map; + return StoredServerInfo.fromJson(decoded); + } + + @override + Future save(StoredServerInfo serverInfo) { + return _storage.write( + key: _storageKey, + value: jsonEncode(serverInfo.toJson()), + ); + } + + @override + Future clear() { + return _storage.delete(key: _storageKey); + } +} diff --git a/useragent/lib/features/connection/server_info_storage.g.dart b/useragent/lib/features/connection/server_info_storage.g.dart index fcd0018..41218c9 100644 --- a/useragent/lib/features/connection/server_info_storage.g.dart +++ b/useragent/lib/features/connection/server_info_storage.g.dart @@ -1,21 +1,21 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'server_info_storage.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -StoredServerInfo _$StoredServerInfoFromJson(Map json) => - StoredServerInfo( - address: json['address'] as String, - port: (json['port'] as num).toInt(), - caCertFingerprint: json['caCertFingerprint'] as String, - ); - -Map _$StoredServerInfoToJson(StoredServerInfo instance) => - { - 'address': instance.address, - 'port': instance.port, - 'caCertFingerprint': instance.caCertFingerprint, - }; +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'server_info_storage.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +StoredServerInfo _$StoredServerInfoFromJson(Map json) => + StoredServerInfo( + address: json['address'] as String, + port: (json['port'] as num).toInt(), + caCertFingerprint: json['caCertFingerprint'] as String, + ); + +Map _$StoredServerInfoToJson(StoredServerInfo instance) => + { + 'address': instance.address, + 'port': instance.port, + 'caCertFingerprint': instance.caCertFingerprint, + }; diff --git a/useragent/lib/features/connection/vault.dart b/useragent/lib/features/connection/vault.dart index 79bc6a1..56a42f9 100644 --- a/useragent/lib/features/connection/vault.dart +++ b/useragent/lib/features/connection/vault.dart @@ -1,160 +1,160 @@ -import 'package:arbiter/features/connection/connection.dart'; -import 'package:arbiter/proto/user_agent/vault/bootstrap.pb.dart' - as ua_bootstrap; -import 'package:arbiter/proto/user_agent/vault/unseal.pb.dart' as ua_unseal; -import 'package:arbiter/proto/user_agent/vault/vault.pb.dart' as ua_vault; -import 'package:arbiter/proto/user_agent.pb.dart'; -import 'package:cryptography/cryptography.dart'; - -const _vaultKeyAssociatedData = 'arbiter.vault.password'; - -Future bootstrapVault( - Connection connection, - String password, -) async { - final encryptedKey = await _encryptVaultKeyMaterial(connection, password); - - final response = await connection.ask( - UserAgentRequest( - vault: ua_vault.Request( - bootstrap: ua_bootstrap.Request( - encryptedKey: ua_bootstrap.BootstrapEncryptedKey( - nonce: encryptedKey.nonce, - ciphertext: encryptedKey.ciphertext, - associatedData: encryptedKey.associatedData, - ), - ), - ), - ), - ); - if (!response.hasVault()) { - throw Exception('Expected vault response, got ${response.whichPayload()}'); - } - - final vaultResponse = response.vault; - if (!vaultResponse.hasBootstrap()) { - throw Exception( - 'Expected bootstrap result, got ${vaultResponse.whichPayload()}', - ); - } - - final bootstrapResponse = vaultResponse.bootstrap; - if (!bootstrapResponse.hasResult()) { - throw Exception('Expected bootstrap result payload.'); - } - - return bootstrapResponse.result; -} - -Future unsealVault( - Connection connection, - String password, -) async { - final encryptedKey = await _encryptVaultKeyMaterial(connection, password); - - final response = await connection.ask( - UserAgentRequest( - vault: ua_vault.Request( - unseal: ua_unseal.Request( - encryptedKey: ua_unseal.UnsealEncryptedKey( - nonce: encryptedKey.nonce, - ciphertext: encryptedKey.ciphertext, - associatedData: encryptedKey.associatedData, - ), - ), - ), - ), - ); - if (!response.hasVault()) { - throw Exception('Expected vault response, got ${response.whichPayload()}'); - } - - final vaultResponse = response.vault; - if (!vaultResponse.hasUnseal()) { - throw Exception( - 'Expected unseal result, got ${vaultResponse.whichPayload()}', - ); - } - - final unsealResponse = vaultResponse.unseal; - if (!unsealResponse.hasResult()) { - throw Exception( - 'Expected unseal result payload, got ${unsealResponse.whichPayload()}', - ); - } - - return unsealResponse.result; -} - -Future<_EncryptedVaultKey> _encryptVaultKeyMaterial( - Connection connection, - String password, -) async { - final keyExchange = X25519(); - final cipher = Xchacha20.poly1305Aead(); - final clientKeyPair = await keyExchange.newKeyPair(); - final clientPublicKey = await clientKeyPair.extractPublicKey(); - - final handshakeResponse = await connection.ask( - UserAgentRequest( - vault: ua_vault.Request( - unseal: ua_unseal.Request( - start: ua_unseal.UnsealStart(clientPubkey: clientPublicKey.bytes), - ), - ), - ), - ); - if (!handshakeResponse.hasVault()) { - throw Exception( - 'Expected vault response, got ${handshakeResponse.whichPayload()}', - ); - } - - final vaultResponse = handshakeResponse.vault; - if (!vaultResponse.hasUnseal()) { - throw Exception( - 'Expected unseal handshake response, got ${vaultResponse.whichPayload()}', - ); - } - - final unsealResponse = vaultResponse.unseal; - if (!unsealResponse.hasStart()) { - throw Exception( - 'Expected unseal handshake payload, got ${unsealResponse.whichPayload()}', - ); - } - - final serverPublicKey = SimplePublicKey( - unsealResponse.start.serverPubkey, - type: KeyPairType.x25519, - ); - final sharedSecret = await keyExchange.sharedSecretKey( - keyPair: clientKeyPair, - remotePublicKey: serverPublicKey, - ); - - final secretBox = await cipher.encrypt( - password.codeUnits, - secretKey: sharedSecret, - nonce: cipher.newNonce(), - aad: _vaultKeyAssociatedData.codeUnits, - ); - - return _EncryptedVaultKey( - nonce: secretBox.nonce, - ciphertext: [...secretBox.cipherText, ...secretBox.mac.bytes], - associatedData: _vaultKeyAssociatedData.codeUnits, - ); -} - -class _EncryptedVaultKey { - const _EncryptedVaultKey({ - required this.nonce, - required this.ciphertext, - required this.associatedData, - }); - - final List nonce; - final List ciphertext; - final List associatedData; -} +import 'package:arbiter/features/connection/connection.dart'; +import 'package:arbiter/proto/user_agent/vault/bootstrap.pb.dart' + as ua_bootstrap; +import 'package:arbiter/proto/user_agent/vault/unseal.pb.dart' as ua_unseal; +import 'package:arbiter/proto/user_agent/vault/vault.pb.dart' as ua_vault; +import 'package:arbiter/proto/user_agent.pb.dart'; +import 'package:cryptography/cryptography.dart'; + +const _vaultKeyAssociatedData = 'arbiter.vault.password'; + +Future bootstrapVault( + Connection connection, + String password, +) async { + final encryptedKey = await _encryptVaultKeyMaterial(connection, password); + + final response = await connection.ask( + UserAgentRequest( + vault: ua_vault.Request( + bootstrap: ua_bootstrap.Request( + encryptedKey: ua_bootstrap.BootstrapEncryptedKey( + nonce: encryptedKey.nonce, + ciphertext: encryptedKey.ciphertext, + associatedData: encryptedKey.associatedData, + ), + ), + ), + ), + ); + if (!response.hasVault()) { + throw Exception('Expected vault response, got ${response.whichPayload()}'); + } + + final vaultResponse = response.vault; + if (!vaultResponse.hasBootstrap()) { + throw Exception( + 'Expected bootstrap result, got ${vaultResponse.whichPayload()}', + ); + } + + final bootstrapResponse = vaultResponse.bootstrap; + if (!bootstrapResponse.hasResult()) { + throw Exception('Expected bootstrap result payload.'); + } + + return bootstrapResponse.result; +} + +Future unsealVault( + Connection connection, + String password, +) async { + final encryptedKey = await _encryptVaultKeyMaterial(connection, password); + + final response = await connection.ask( + UserAgentRequest( + vault: ua_vault.Request( + unseal: ua_unseal.Request( + encryptedKey: ua_unseal.UnsealEncryptedKey( + nonce: encryptedKey.nonce, + ciphertext: encryptedKey.ciphertext, + associatedData: encryptedKey.associatedData, + ), + ), + ), + ), + ); + if (!response.hasVault()) { + throw Exception('Expected vault response, got ${response.whichPayload()}'); + } + + final vaultResponse = response.vault; + if (!vaultResponse.hasUnseal()) { + throw Exception( + 'Expected unseal result, got ${vaultResponse.whichPayload()}', + ); + } + + final unsealResponse = vaultResponse.unseal; + if (!unsealResponse.hasResult()) { + throw Exception( + 'Expected unseal result payload, got ${unsealResponse.whichPayload()}', + ); + } + + return unsealResponse.result; +} + +Future<_EncryptedVaultKey> _encryptVaultKeyMaterial( + Connection connection, + String password, +) async { + final keyExchange = X25519(); + final cipher = Xchacha20.poly1305Aead(); + final clientKeyPair = await keyExchange.newKeyPair(); + final clientPublicKey = await clientKeyPair.extractPublicKey(); + + final handshakeResponse = await connection.ask( + UserAgentRequest( + vault: ua_vault.Request( + unseal: ua_unseal.Request( + start: ua_unseal.UnsealStart(clientPubkey: clientPublicKey.bytes), + ), + ), + ), + ); + if (!handshakeResponse.hasVault()) { + throw Exception( + 'Expected vault response, got ${handshakeResponse.whichPayload()}', + ); + } + + final vaultResponse = handshakeResponse.vault; + if (!vaultResponse.hasUnseal()) { + throw Exception( + 'Expected unseal handshake response, got ${vaultResponse.whichPayload()}', + ); + } + + final unsealResponse = vaultResponse.unseal; + if (!unsealResponse.hasStart()) { + throw Exception( + 'Expected unseal handshake payload, got ${unsealResponse.whichPayload()}', + ); + } + + final serverPublicKey = SimplePublicKey( + unsealResponse.start.serverPubkey, + type: KeyPairType.x25519, + ); + final sharedSecret = await keyExchange.sharedSecretKey( + keyPair: clientKeyPair, + remotePublicKey: serverPublicKey, + ); + + final secretBox = await cipher.encrypt( + password.codeUnits, + secretKey: sharedSecret, + nonce: cipher.newNonce(), + aad: _vaultKeyAssociatedData.codeUnits, + ); + + return _EncryptedVaultKey( + nonce: secretBox.nonce, + ciphertext: [...secretBox.cipherText, ...secretBox.mac.bytes], + associatedData: _vaultKeyAssociatedData.codeUnits, + ); +} + +class _EncryptedVaultKey { + const _EncryptedVaultKey({ + required this.nonce, + required this.ciphertext, + required this.associatedData, + }); + + final List nonce; + final List ciphertext; + final List associatedData; +} diff --git a/useragent/lib/features/identity/hazmat_mldsa.dart b/useragent/lib/features/identity/hazmat_mldsa.dart index 682a69b..fd266e6 100644 --- a/useragent/lib/features/identity/hazmat_mldsa.dart +++ b/useragent/lib/features/identity/hazmat_mldsa.dart @@ -1,71 +1,71 @@ -import 'dart:convert'; - -import 'package:arbiter/src/rust/api.dart'; -import 'package:cryptography/cryptography.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:arbiter/features/identity/pk_manager.dart'; - -final storage = FlutterSecureStorage( - aOptions: AndroidOptions.biometric( - enforceBiometrics: true, - biometricPromptTitle: 'Authentication Required', - ), - mOptions: MacOsOptions( - accessibility: KeychainAccessibility.unlocked_this_device, - label: "Arbiter", - description: "Confirm your identity to access vault", - synchronizable: false, - accessControlFlags: [AccessControlFlag.userPresence], - usesDataProtectionKeychain: true, - ), -); - -class HazmatMldsa extends KeyHandle { - final MldsaKey _key; - - HazmatMldsa({required MldsaKey key}) : _key = key; - - @override - Future> getPublicKey() async { - final publicKey = await _key.getPublicKey(); - return publicKey; - } - - @override - Future> sign(List data) async { - final signature = await _key.sign(message: data); - return signature; - } -} - -class HazmatMLDSAManager extends KeyManager { - static const _storageKey = "ed25519_identity"; - - @override - Future create() async { - final storedKey = await get(); - if (storedKey != null) { - return storedKey; - } - - final newKeypair = await MldsaKey.generate(); - final keyBytes = await newKeypair.toBytes(); - - await storage.write(key: _storageKey, value: base64Encode(keyBytes)); - - return HazmatMldsa(key: newKeypair); - } - - @override - Future get() async { - final storedKeyPair = await storage.read(key: _storageKey); - if (storedKeyPair == null) { - return null; - } - - final keyBytes = base64Decode(storedKeyPair); - final key = await MldsaKey.fromBytes(bytes: keyBytes); - - return HazmatMldsa(key: key); - } -} +import 'dart:convert'; + +import 'package:arbiter/src/rust/api.dart'; +import 'package:cryptography/cryptography.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:arbiter/features/identity/pk_manager.dart'; + +final storage = FlutterSecureStorage( + aOptions: AndroidOptions.biometric( + enforceBiometrics: true, + biometricPromptTitle: 'Authentication Required', + ), + mOptions: MacOsOptions( + accessibility: KeychainAccessibility.unlocked_this_device, + label: "Arbiter", + description: "Confirm your identity to access vault", + synchronizable: false, + accessControlFlags: [AccessControlFlag.userPresence], + usesDataProtectionKeychain: true, + ), +); + +class HazmatMldsa extends KeyHandle { + final MldsaKey _key; + + HazmatMldsa({required MldsaKey key}) : _key = key; + + @override + Future> getPublicKey() async { + final publicKey = await _key.getPublicKey(); + return publicKey; + } + + @override + Future> sign(List data) async { + final signature = await _key.sign(message: data); + return signature; + } +} + +class HazmatMLDSAManager extends KeyManager { + static const _storageKey = "ed25519_identity"; + + @override + Future create() async { + final storedKey = await get(); + if (storedKey != null) { + return storedKey; + } + + final newKeypair = await MldsaKey.generate(); + final keyBytes = await newKeypair.toBytes(); + + await storage.write(key: _storageKey, value: base64Encode(keyBytes)); + + return HazmatMldsa(key: newKeypair); + } + + @override + Future get() async { + final storedKeyPair = await storage.read(key: _storageKey); + if (storedKeyPair == null) { + return null; + } + + final keyBytes = base64Decode(storedKeyPair); + final key = await MldsaKey.fromBytes(bytes: keyBytes); + + return HazmatMldsa(key: key); + } +} diff --git a/useragent/lib/features/identity/pk_manager.dart b/useragent/lib/features/identity/pk_manager.dart index d0ecb9f..337d850 100644 --- a/useragent/lib/features/identity/pk_manager.dart +++ b/useragent/lib/features/identity/pk_manager.dart @@ -1,11 +1,11 @@ -// The API to handle without storing the private key in memory. -//The implementation will use platform-specific secure storage and signing capabilities. -abstract class KeyHandle { - Future> sign(List data); - Future> getPublicKey(); -} - -abstract class KeyManager { - Future get(); - Future create(); -} +// The API to handle without storing the private key in memory. +//The implementation will use platform-specific secure storage and signing capabilities. +abstract class KeyHandle { + Future> sign(List data); + Future> getPublicKey(); +} + +abstract class KeyManager { + Future get(); + Future create(); +} diff --git a/useragent/lib/main.dart b/useragent/lib/main.dart index d361cdb..723df60 100644 --- a/useragent/lib/main.dart +++ b/useragent/lib/main.dart @@ -1,39 +1,39 @@ -import 'package:arbiter/router.dart'; -import 'package:arbiter/src/rust/frb_generated.dart'; -import 'package:flutter/material.dart' hide Router; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -Future main() async { - WidgetsFlutterBinding.ensureInitialized(); - await RustLib.init(); - runApp(const ProviderScope(child: App())); -} - -class App extends StatefulWidget { - const App({super.key}); - - @override - State createState() => _AppState(); -} - -class _AppState extends State { - late final Router _router; - - @override - void initState() { - super.initState(); - _router = Router(); - } - - @override - Widget build(BuildContext context) { - return Sizer( - builder: (context, orientation, deviceType) { - return MaterialApp.router(routerConfig: _router.config()); - }, - ); - } -} - - +import 'package:arbiter/router.dart'; +import 'package:arbiter/src/rust/frb_generated.dart'; +import 'package:flutter/material.dart' hide Router; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + await RustLib.init(); + runApp(const ProviderScope(child: App())); +} + +class App extends StatefulWidget { + const App({super.key}); + + @override + State createState() => _AppState(); +} + +class _AppState extends State { + late final Router _router; + + @override + void initState() { + super.initState(); + _router = Router(); + } + + @override + Widget build(BuildContext context) { + return Sizer( + builder: (context, orientation, deviceType) { + return MaterialApp.router(routerConfig: _router.config()); + }, + ); + } +} + + diff --git a/useragent/lib/proto/arbiter.pb.dart b/useragent/lib/proto/arbiter.pb.dart index 58ca420..4cabbee 100644 --- a/useragent/lib/proto/arbiter.pb.dart +++ b/useragent/lib/proto/arbiter.pb.dart @@ -1,88 +1,88 @@ -// This is a generated file - do not edit. -// -// Generated from arbiter.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -class ServerInfo extends $pb.GeneratedMessage { - factory ServerInfo({ - $core.String? version, - $core.List<$core.int>? certPublicKey, - }) { - final result = create(); - if (version != null) result.version = version; - if (certPublicKey != null) result.certPublicKey = certPublicKey; - return result; - } - - ServerInfo._(); - - factory ServerInfo.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory ServerInfo.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'ServerInfo', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter'), - createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'version') - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'certPublicKey', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ServerInfo clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ServerInfo copyWith(void Function(ServerInfo) updates) => - super.copyWith((message) => updates(message as ServerInfo)) as ServerInfo; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static ServerInfo create() => ServerInfo._(); - @$core.override - ServerInfo createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static ServerInfo getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static ServerInfo? _defaultInstance; - - @$pb.TagNumber(1) - $core.String get version => $_getSZ(0); - @$pb.TagNumber(1) - set version($core.String value) => $_setString(0, value); - @$pb.TagNumber(1) - $core.bool hasVersion() => $_has(0); - @$pb.TagNumber(1) - void clearVersion() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get certPublicKey => $_getN(1); - @$pb.TagNumber(2) - set certPublicKey($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasCertPublicKey() => $_has(1); - @$pb.TagNumber(2) - void clearCertPublicKey() => $_clearField(2); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from arbiter.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +class ServerInfo extends $pb.GeneratedMessage { + factory ServerInfo({ + $core.String? version, + $core.List<$core.int>? certPublicKey, + }) { + final result = create(); + if (version != null) result.version = version; + if (certPublicKey != null) result.certPublicKey = certPublicKey; + return result; + } + + ServerInfo._(); + + factory ServerInfo.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory ServerInfo.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ServerInfo', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter'), + createEmptyInstance: create) + ..aOS(1, _omitFieldNames ? '' : 'version') + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'certPublicKey', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ServerInfo clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ServerInfo copyWith(void Function(ServerInfo) updates) => + super.copyWith((message) => updates(message as ServerInfo)) as ServerInfo; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ServerInfo create() => ServerInfo._(); + @$core.override + ServerInfo createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static ServerInfo getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static ServerInfo? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get version => $_getSZ(0); + @$pb.TagNumber(1) + set version($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasVersion() => $_has(0); + @$pb.TagNumber(1) + void clearVersion() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get certPublicKey => $_getN(1); + @$pb.TagNumber(2) + set certPublicKey($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasCertPublicKey() => $_has(1); + @$pb.TagNumber(2) + void clearCertPublicKey() => $_clearField(2); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/arbiter.pbenum.dart b/useragent/lib/proto/arbiter.pbenum.dart index f68d099..aa2975d 100644 --- a/useragent/lib/proto/arbiter.pbenum.dart +++ b/useragent/lib/proto/arbiter.pbenum.dart @@ -1,11 +1,11 @@ -// This is a generated file - do not edit. -// -// Generated from arbiter.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// This is a generated file - do not edit. +// +// Generated from arbiter.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports diff --git a/useragent/lib/proto/arbiter.pbgrpc.dart b/useragent/lib/proto/arbiter.pbgrpc.dart index 4cc66b9..4c7c6f4 100644 --- a/useragent/lib/proto/arbiter.pbgrpc.dart +++ b/useragent/lib/proto/arbiter.pbgrpc.dart @@ -1,90 +1,90 @@ -// This is a generated file - do not edit. -// -// Generated from arbiter.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:async' as $async; -import 'dart:core' as $core; - -import 'package:grpc/service_api.dart' as $grpc; -import 'package:protobuf/protobuf.dart' as $pb; - -import 'client.pb.dart' as $0; -import 'user_agent.pb.dart' as $1; - -export 'arbiter.pb.dart'; - -@$pb.GrpcServiceName('arbiter.ArbiterService') -class ArbiterServiceClient extends $grpc.Client { - /// The hostname for this service. - static const $core.String defaultHost = ''; - - /// OAuth scopes needed for the client. - static const $core.List<$core.String> oauthScopes = [ - '', - ]; - - ArbiterServiceClient(super.channel, {super.options, super.interceptors}); - - $grpc.ResponseStream<$0.ClientResponse> client( - $async.Stream<$0.ClientRequest> request, { - $grpc.CallOptions? options, - }) { - return $createStreamingCall(_$client, request, options: options); - } - - $grpc.ResponseStream<$1.UserAgentResponse> userAgent( - $async.Stream<$1.UserAgentRequest> request, { - $grpc.CallOptions? options, - }) { - return $createStreamingCall(_$userAgent, request, options: options); - } - - // method descriptors - - static final _$client = - $grpc.ClientMethod<$0.ClientRequest, $0.ClientResponse>( - '/arbiter.ArbiterService/Client', - ($0.ClientRequest value) => value.writeToBuffer(), - $0.ClientResponse.fromBuffer); - static final _$userAgent = - $grpc.ClientMethod<$1.UserAgentRequest, $1.UserAgentResponse>( - '/arbiter.ArbiterService/UserAgent', - ($1.UserAgentRequest value) => value.writeToBuffer(), - $1.UserAgentResponse.fromBuffer); -} - -@$pb.GrpcServiceName('arbiter.ArbiterService') -abstract class ArbiterServiceBase extends $grpc.Service { - $core.String get $name => 'arbiter.ArbiterService'; - - ArbiterServiceBase() { - $addMethod($grpc.ServiceMethod<$0.ClientRequest, $0.ClientResponse>( - 'Client', - client, - true, - true, - ($core.List<$core.int> value) => $0.ClientRequest.fromBuffer(value), - ($0.ClientResponse value) => value.writeToBuffer())); - $addMethod($grpc.ServiceMethod<$1.UserAgentRequest, $1.UserAgentResponse>( - 'UserAgent', - userAgent, - true, - true, - ($core.List<$core.int> value) => $1.UserAgentRequest.fromBuffer(value), - ($1.UserAgentResponse value) => value.writeToBuffer())); - } - - $async.Stream<$0.ClientResponse> client( - $grpc.ServiceCall call, $async.Stream<$0.ClientRequest> request); - - $async.Stream<$1.UserAgentResponse> userAgent( - $grpc.ServiceCall call, $async.Stream<$1.UserAgentRequest> request); -} +// This is a generated file - do not edit. +// +// Generated from arbiter.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:async' as $async; +import 'dart:core' as $core; + +import 'package:grpc/service_api.dart' as $grpc; +import 'package:protobuf/protobuf.dart' as $pb; + +import 'client.pb.dart' as $0; +import 'user_agent.pb.dart' as $1; + +export 'arbiter.pb.dart'; + +@$pb.GrpcServiceName('arbiter.ArbiterService') +class ArbiterServiceClient extends $grpc.Client { + /// The hostname for this service. + static const $core.String defaultHost = ''; + + /// OAuth scopes needed for the client. + static const $core.List<$core.String> oauthScopes = [ + '', + ]; + + ArbiterServiceClient(super.channel, {super.options, super.interceptors}); + + $grpc.ResponseStream<$0.ClientResponse> client( + $async.Stream<$0.ClientRequest> request, { + $grpc.CallOptions? options, + }) { + return $createStreamingCall(_$client, request, options: options); + } + + $grpc.ResponseStream<$1.UserAgentResponse> userAgent( + $async.Stream<$1.UserAgentRequest> request, { + $grpc.CallOptions? options, + }) { + return $createStreamingCall(_$userAgent, request, options: options); + } + + // method descriptors + + static final _$client = + $grpc.ClientMethod<$0.ClientRequest, $0.ClientResponse>( + '/arbiter.ArbiterService/Client', + ($0.ClientRequest value) => value.writeToBuffer(), + $0.ClientResponse.fromBuffer); + static final _$userAgent = + $grpc.ClientMethod<$1.UserAgentRequest, $1.UserAgentResponse>( + '/arbiter.ArbiterService/UserAgent', + ($1.UserAgentRequest value) => value.writeToBuffer(), + $1.UserAgentResponse.fromBuffer); +} + +@$pb.GrpcServiceName('arbiter.ArbiterService') +abstract class ArbiterServiceBase extends $grpc.Service { + $core.String get $name => 'arbiter.ArbiterService'; + + ArbiterServiceBase() { + $addMethod($grpc.ServiceMethod<$0.ClientRequest, $0.ClientResponse>( + 'Client', + client, + true, + true, + ($core.List<$core.int> value) => $0.ClientRequest.fromBuffer(value), + ($0.ClientResponse value) => value.writeToBuffer())); + $addMethod($grpc.ServiceMethod<$1.UserAgentRequest, $1.UserAgentResponse>( + 'UserAgent', + userAgent, + true, + true, + ($core.List<$core.int> value) => $1.UserAgentRequest.fromBuffer(value), + ($1.UserAgentResponse value) => value.writeToBuffer())); + } + + $async.Stream<$0.ClientResponse> client( + $grpc.ServiceCall call, $async.Stream<$0.ClientRequest> request); + + $async.Stream<$1.UserAgentResponse> userAgent( + $grpc.ServiceCall call, $async.Stream<$1.UserAgentRequest> request); +} diff --git a/useragent/lib/proto/arbiter.pbjson.dart b/useragent/lib/proto/arbiter.pbjson.dart index d93bf39..d22a63a 100644 --- a/useragent/lib/proto/arbiter.pbjson.dart +++ b/useragent/lib/proto/arbiter.pbjson.dart @@ -1,30 +1,30 @@ -// This is a generated file - do not edit. -// -// Generated from arbiter.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use serverInfoDescriptor instead') -const ServerInfo$json = { - '1': 'ServerInfo', - '2': [ - {'1': 'version', '3': 1, '4': 1, '5': 9, '10': 'version'}, - {'1': 'cert_public_key', '3': 2, '4': 1, '5': 12, '10': 'certPublicKey'}, - ], -}; - -/// Descriptor for `ServerInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List serverInfoDescriptor = $convert.base64Decode( - 'CgpTZXJ2ZXJJbmZvEhgKB3ZlcnNpb24YASABKAlSB3ZlcnNpb24SJgoPY2VydF9wdWJsaWNfa2' - 'V5GAIgASgMUg1jZXJ0UHVibGljS2V5'); +// This is a generated file - do not edit. +// +// Generated from arbiter.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use serverInfoDescriptor instead') +const ServerInfo$json = { + '1': 'ServerInfo', + '2': [ + {'1': 'version', '3': 1, '4': 1, '5': 9, '10': 'version'}, + {'1': 'cert_public_key', '3': 2, '4': 1, '5': 12, '10': 'certPublicKey'}, + ], +}; + +/// Descriptor for `ServerInfo`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List serverInfoDescriptor = $convert.base64Decode( + 'CgpTZXJ2ZXJJbmZvEhgKB3ZlcnNpb24YASABKAlSB3ZlcnNpb24SJgoPY2VydF9wdWJsaWNfa2' + 'V5GAIgASgMUg1jZXJ0UHVibGljS2V5'); diff --git a/useragent/lib/proto/client.pb.dart b/useragent/lib/proto/client.pb.dart index 69cc082..22f761b 100644 --- a/useragent/lib/proto/client.pb.dart +++ b/useragent/lib/proto/client.pb.dart @@ -1,264 +1,264 @@ -// This is a generated file - do not edit. -// -// Generated from client.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -import 'client/auth.pb.dart' as $0; -import 'client/evm.pb.dart' as $2; -import 'client/vault.pb.dart' as $1; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -enum ClientRequest_Payload { auth, vault, evm, notSet } - -class ClientRequest extends $pb.GeneratedMessage { - factory ClientRequest({ - $0.Request? auth, - $1.Request? vault, - $2.Request? evm, - $core.int? requestId, - }) { - final result = create(); - if (auth != null) result.auth = auth; - if (vault != null) result.vault = vault; - if (evm != null) result.evm = evm; - if (requestId != null) result.requestId = requestId; - return result; - } - - ClientRequest._(); - - factory ClientRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory ClientRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, ClientRequest_Payload> - _ClientRequest_PayloadByTag = { - 1: ClientRequest_Payload.auth, - 2: ClientRequest_Payload.vault, - 3: ClientRequest_Payload.evm, - 0: ClientRequest_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'ClientRequest', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3]) - ..aOM<$0.Request>(1, _omitFieldNames ? '' : 'auth', - subBuilder: $0.Request.create) - ..aOM<$1.Request>(2, _omitFieldNames ? '' : 'vault', - subBuilder: $1.Request.create) - ..aOM<$2.Request>(3, _omitFieldNames ? '' : 'evm', - subBuilder: $2.Request.create) - ..aI(4, _omitFieldNames ? '' : 'requestId') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ClientRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ClientRequest copyWith(void Function(ClientRequest) updates) => - super.copyWith((message) => updates(message as ClientRequest)) - as ClientRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static ClientRequest create() => ClientRequest._(); - @$core.override - ClientRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static ClientRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static ClientRequest? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - ClientRequest_Payload whichPayload() => - _ClientRequest_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $0.Request get auth => $_getN(0); - @$pb.TagNumber(1) - set auth($0.Request value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasAuth() => $_has(0); - @$pb.TagNumber(1) - void clearAuth() => $_clearField(1); - @$pb.TagNumber(1) - $0.Request ensureAuth() => $_ensure(0); - - @$pb.TagNumber(2) - $1.Request get vault => $_getN(1); - @$pb.TagNumber(2) - set vault($1.Request value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasVault() => $_has(1); - @$pb.TagNumber(2) - void clearVault() => $_clearField(2); - @$pb.TagNumber(2) - $1.Request ensureVault() => $_ensure(1); - - @$pb.TagNumber(3) - $2.Request get evm => $_getN(2); - @$pb.TagNumber(3) - set evm($2.Request value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasEvm() => $_has(2); - @$pb.TagNumber(3) - void clearEvm() => $_clearField(3); - @$pb.TagNumber(3) - $2.Request ensureEvm() => $_ensure(2); - - @$pb.TagNumber(4) - $core.int get requestId => $_getIZ(3); - @$pb.TagNumber(4) - set requestId($core.int value) => $_setSignedInt32(3, value); - @$pb.TagNumber(4) - $core.bool hasRequestId() => $_has(3); - @$pb.TagNumber(4) - void clearRequestId() => $_clearField(4); -} - -enum ClientResponse_Payload { auth, vault, evm, notSet } - -class ClientResponse extends $pb.GeneratedMessage { - factory ClientResponse({ - $0.Response? auth, - $1.Response? vault, - $2.Response? evm, - $core.int? requestId, - }) { - final result = create(); - if (auth != null) result.auth = auth; - if (vault != null) result.vault = vault; - if (evm != null) result.evm = evm; - if (requestId != null) result.requestId = requestId; - return result; - } - - ClientResponse._(); - - factory ClientResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory ClientResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, ClientResponse_Payload> - _ClientResponse_PayloadByTag = { - 1: ClientResponse_Payload.auth, - 2: ClientResponse_Payload.vault, - 3: ClientResponse_Payload.evm, - 0: ClientResponse_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'ClientResponse', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3]) - ..aOM<$0.Response>(1, _omitFieldNames ? '' : 'auth', - subBuilder: $0.Response.create) - ..aOM<$1.Response>(2, _omitFieldNames ? '' : 'vault', - subBuilder: $1.Response.create) - ..aOM<$2.Response>(3, _omitFieldNames ? '' : 'evm', - subBuilder: $2.Response.create) - ..aI(7, _omitFieldNames ? '' : 'requestId') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ClientResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ClientResponse copyWith(void Function(ClientResponse) updates) => - super.copyWith((message) => updates(message as ClientResponse)) - as ClientResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static ClientResponse create() => ClientResponse._(); - @$core.override - ClientResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static ClientResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static ClientResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - ClientResponse_Payload whichPayload() => - _ClientResponse_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $0.Response get auth => $_getN(0); - @$pb.TagNumber(1) - set auth($0.Response value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasAuth() => $_has(0); - @$pb.TagNumber(1) - void clearAuth() => $_clearField(1); - @$pb.TagNumber(1) - $0.Response ensureAuth() => $_ensure(0); - - @$pb.TagNumber(2) - $1.Response get vault => $_getN(1); - @$pb.TagNumber(2) - set vault($1.Response value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasVault() => $_has(1); - @$pb.TagNumber(2) - void clearVault() => $_clearField(2); - @$pb.TagNumber(2) - $1.Response ensureVault() => $_ensure(1); - - @$pb.TagNumber(3) - $2.Response get evm => $_getN(2); - @$pb.TagNumber(3) - set evm($2.Response value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasEvm() => $_has(2); - @$pb.TagNumber(3) - void clearEvm() => $_clearField(3); - @$pb.TagNumber(3) - $2.Response ensureEvm() => $_ensure(2); - - @$pb.TagNumber(7) - $core.int get requestId => $_getIZ(3); - @$pb.TagNumber(7) - set requestId($core.int value) => $_setSignedInt32(3, value); - @$pb.TagNumber(7) - $core.bool hasRequestId() => $_has(3); - @$pb.TagNumber(7) - void clearRequestId() => $_clearField(7); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from client.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'client/auth.pb.dart' as $0; +import 'client/evm.pb.dart' as $2; +import 'client/vault.pb.dart' as $1; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +enum ClientRequest_Payload { auth, vault, evm, notSet } + +class ClientRequest extends $pb.GeneratedMessage { + factory ClientRequest({ + $0.Request? auth, + $1.Request? vault, + $2.Request? evm, + $core.int? requestId, + }) { + final result = create(); + if (auth != null) result.auth = auth; + if (vault != null) result.vault = vault; + if (evm != null) result.evm = evm; + if (requestId != null) result.requestId = requestId; + return result; + } + + ClientRequest._(); + + factory ClientRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory ClientRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, ClientRequest_Payload> + _ClientRequest_PayloadByTag = { + 1: ClientRequest_Payload.auth, + 2: ClientRequest_Payload.vault, + 3: ClientRequest_Payload.evm, + 0: ClientRequest_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ClientRequest', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3]) + ..aOM<$0.Request>(1, _omitFieldNames ? '' : 'auth', + subBuilder: $0.Request.create) + ..aOM<$1.Request>(2, _omitFieldNames ? '' : 'vault', + subBuilder: $1.Request.create) + ..aOM<$2.Request>(3, _omitFieldNames ? '' : 'evm', + subBuilder: $2.Request.create) + ..aI(4, _omitFieldNames ? '' : 'requestId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ClientRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ClientRequest copyWith(void Function(ClientRequest) updates) => + super.copyWith((message) => updates(message as ClientRequest)) + as ClientRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ClientRequest create() => ClientRequest._(); + @$core.override + ClientRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static ClientRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static ClientRequest? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + ClientRequest_Payload whichPayload() => + _ClientRequest_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $0.Request get auth => $_getN(0); + @$pb.TagNumber(1) + set auth($0.Request value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasAuth() => $_has(0); + @$pb.TagNumber(1) + void clearAuth() => $_clearField(1); + @$pb.TagNumber(1) + $0.Request ensureAuth() => $_ensure(0); + + @$pb.TagNumber(2) + $1.Request get vault => $_getN(1); + @$pb.TagNumber(2) + set vault($1.Request value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasVault() => $_has(1); + @$pb.TagNumber(2) + void clearVault() => $_clearField(2); + @$pb.TagNumber(2) + $1.Request ensureVault() => $_ensure(1); + + @$pb.TagNumber(3) + $2.Request get evm => $_getN(2); + @$pb.TagNumber(3) + set evm($2.Request value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasEvm() => $_has(2); + @$pb.TagNumber(3) + void clearEvm() => $_clearField(3); + @$pb.TagNumber(3) + $2.Request ensureEvm() => $_ensure(2); + + @$pb.TagNumber(4) + $core.int get requestId => $_getIZ(3); + @$pb.TagNumber(4) + set requestId($core.int value) => $_setSignedInt32(3, value); + @$pb.TagNumber(4) + $core.bool hasRequestId() => $_has(3); + @$pb.TagNumber(4) + void clearRequestId() => $_clearField(4); +} + +enum ClientResponse_Payload { auth, vault, evm, notSet } + +class ClientResponse extends $pb.GeneratedMessage { + factory ClientResponse({ + $0.Response? auth, + $1.Response? vault, + $2.Response? evm, + $core.int? requestId, + }) { + final result = create(); + if (auth != null) result.auth = auth; + if (vault != null) result.vault = vault; + if (evm != null) result.evm = evm; + if (requestId != null) result.requestId = requestId; + return result; + } + + ClientResponse._(); + + factory ClientResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory ClientResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, ClientResponse_Payload> + _ClientResponse_PayloadByTag = { + 1: ClientResponse_Payload.auth, + 2: ClientResponse_Payload.vault, + 3: ClientResponse_Payload.evm, + 0: ClientResponse_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ClientResponse', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3]) + ..aOM<$0.Response>(1, _omitFieldNames ? '' : 'auth', + subBuilder: $0.Response.create) + ..aOM<$1.Response>(2, _omitFieldNames ? '' : 'vault', + subBuilder: $1.Response.create) + ..aOM<$2.Response>(3, _omitFieldNames ? '' : 'evm', + subBuilder: $2.Response.create) + ..aI(7, _omitFieldNames ? '' : 'requestId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ClientResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ClientResponse copyWith(void Function(ClientResponse) updates) => + super.copyWith((message) => updates(message as ClientResponse)) + as ClientResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ClientResponse create() => ClientResponse._(); + @$core.override + ClientResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static ClientResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static ClientResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + ClientResponse_Payload whichPayload() => + _ClientResponse_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $0.Response get auth => $_getN(0); + @$pb.TagNumber(1) + set auth($0.Response value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasAuth() => $_has(0); + @$pb.TagNumber(1) + void clearAuth() => $_clearField(1); + @$pb.TagNumber(1) + $0.Response ensureAuth() => $_ensure(0); + + @$pb.TagNumber(2) + $1.Response get vault => $_getN(1); + @$pb.TagNumber(2) + set vault($1.Response value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasVault() => $_has(1); + @$pb.TagNumber(2) + void clearVault() => $_clearField(2); + @$pb.TagNumber(2) + $1.Response ensureVault() => $_ensure(1); + + @$pb.TagNumber(3) + $2.Response get evm => $_getN(2); + @$pb.TagNumber(3) + set evm($2.Response value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasEvm() => $_has(2); + @$pb.TagNumber(3) + void clearEvm() => $_clearField(3); + @$pb.TagNumber(3) + $2.Response ensureEvm() => $_ensure(2); + + @$pb.TagNumber(7) + $core.int get requestId => $_getIZ(3); + @$pb.TagNumber(7) + set requestId($core.int value) => $_setSignedInt32(3, value); + @$pb.TagNumber(7) + $core.bool hasRequestId() => $_has(3); + @$pb.TagNumber(7) + void clearRequestId() => $_clearField(7); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/client.pbenum.dart b/useragent/lib/proto/client.pbenum.dart index 685a348..bdf9c6d 100644 --- a/useragent/lib/proto/client.pbenum.dart +++ b/useragent/lib/proto/client.pbenum.dart @@ -1,11 +1,11 @@ -// This is a generated file - do not edit. -// -// Generated from client.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// This is a generated file - do not edit. +// +// Generated from client.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports diff --git a/useragent/lib/proto/client.pbjson.dart b/useragent/lib/proto/client.pbjson.dart index 4f861cc..51a8103 100644 --- a/useragent/lib/proto/client.pbjson.dart +++ b/useragent/lib/proto/client.pbjson.dart @@ -1,116 +1,116 @@ -// This is a generated file - do not edit. -// -// Generated from client.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use clientRequestDescriptor instead') -const ClientRequest$json = { - '1': 'ClientRequest', - '2': [ - {'1': 'request_id', '3': 4, '4': 1, '5': 5, '10': 'requestId'}, - { - '1': 'auth', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.client.auth.Request', - '9': 0, - '10': 'auth' - }, - { - '1': 'vault', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.client.vault.Request', - '9': 0, - '10': 'vault' - }, - { - '1': 'evm', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.client.evm.Request', - '9': 0, - '10': 'evm' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `ClientRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List clientRequestDescriptor = $convert.base64Decode( - 'Cg1DbGllbnRSZXF1ZXN0Eh0KCnJlcXVlc3RfaWQYBCABKAVSCXJlcXVlc3RJZBIyCgRhdXRoGA' - 'EgASgLMhwuYXJiaXRlci5jbGllbnQuYXV0aC5SZXF1ZXN0SABSBGF1dGgSNQoFdmF1bHQYAiAB' - 'KAsyHS5hcmJpdGVyLmNsaWVudC52YXVsdC5SZXF1ZXN0SABSBXZhdWx0Ei8KA2V2bRgDIAEoCz' - 'IbLmFyYml0ZXIuY2xpZW50LmV2bS5SZXF1ZXN0SABSA2V2bUIJCgdwYXlsb2Fk'); - -@$core.Deprecated('Use clientResponseDescriptor instead') -const ClientResponse$json = { - '1': 'ClientResponse', - '2': [ - { - '1': 'request_id', - '3': 7, - '4': 1, - '5': 5, - '9': 1, - '10': 'requestId', - '17': true - }, - { - '1': 'auth', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.client.auth.Response', - '9': 0, - '10': 'auth' - }, - { - '1': 'vault', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.client.vault.Response', - '9': 0, - '10': 'vault' - }, - { - '1': 'evm', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.client.evm.Response', - '9': 0, - '10': 'evm' - }, - ], - '8': [ - {'1': 'payload'}, - {'1': '_request_id'}, - ], -}; - -/// Descriptor for `ClientResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List clientResponseDescriptor = $convert.base64Decode( - 'Cg5DbGllbnRSZXNwb25zZRIiCgpyZXF1ZXN0X2lkGAcgASgFSAFSCXJlcXVlc3RJZIgBARIzCg' - 'RhdXRoGAEgASgLMh0uYXJiaXRlci5jbGllbnQuYXV0aC5SZXNwb25zZUgAUgRhdXRoEjYKBXZh' - 'dWx0GAIgASgLMh4uYXJiaXRlci5jbGllbnQudmF1bHQuUmVzcG9uc2VIAFIFdmF1bHQSMAoDZX' - 'ZtGAMgASgLMhwuYXJiaXRlci5jbGllbnQuZXZtLlJlc3BvbnNlSABSA2V2bUIJCgdwYXlsb2Fk' - 'Qg0KC19yZXF1ZXN0X2lk'); +// This is a generated file - do not edit. +// +// Generated from client.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use clientRequestDescriptor instead') +const ClientRequest$json = { + '1': 'ClientRequest', + '2': [ + {'1': 'request_id', '3': 4, '4': 1, '5': 5, '10': 'requestId'}, + { + '1': 'auth', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.client.auth.Request', + '9': 0, + '10': 'auth' + }, + { + '1': 'vault', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.client.vault.Request', + '9': 0, + '10': 'vault' + }, + { + '1': 'evm', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.client.evm.Request', + '9': 0, + '10': 'evm' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `ClientRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List clientRequestDescriptor = $convert.base64Decode( + 'Cg1DbGllbnRSZXF1ZXN0Eh0KCnJlcXVlc3RfaWQYBCABKAVSCXJlcXVlc3RJZBIyCgRhdXRoGA' + 'EgASgLMhwuYXJiaXRlci5jbGllbnQuYXV0aC5SZXF1ZXN0SABSBGF1dGgSNQoFdmF1bHQYAiAB' + 'KAsyHS5hcmJpdGVyLmNsaWVudC52YXVsdC5SZXF1ZXN0SABSBXZhdWx0Ei8KA2V2bRgDIAEoCz' + 'IbLmFyYml0ZXIuY2xpZW50LmV2bS5SZXF1ZXN0SABSA2V2bUIJCgdwYXlsb2Fk'); + +@$core.Deprecated('Use clientResponseDescriptor instead') +const ClientResponse$json = { + '1': 'ClientResponse', + '2': [ + { + '1': 'request_id', + '3': 7, + '4': 1, + '5': 5, + '9': 1, + '10': 'requestId', + '17': true + }, + { + '1': 'auth', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.client.auth.Response', + '9': 0, + '10': 'auth' + }, + { + '1': 'vault', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.client.vault.Response', + '9': 0, + '10': 'vault' + }, + { + '1': 'evm', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.client.evm.Response', + '9': 0, + '10': 'evm' + }, + ], + '8': [ + {'1': 'payload'}, + {'1': '_request_id'}, + ], +}; + +/// Descriptor for `ClientResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List clientResponseDescriptor = $convert.base64Decode( + 'Cg5DbGllbnRSZXNwb25zZRIiCgpyZXF1ZXN0X2lkGAcgASgFSAFSCXJlcXVlc3RJZIgBARIzCg' + 'RhdXRoGAEgASgLMh0uYXJiaXRlci5jbGllbnQuYXV0aC5SZXNwb25zZUgAUgRhdXRoEjYKBXZh' + 'dWx0GAIgASgLMh4uYXJiaXRlci5jbGllbnQudmF1bHQuUmVzcG9uc2VIAFIFdmF1bHQSMAoDZX' + 'ZtGAMgASgLMhwuYXJiaXRlci5jbGllbnQuZXZtLlJlc3BvbnNlSABSA2V2bUIJCgdwYXlsb2Fk' + 'Qg0KC19yZXF1ZXN0X2lk'); diff --git a/useragent/lib/proto/client/auth.pb.dart b/useragent/lib/proto/client/auth.pb.dart index ae19314..02c6753 100644 --- a/useragent/lib/proto/client/auth.pb.dart +++ b/useragent/lib/proto/client/auth.pb.dart @@ -1,398 +1,398 @@ -// This is a generated file - do not edit. -// -// Generated from client/auth.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:fixnum/fixnum.dart' as $fixnum; -import 'package:protobuf/protobuf.dart' as $pb; - -import '../shared/client.pb.dart' as $0; -import 'auth.pbenum.dart'; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -export 'auth.pbenum.dart'; - -class AuthChallengeRequest extends $pb.GeneratedMessage { - factory AuthChallengeRequest({ - $core.List<$core.int>? pubkey, - $0.ClientInfo? clientInfo, - }) { - final result = create(); - if (pubkey != null) result.pubkey = pubkey; - if (clientInfo != null) result.clientInfo = clientInfo; - return result; - } - - AuthChallengeRequest._(); - - factory AuthChallengeRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory AuthChallengeRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'AuthChallengeRequest', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) - ..aOM<$0.ClientInfo>(2, _omitFieldNames ? '' : 'clientInfo', - subBuilder: $0.ClientInfo.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallengeRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallengeRequest copyWith(void Function(AuthChallengeRequest) updates) => - super.copyWith((message) => updates(message as AuthChallengeRequest)) - as AuthChallengeRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static AuthChallengeRequest create() => AuthChallengeRequest._(); - @$core.override - AuthChallengeRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static AuthChallengeRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static AuthChallengeRequest? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get pubkey => $_getN(0); - @$pb.TagNumber(1) - set pubkey($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasPubkey() => $_has(0); - @$pb.TagNumber(1) - void clearPubkey() => $_clearField(1); - - @$pb.TagNumber(2) - $0.ClientInfo get clientInfo => $_getN(1); - @$pb.TagNumber(2) - set clientInfo($0.ClientInfo value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasClientInfo() => $_has(1); - @$pb.TagNumber(2) - void clearClientInfo() => $_clearField(2); - @$pb.TagNumber(2) - $0.ClientInfo ensureClientInfo() => $_ensure(1); -} - -class AuthChallenge extends $pb.GeneratedMessage { - factory AuthChallenge({ - $fixnum.Int64? timestampNanos, - $core.List<$core.int>? random, - }) { - final result = create(); - if (timestampNanos != null) result.timestampNanos = timestampNanos; - if (random != null) result.random = random; - return result; - } - - AuthChallenge._(); - - factory AuthChallenge.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory AuthChallenge.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'AuthChallenge', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'), - createEmptyInstance: create) - ..a<$fixnum.Int64>( - 1, _omitFieldNames ? '' : 'timestampNanos', $pb.PbFieldType.OU6, - defaultOrMaker: $fixnum.Int64.ZERO) - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'random', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallenge clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallenge copyWith(void Function(AuthChallenge) updates) => - super.copyWith((message) => updates(message as AuthChallenge)) - as AuthChallenge; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static AuthChallenge create() => AuthChallenge._(); - @$core.override - AuthChallenge createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static AuthChallenge getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static AuthChallenge? _defaultInstance; - - @$pb.TagNumber(1) - $fixnum.Int64 get timestampNanos => $_getI64(0); - @$pb.TagNumber(1) - set timestampNanos($fixnum.Int64 value) => $_setInt64(0, value); - @$pb.TagNumber(1) - $core.bool hasTimestampNanos() => $_has(0); - @$pb.TagNumber(1) - void clearTimestampNanos() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get random => $_getN(1); - @$pb.TagNumber(2) - set random($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasRandom() => $_has(1); - @$pb.TagNumber(2) - void clearRandom() => $_clearField(2); -} - -class AuthChallengeSolution extends $pb.GeneratedMessage { - factory AuthChallengeSolution({ - $core.List<$core.int>? signature, - }) { - final result = create(); - if (signature != null) result.signature = signature; - return result; - } - - AuthChallengeSolution._(); - - factory AuthChallengeSolution.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory AuthChallengeSolution.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'AuthChallengeSolution', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallengeSolution clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallengeSolution copyWith( - void Function(AuthChallengeSolution) updates) => - super.copyWith((message) => updates(message as AuthChallengeSolution)) - as AuthChallengeSolution; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static AuthChallengeSolution create() => AuthChallengeSolution._(); - @$core.override - AuthChallengeSolution createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static AuthChallengeSolution getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static AuthChallengeSolution? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get signature => $_getN(0); - @$pb.TagNumber(1) - set signature($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasSignature() => $_has(0); - @$pb.TagNumber(1) - void clearSignature() => $_clearField(1); -} - -enum Request_Payload { challengeRequest, challengeSolution, notSet } - -class Request extends $pb.GeneratedMessage { - factory Request({ - AuthChallengeRequest? challengeRequest, - AuthChallengeSolution? challengeSolution, - }) { - final result = create(); - if (challengeRequest != null) result.challengeRequest = challengeRequest; - if (challengeSolution != null) result.challengeSolution = challengeSolution; - return result; - } - - Request._(); - - factory Request.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Request.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { - 1: Request_Payload.challengeRequest, - 2: Request_Payload.challengeSolution, - 0: Request_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Request', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'challengeRequest', - subBuilder: AuthChallengeRequest.create) - ..aOM(2, _omitFieldNames ? '' : 'challengeSolution', - subBuilder: AuthChallengeSolution.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request copyWith(void Function(Request) updates) => - super.copyWith((message) => updates(message as Request)) as Request; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Request create() => Request._(); - @$core.override - Request createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Request getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Request? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - AuthChallengeRequest get challengeRequest => $_getN(0); - @$pb.TagNumber(1) - set challengeRequest(AuthChallengeRequest value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasChallengeRequest() => $_has(0); - @$pb.TagNumber(1) - void clearChallengeRequest() => $_clearField(1); - @$pb.TagNumber(1) - AuthChallengeRequest ensureChallengeRequest() => $_ensure(0); - - @$pb.TagNumber(2) - AuthChallengeSolution get challengeSolution => $_getN(1); - @$pb.TagNumber(2) - set challengeSolution(AuthChallengeSolution value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasChallengeSolution() => $_has(1); - @$pb.TagNumber(2) - void clearChallengeSolution() => $_clearField(2); - @$pb.TagNumber(2) - AuthChallengeSolution ensureChallengeSolution() => $_ensure(1); -} - -enum Response_Payload { challenge, result, notSet } - -class Response extends $pb.GeneratedMessage { - factory Response({ - AuthChallenge? challenge, - AuthResult? result, - }) { - final result$ = create(); - if (challenge != null) result$.challenge = challenge; - if (result != null) result$.result = result; - return result$; - } - - Response._(); - - factory Response.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Response.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { - 1: Response_Payload.challenge, - 2: Response_Payload.result, - 0: Response_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Response', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'challenge', - subBuilder: AuthChallenge.create) - ..aE(2, _omitFieldNames ? '' : 'result', - enumValues: AuthResult.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response copyWith(void Function(Response) updates) => - super.copyWith((message) => updates(message as Response)) as Response; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Response create() => Response._(); - @$core.override - Response createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Response getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Response? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - AuthChallenge get challenge => $_getN(0); - @$pb.TagNumber(1) - set challenge(AuthChallenge value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasChallenge() => $_has(0); - @$pb.TagNumber(1) - void clearChallenge() => $_clearField(1); - @$pb.TagNumber(1) - AuthChallenge ensureChallenge() => $_ensure(0); - - @$pb.TagNumber(2) - AuthResult get result => $_getN(1); - @$pb.TagNumber(2) - set result(AuthResult value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasResult() => $_has(1); - @$pb.TagNumber(2) - void clearResult() => $_clearField(2); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from client/auth.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; + +import '../shared/client.pb.dart' as $0; +import 'auth.pbenum.dart'; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +export 'auth.pbenum.dart'; + +class AuthChallengeRequest extends $pb.GeneratedMessage { + factory AuthChallengeRequest({ + $core.List<$core.int>? pubkey, + $0.ClientInfo? clientInfo, + }) { + final result = create(); + if (pubkey != null) result.pubkey = pubkey; + if (clientInfo != null) result.clientInfo = clientInfo; + return result; + } + + AuthChallengeRequest._(); + + factory AuthChallengeRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory AuthChallengeRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'AuthChallengeRequest', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) + ..aOM<$0.ClientInfo>(2, _omitFieldNames ? '' : 'clientInfo', + subBuilder: $0.ClientInfo.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallengeRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallengeRequest copyWith(void Function(AuthChallengeRequest) updates) => + super.copyWith((message) => updates(message as AuthChallengeRequest)) + as AuthChallengeRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static AuthChallengeRequest create() => AuthChallengeRequest._(); + @$core.override + AuthChallengeRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static AuthChallengeRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static AuthChallengeRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get pubkey => $_getN(0); + @$pb.TagNumber(1) + set pubkey($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasPubkey() => $_has(0); + @$pb.TagNumber(1) + void clearPubkey() => $_clearField(1); + + @$pb.TagNumber(2) + $0.ClientInfo get clientInfo => $_getN(1); + @$pb.TagNumber(2) + set clientInfo($0.ClientInfo value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasClientInfo() => $_has(1); + @$pb.TagNumber(2) + void clearClientInfo() => $_clearField(2); + @$pb.TagNumber(2) + $0.ClientInfo ensureClientInfo() => $_ensure(1); +} + +class AuthChallenge extends $pb.GeneratedMessage { + factory AuthChallenge({ + $fixnum.Int64? timestampNanos, + $core.List<$core.int>? random, + }) { + final result = create(); + if (timestampNanos != null) result.timestampNanos = timestampNanos; + if (random != null) result.random = random; + return result; + } + + AuthChallenge._(); + + factory AuthChallenge.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory AuthChallenge.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'AuthChallenge', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'), + createEmptyInstance: create) + ..a<$fixnum.Int64>( + 1, _omitFieldNames ? '' : 'timestampNanos', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'random', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallenge clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallenge copyWith(void Function(AuthChallenge) updates) => + super.copyWith((message) => updates(message as AuthChallenge)) + as AuthChallenge; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static AuthChallenge create() => AuthChallenge._(); + @$core.override + AuthChallenge createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static AuthChallenge getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static AuthChallenge? _defaultInstance; + + @$pb.TagNumber(1) + $fixnum.Int64 get timestampNanos => $_getI64(0); + @$pb.TagNumber(1) + set timestampNanos($fixnum.Int64 value) => $_setInt64(0, value); + @$pb.TagNumber(1) + $core.bool hasTimestampNanos() => $_has(0); + @$pb.TagNumber(1) + void clearTimestampNanos() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get random => $_getN(1); + @$pb.TagNumber(2) + set random($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasRandom() => $_has(1); + @$pb.TagNumber(2) + void clearRandom() => $_clearField(2); +} + +class AuthChallengeSolution extends $pb.GeneratedMessage { + factory AuthChallengeSolution({ + $core.List<$core.int>? signature, + }) { + final result = create(); + if (signature != null) result.signature = signature; + return result; + } + + AuthChallengeSolution._(); + + factory AuthChallengeSolution.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory AuthChallengeSolution.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'AuthChallengeSolution', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallengeSolution clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallengeSolution copyWith( + void Function(AuthChallengeSolution) updates) => + super.copyWith((message) => updates(message as AuthChallengeSolution)) + as AuthChallengeSolution; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static AuthChallengeSolution create() => AuthChallengeSolution._(); + @$core.override + AuthChallengeSolution createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static AuthChallengeSolution getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static AuthChallengeSolution? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get signature => $_getN(0); + @$pb.TagNumber(1) + set signature($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasSignature() => $_has(0); + @$pb.TagNumber(1) + void clearSignature() => $_clearField(1); +} + +enum Request_Payload { challengeRequest, challengeSolution, notSet } + +class Request extends $pb.GeneratedMessage { + factory Request({ + AuthChallengeRequest? challengeRequest, + AuthChallengeSolution? challengeSolution, + }) { + final result = create(); + if (challengeRequest != null) result.challengeRequest = challengeRequest; + if (challengeSolution != null) result.challengeSolution = challengeSolution; + return result; + } + + Request._(); + + factory Request.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Request.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { + 1: Request_Payload.challengeRequest, + 2: Request_Payload.challengeSolution, + 0: Request_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Request', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'challengeRequest', + subBuilder: AuthChallengeRequest.create) + ..aOM(2, _omitFieldNames ? '' : 'challengeSolution', + subBuilder: AuthChallengeSolution.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request copyWith(void Function(Request) updates) => + super.copyWith((message) => updates(message as Request)) as Request; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Request create() => Request._(); + @$core.override + Request createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Request getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Request? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + AuthChallengeRequest get challengeRequest => $_getN(0); + @$pb.TagNumber(1) + set challengeRequest(AuthChallengeRequest value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasChallengeRequest() => $_has(0); + @$pb.TagNumber(1) + void clearChallengeRequest() => $_clearField(1); + @$pb.TagNumber(1) + AuthChallengeRequest ensureChallengeRequest() => $_ensure(0); + + @$pb.TagNumber(2) + AuthChallengeSolution get challengeSolution => $_getN(1); + @$pb.TagNumber(2) + set challengeSolution(AuthChallengeSolution value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasChallengeSolution() => $_has(1); + @$pb.TagNumber(2) + void clearChallengeSolution() => $_clearField(2); + @$pb.TagNumber(2) + AuthChallengeSolution ensureChallengeSolution() => $_ensure(1); +} + +enum Response_Payload { challenge, result, notSet } + +class Response extends $pb.GeneratedMessage { + factory Response({ + AuthChallenge? challenge, + AuthResult? result, + }) { + final result$ = create(); + if (challenge != null) result$.challenge = challenge; + if (result != null) result$.result = result; + return result$; + } + + Response._(); + + factory Response.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Response.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { + 1: Response_Payload.challenge, + 2: Response_Payload.result, + 0: Response_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Response', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.auth'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'challenge', + subBuilder: AuthChallenge.create) + ..aE(2, _omitFieldNames ? '' : 'result', + enumValues: AuthResult.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response copyWith(void Function(Response) updates) => + super.copyWith((message) => updates(message as Response)) as Response; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Response create() => Response._(); + @$core.override + Response createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Response getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Response? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + AuthChallenge get challenge => $_getN(0); + @$pb.TagNumber(1) + set challenge(AuthChallenge value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasChallenge() => $_has(0); + @$pb.TagNumber(1) + void clearChallenge() => $_clearField(1); + @$pb.TagNumber(1) + AuthChallenge ensureChallenge() => $_ensure(0); + + @$pb.TagNumber(2) + AuthResult get result => $_getN(1); + @$pb.TagNumber(2) + set result(AuthResult value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasResult() => $_has(1); + @$pb.TagNumber(2) + void clearResult() => $_clearField(2); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/client/auth.pbenum.dart b/useragent/lib/proto/client/auth.pbenum.dart index 8e1baba..b48d779 100644 --- a/useragent/lib/proto/client/auth.pbenum.dart +++ b/useragent/lib/proto/client/auth.pbenum.dart @@ -1,52 +1,52 @@ -// This is a generated file - do not edit. -// -// Generated from client/auth.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -class AuthResult extends $pb.ProtobufEnum { - static const AuthResult AUTH_RESULT_UNSPECIFIED = - AuthResult._(0, _omitEnumNames ? '' : 'AUTH_RESULT_UNSPECIFIED'); - static const AuthResult AUTH_RESULT_SUCCESS = - AuthResult._(1, _omitEnumNames ? '' : 'AUTH_RESULT_SUCCESS'); - static const AuthResult AUTH_RESULT_INVALID_KEY = - AuthResult._(2, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_KEY'); - static const AuthResult AUTH_RESULT_INVALID_SIGNATURE = - AuthResult._(3, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_SIGNATURE'); - static const AuthResult AUTH_RESULT_APPROVAL_DENIED = - AuthResult._(4, _omitEnumNames ? '' : 'AUTH_RESULT_APPROVAL_DENIED'); - static const AuthResult AUTH_RESULT_NO_USER_AGENTS_ONLINE = AuthResult._( - 5, _omitEnumNames ? '' : 'AUTH_RESULT_NO_USER_AGENTS_ONLINE'); - static const AuthResult AUTH_RESULT_INTERNAL = - AuthResult._(6, _omitEnumNames ? '' : 'AUTH_RESULT_INTERNAL'); - - static const $core.List values = [ - AUTH_RESULT_UNSPECIFIED, - AUTH_RESULT_SUCCESS, - AUTH_RESULT_INVALID_KEY, - AUTH_RESULT_INVALID_SIGNATURE, - AUTH_RESULT_APPROVAL_DENIED, - AUTH_RESULT_NO_USER_AGENTS_ONLINE, - AUTH_RESULT_INTERNAL, - ]; - - static final $core.List _byValue = - $pb.ProtobufEnum.$_initByValueList(values, 6); - static AuthResult? valueOf($core.int value) => - value < 0 || value >= _byValue.length ? null : _byValue[value]; - - const AuthResult._(super.value, super.name); -} - -const $core.bool _omitEnumNames = - $core.bool.fromEnvironment('protobuf.omit_enum_names'); +// This is a generated file - do not edit. +// +// Generated from client/auth.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class AuthResult extends $pb.ProtobufEnum { + static const AuthResult AUTH_RESULT_UNSPECIFIED = + AuthResult._(0, _omitEnumNames ? '' : 'AUTH_RESULT_UNSPECIFIED'); + static const AuthResult AUTH_RESULT_SUCCESS = + AuthResult._(1, _omitEnumNames ? '' : 'AUTH_RESULT_SUCCESS'); + static const AuthResult AUTH_RESULT_INVALID_KEY = + AuthResult._(2, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_KEY'); + static const AuthResult AUTH_RESULT_INVALID_SIGNATURE = + AuthResult._(3, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_SIGNATURE'); + static const AuthResult AUTH_RESULT_APPROVAL_DENIED = + AuthResult._(4, _omitEnumNames ? '' : 'AUTH_RESULT_APPROVAL_DENIED'); + static const AuthResult AUTH_RESULT_NO_USER_AGENTS_ONLINE = AuthResult._( + 5, _omitEnumNames ? '' : 'AUTH_RESULT_NO_USER_AGENTS_ONLINE'); + static const AuthResult AUTH_RESULT_INTERNAL = + AuthResult._(6, _omitEnumNames ? '' : 'AUTH_RESULT_INTERNAL'); + + static const $core.List values = [ + AUTH_RESULT_UNSPECIFIED, + AUTH_RESULT_SUCCESS, + AUTH_RESULT_INVALID_KEY, + AUTH_RESULT_INVALID_SIGNATURE, + AUTH_RESULT_APPROVAL_DENIED, + AUTH_RESULT_NO_USER_AGENTS_ONLINE, + AUTH_RESULT_INTERNAL, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 6); + static AuthResult? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const AuthResult._(super.value, super.name); +} + +const $core.bool _omitEnumNames = + $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/useragent/lib/proto/client/auth.pbjson.dart b/useragent/lib/proto/client/auth.pbjson.dart index c7b42b7..9f681a1 100644 --- a/useragent/lib/proto/client/auth.pbjson.dart +++ b/useragent/lib/proto/client/auth.pbjson.dart @@ -1,154 +1,154 @@ -// This is a generated file - do not edit. -// -// Generated from client/auth.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use authResultDescriptor instead') -const AuthResult$json = { - '1': 'AuthResult', - '2': [ - {'1': 'AUTH_RESULT_UNSPECIFIED', '2': 0}, - {'1': 'AUTH_RESULT_SUCCESS', '2': 1}, - {'1': 'AUTH_RESULT_INVALID_KEY', '2': 2}, - {'1': 'AUTH_RESULT_INVALID_SIGNATURE', '2': 3}, - {'1': 'AUTH_RESULT_APPROVAL_DENIED', '2': 4}, - {'1': 'AUTH_RESULT_NO_USER_AGENTS_ONLINE', '2': 5}, - {'1': 'AUTH_RESULT_INTERNAL', '2': 6}, - ], -}; - -/// Descriptor for `AuthResult`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List authResultDescriptor = $convert.base64Decode( - 'CgpBdXRoUmVzdWx0EhsKF0FVVEhfUkVTVUxUX1VOU1BFQ0lGSUVEEAASFwoTQVVUSF9SRVNVTF' - 'RfU1VDQ0VTUxABEhsKF0FVVEhfUkVTVUxUX0lOVkFMSURfS0VZEAISIQodQVVUSF9SRVNVTFRf' - 'SU5WQUxJRF9TSUdOQVRVUkUQAxIfChtBVVRIX1JFU1VMVF9BUFBST1ZBTF9ERU5JRUQQBBIlCi' - 'FBVVRIX1JFU1VMVF9OT19VU0VSX0FHRU5UU19PTkxJTkUQBRIYChRBVVRIX1JFU1VMVF9JTlRF' - 'Uk5BTBAG'); - -@$core.Deprecated('Use authChallengeRequestDescriptor instead') -const AuthChallengeRequest$json = { - '1': 'AuthChallengeRequest', - '2': [ - {'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'}, - { - '1': 'client_info', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.shared.ClientInfo', - '10': 'clientInfo' - }, - ], -}; - -/// Descriptor for `AuthChallengeRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List authChallengeRequestDescriptor = $convert.base64Decode( - 'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRI7CgtjbGllbn' - 'RfaW5mbxgCIAEoCzIaLmFyYml0ZXIuc2hhcmVkLkNsaWVudEluZm9SCmNsaWVudEluZm8='); - -@$core.Deprecated('Use authChallengeDescriptor instead') -const AuthChallenge$json = { - '1': 'AuthChallenge', - '2': [ - {'1': 'timestamp_nanos', '3': 1, '4': 1, '5': 4, '10': 'timestampNanos'}, - {'1': 'random', '3': 2, '4': 1, '5': 12, '10': 'random'}, - ], -}; - -/// Descriptor for `AuthChallenge`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List authChallengeDescriptor = $convert.base64Decode( - 'Cg1BdXRoQ2hhbGxlbmdlEicKD3RpbWVzdGFtcF9uYW5vcxgBIAEoBFIOdGltZXN0YW1wTmFub3' - 'MSFgoGcmFuZG9tGAIgASgMUgZyYW5kb20='); - -@$core.Deprecated('Use authChallengeSolutionDescriptor instead') -const AuthChallengeSolution$json = { - '1': 'AuthChallengeSolution', - '2': [ - {'1': 'signature', '3': 1, '4': 1, '5': 12, '10': 'signature'}, - ], -}; - -/// Descriptor for `AuthChallengeSolution`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List authChallengeSolutionDescriptor = $convert.base64Decode( - 'ChVBdXRoQ2hhbGxlbmdlU29sdXRpb24SHAoJc2lnbmF0dXJlGAEgASgMUglzaWduYXR1cmU='); - -@$core.Deprecated('Use requestDescriptor instead') -const Request$json = { - '1': 'Request', - '2': [ - { - '1': 'challenge_request', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.client.auth.AuthChallengeRequest', - '9': 0, - '10': 'challengeRequest' - }, - { - '1': 'challenge_solution', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.client.auth.AuthChallengeSolution', - '9': 0, - '10': 'challengeSolution' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( - 'CgdSZXF1ZXN0ElgKEWNoYWxsZW5nZV9yZXF1ZXN0GAEgASgLMikuYXJiaXRlci5jbGllbnQuYX' - 'V0aC5BdXRoQ2hhbGxlbmdlUmVxdWVzdEgAUhBjaGFsbGVuZ2VSZXF1ZXN0ElsKEmNoYWxsZW5n' - 'ZV9zb2x1dGlvbhgCIAEoCzIqLmFyYml0ZXIuY2xpZW50LmF1dGguQXV0aENoYWxsZW5nZVNvbH' - 'V0aW9uSABSEWNoYWxsZW5nZVNvbHV0aW9uQgkKB3BheWxvYWQ='); - -@$core.Deprecated('Use responseDescriptor instead') -const Response$json = { - '1': 'Response', - '2': [ - { - '1': 'challenge', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.client.auth.AuthChallenge', - '9': 0, - '10': 'challenge' - }, - { - '1': 'result', - '3': 2, - '4': 1, - '5': 14, - '6': '.arbiter.client.auth.AuthResult', - '9': 0, - '10': 'result' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( - 'CghSZXNwb25zZRJCCgljaGFsbGVuZ2UYASABKAsyIi5hcmJpdGVyLmNsaWVudC5hdXRoLkF1dG' - 'hDaGFsbGVuZ2VIAFIJY2hhbGxlbmdlEjkKBnJlc3VsdBgCIAEoDjIfLmFyYml0ZXIuY2xpZW50' - 'LmF1dGguQXV0aFJlc3VsdEgAUgZyZXN1bHRCCQoHcGF5bG9hZA=='); +// This is a generated file - do not edit. +// +// Generated from client/auth.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use authResultDescriptor instead') +const AuthResult$json = { + '1': 'AuthResult', + '2': [ + {'1': 'AUTH_RESULT_UNSPECIFIED', '2': 0}, + {'1': 'AUTH_RESULT_SUCCESS', '2': 1}, + {'1': 'AUTH_RESULT_INVALID_KEY', '2': 2}, + {'1': 'AUTH_RESULT_INVALID_SIGNATURE', '2': 3}, + {'1': 'AUTH_RESULT_APPROVAL_DENIED', '2': 4}, + {'1': 'AUTH_RESULT_NO_USER_AGENTS_ONLINE', '2': 5}, + {'1': 'AUTH_RESULT_INTERNAL', '2': 6}, + ], +}; + +/// Descriptor for `AuthResult`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List authResultDescriptor = $convert.base64Decode( + 'CgpBdXRoUmVzdWx0EhsKF0FVVEhfUkVTVUxUX1VOU1BFQ0lGSUVEEAASFwoTQVVUSF9SRVNVTF' + 'RfU1VDQ0VTUxABEhsKF0FVVEhfUkVTVUxUX0lOVkFMSURfS0VZEAISIQodQVVUSF9SRVNVTFRf' + 'SU5WQUxJRF9TSUdOQVRVUkUQAxIfChtBVVRIX1JFU1VMVF9BUFBST1ZBTF9ERU5JRUQQBBIlCi' + 'FBVVRIX1JFU1VMVF9OT19VU0VSX0FHRU5UU19PTkxJTkUQBRIYChRBVVRIX1JFU1VMVF9JTlRF' + 'Uk5BTBAG'); + +@$core.Deprecated('Use authChallengeRequestDescriptor instead') +const AuthChallengeRequest$json = { + '1': 'AuthChallengeRequest', + '2': [ + {'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'}, + { + '1': 'client_info', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.shared.ClientInfo', + '10': 'clientInfo' + }, + ], +}; + +/// Descriptor for `AuthChallengeRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List authChallengeRequestDescriptor = $convert.base64Decode( + 'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRI7CgtjbGllbn' + 'RfaW5mbxgCIAEoCzIaLmFyYml0ZXIuc2hhcmVkLkNsaWVudEluZm9SCmNsaWVudEluZm8='); + +@$core.Deprecated('Use authChallengeDescriptor instead') +const AuthChallenge$json = { + '1': 'AuthChallenge', + '2': [ + {'1': 'timestamp_nanos', '3': 1, '4': 1, '5': 4, '10': 'timestampNanos'}, + {'1': 'random', '3': 2, '4': 1, '5': 12, '10': 'random'}, + ], +}; + +/// Descriptor for `AuthChallenge`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List authChallengeDescriptor = $convert.base64Decode( + 'Cg1BdXRoQ2hhbGxlbmdlEicKD3RpbWVzdGFtcF9uYW5vcxgBIAEoBFIOdGltZXN0YW1wTmFub3' + 'MSFgoGcmFuZG9tGAIgASgMUgZyYW5kb20='); + +@$core.Deprecated('Use authChallengeSolutionDescriptor instead') +const AuthChallengeSolution$json = { + '1': 'AuthChallengeSolution', + '2': [ + {'1': 'signature', '3': 1, '4': 1, '5': 12, '10': 'signature'}, + ], +}; + +/// Descriptor for `AuthChallengeSolution`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List authChallengeSolutionDescriptor = $convert.base64Decode( + 'ChVBdXRoQ2hhbGxlbmdlU29sdXRpb24SHAoJc2lnbmF0dXJlGAEgASgMUglzaWduYXR1cmU='); + +@$core.Deprecated('Use requestDescriptor instead') +const Request$json = { + '1': 'Request', + '2': [ + { + '1': 'challenge_request', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.client.auth.AuthChallengeRequest', + '9': 0, + '10': 'challengeRequest' + }, + { + '1': 'challenge_solution', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.client.auth.AuthChallengeSolution', + '9': 0, + '10': 'challengeSolution' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( + 'CgdSZXF1ZXN0ElgKEWNoYWxsZW5nZV9yZXF1ZXN0GAEgASgLMikuYXJiaXRlci5jbGllbnQuYX' + 'V0aC5BdXRoQ2hhbGxlbmdlUmVxdWVzdEgAUhBjaGFsbGVuZ2VSZXF1ZXN0ElsKEmNoYWxsZW5n' + 'ZV9zb2x1dGlvbhgCIAEoCzIqLmFyYml0ZXIuY2xpZW50LmF1dGguQXV0aENoYWxsZW5nZVNvbH' + 'V0aW9uSABSEWNoYWxsZW5nZVNvbHV0aW9uQgkKB3BheWxvYWQ='); + +@$core.Deprecated('Use responseDescriptor instead') +const Response$json = { + '1': 'Response', + '2': [ + { + '1': 'challenge', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.client.auth.AuthChallenge', + '9': 0, + '10': 'challenge' + }, + { + '1': 'result', + '3': 2, + '4': 1, + '5': 14, + '6': '.arbiter.client.auth.AuthResult', + '9': 0, + '10': 'result' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( + 'CghSZXNwb25zZRJCCgljaGFsbGVuZ2UYASABKAsyIi5hcmJpdGVyLmNsaWVudC5hdXRoLkF1dG' + 'hDaGFsbGVuZ2VIAFIJY2hhbGxlbmdlEjkKBnJlc3VsdBgCIAEoDjIfLmFyYml0ZXIuY2xpZW50' + 'LmF1dGguQXV0aFJlc3VsdEgAUgZyZXN1bHRCCQoHcGF5bG9hZA=='); diff --git a/useragent/lib/proto/client/evm.pb.dart b/useragent/lib/proto/client/evm.pb.dart index ca9dd65..009e706 100644 --- a/useragent/lib/proto/client/evm.pb.dart +++ b/useragent/lib/proto/client/evm.pb.dart @@ -1,208 +1,208 @@ -// This is a generated file - do not edit. -// -// Generated from client/evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -import '../evm.pb.dart' as $0; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -enum Request_Payload { signTransaction, analyzeTransaction, notSet } - -class Request extends $pb.GeneratedMessage { - factory Request({ - $0.EvmSignTransactionRequest? signTransaction, - $0.EvmAnalyzeTransactionRequest? analyzeTransaction, - }) { - final result = create(); - if (signTransaction != null) result.signTransaction = signTransaction; - if (analyzeTransaction != null) - result.analyzeTransaction = analyzeTransaction; - return result; - } - - Request._(); - - factory Request.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Request.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { - 1: Request_Payload.signTransaction, - 2: Request_Payload.analyzeTransaction, - 0: Request_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Request', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM<$0.EvmSignTransactionRequest>( - 1, _omitFieldNames ? '' : 'signTransaction', - subBuilder: $0.EvmSignTransactionRequest.create) - ..aOM<$0.EvmAnalyzeTransactionRequest>( - 2, _omitFieldNames ? '' : 'analyzeTransaction', - subBuilder: $0.EvmAnalyzeTransactionRequest.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request copyWith(void Function(Request) updates) => - super.copyWith((message) => updates(message as Request)) as Request; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Request create() => Request._(); - @$core.override - Request createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Request getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Request? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $0.EvmSignTransactionRequest get signTransaction => $_getN(0); - @$pb.TagNumber(1) - set signTransaction($0.EvmSignTransactionRequest value) => - $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasSignTransaction() => $_has(0); - @$pb.TagNumber(1) - void clearSignTransaction() => $_clearField(1); - @$pb.TagNumber(1) - $0.EvmSignTransactionRequest ensureSignTransaction() => $_ensure(0); - - @$pb.TagNumber(2) - $0.EvmAnalyzeTransactionRequest get analyzeTransaction => $_getN(1); - @$pb.TagNumber(2) - set analyzeTransaction($0.EvmAnalyzeTransactionRequest value) => - $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasAnalyzeTransaction() => $_has(1); - @$pb.TagNumber(2) - void clearAnalyzeTransaction() => $_clearField(2); - @$pb.TagNumber(2) - $0.EvmAnalyzeTransactionRequest ensureAnalyzeTransaction() => $_ensure(1); -} - -enum Response_Payload { signTransaction, analyzeTransaction, notSet } - -class Response extends $pb.GeneratedMessage { - factory Response({ - $0.EvmSignTransactionResponse? signTransaction, - $0.EvmAnalyzeTransactionResponse? analyzeTransaction, - }) { - final result = create(); - if (signTransaction != null) result.signTransaction = signTransaction; - if (analyzeTransaction != null) - result.analyzeTransaction = analyzeTransaction; - return result; - } - - Response._(); - - factory Response.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Response.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { - 1: Response_Payload.signTransaction, - 2: Response_Payload.analyzeTransaction, - 0: Response_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Response', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM<$0.EvmSignTransactionResponse>( - 1, _omitFieldNames ? '' : 'signTransaction', - subBuilder: $0.EvmSignTransactionResponse.create) - ..aOM<$0.EvmAnalyzeTransactionResponse>( - 2, _omitFieldNames ? '' : 'analyzeTransaction', - subBuilder: $0.EvmAnalyzeTransactionResponse.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response copyWith(void Function(Response) updates) => - super.copyWith((message) => updates(message as Response)) as Response; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Response create() => Response._(); - @$core.override - Response createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Response getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Response? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $0.EvmSignTransactionResponse get signTransaction => $_getN(0); - @$pb.TagNumber(1) - set signTransaction($0.EvmSignTransactionResponse value) => - $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasSignTransaction() => $_has(0); - @$pb.TagNumber(1) - void clearSignTransaction() => $_clearField(1); - @$pb.TagNumber(1) - $0.EvmSignTransactionResponse ensureSignTransaction() => $_ensure(0); - - @$pb.TagNumber(2) - $0.EvmAnalyzeTransactionResponse get analyzeTransaction => $_getN(1); - @$pb.TagNumber(2) - set analyzeTransaction($0.EvmAnalyzeTransactionResponse value) => - $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasAnalyzeTransaction() => $_has(1); - @$pb.TagNumber(2) - void clearAnalyzeTransaction() => $_clearField(2); - @$pb.TagNumber(2) - $0.EvmAnalyzeTransactionResponse ensureAnalyzeTransaction() => $_ensure(1); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from client/evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import '../evm.pb.dart' as $0; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +enum Request_Payload { signTransaction, analyzeTransaction, notSet } + +class Request extends $pb.GeneratedMessage { + factory Request({ + $0.EvmSignTransactionRequest? signTransaction, + $0.EvmAnalyzeTransactionRequest? analyzeTransaction, + }) { + final result = create(); + if (signTransaction != null) result.signTransaction = signTransaction; + if (analyzeTransaction != null) + result.analyzeTransaction = analyzeTransaction; + return result; + } + + Request._(); + + factory Request.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Request.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { + 1: Request_Payload.signTransaction, + 2: Request_Payload.analyzeTransaction, + 0: Request_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Request', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM<$0.EvmSignTransactionRequest>( + 1, _omitFieldNames ? '' : 'signTransaction', + subBuilder: $0.EvmSignTransactionRequest.create) + ..aOM<$0.EvmAnalyzeTransactionRequest>( + 2, _omitFieldNames ? '' : 'analyzeTransaction', + subBuilder: $0.EvmAnalyzeTransactionRequest.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request copyWith(void Function(Request) updates) => + super.copyWith((message) => updates(message as Request)) as Request; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Request create() => Request._(); + @$core.override + Request createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Request getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Request? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $0.EvmSignTransactionRequest get signTransaction => $_getN(0); + @$pb.TagNumber(1) + set signTransaction($0.EvmSignTransactionRequest value) => + $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasSignTransaction() => $_has(0); + @$pb.TagNumber(1) + void clearSignTransaction() => $_clearField(1); + @$pb.TagNumber(1) + $0.EvmSignTransactionRequest ensureSignTransaction() => $_ensure(0); + + @$pb.TagNumber(2) + $0.EvmAnalyzeTransactionRequest get analyzeTransaction => $_getN(1); + @$pb.TagNumber(2) + set analyzeTransaction($0.EvmAnalyzeTransactionRequest value) => + $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasAnalyzeTransaction() => $_has(1); + @$pb.TagNumber(2) + void clearAnalyzeTransaction() => $_clearField(2); + @$pb.TagNumber(2) + $0.EvmAnalyzeTransactionRequest ensureAnalyzeTransaction() => $_ensure(1); +} + +enum Response_Payload { signTransaction, analyzeTransaction, notSet } + +class Response extends $pb.GeneratedMessage { + factory Response({ + $0.EvmSignTransactionResponse? signTransaction, + $0.EvmAnalyzeTransactionResponse? analyzeTransaction, + }) { + final result = create(); + if (signTransaction != null) result.signTransaction = signTransaction; + if (analyzeTransaction != null) + result.analyzeTransaction = analyzeTransaction; + return result; + } + + Response._(); + + factory Response.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Response.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { + 1: Response_Payload.signTransaction, + 2: Response_Payload.analyzeTransaction, + 0: Response_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Response', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.client.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM<$0.EvmSignTransactionResponse>( + 1, _omitFieldNames ? '' : 'signTransaction', + subBuilder: $0.EvmSignTransactionResponse.create) + ..aOM<$0.EvmAnalyzeTransactionResponse>( + 2, _omitFieldNames ? '' : 'analyzeTransaction', + subBuilder: $0.EvmAnalyzeTransactionResponse.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response copyWith(void Function(Response) updates) => + super.copyWith((message) => updates(message as Response)) as Response; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Response create() => Response._(); + @$core.override + Response createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Response getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Response? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $0.EvmSignTransactionResponse get signTransaction => $_getN(0); + @$pb.TagNumber(1) + set signTransaction($0.EvmSignTransactionResponse value) => + $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasSignTransaction() => $_has(0); + @$pb.TagNumber(1) + void clearSignTransaction() => $_clearField(1); + @$pb.TagNumber(1) + $0.EvmSignTransactionResponse ensureSignTransaction() => $_ensure(0); + + @$pb.TagNumber(2) + $0.EvmAnalyzeTransactionResponse get analyzeTransaction => $_getN(1); + @$pb.TagNumber(2) + set analyzeTransaction($0.EvmAnalyzeTransactionResponse value) => + $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasAnalyzeTransaction() => $_has(1); + @$pb.TagNumber(2) + void clearAnalyzeTransaction() => $_clearField(2); + @$pb.TagNumber(2) + $0.EvmAnalyzeTransactionResponse ensureAnalyzeTransaction() => $_ensure(1); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/client/evm.pbenum.dart b/useragent/lib/proto/client/evm.pbenum.dart index cc33348..229af53 100644 --- a/useragent/lib/proto/client/evm.pbenum.dart +++ b/useragent/lib/proto/client/evm.pbenum.dart @@ -1,11 +1,11 @@ -// This is a generated file - do not edit. -// -// Generated from client/evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// This is a generated file - do not edit. +// +// Generated from client/evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports diff --git a/useragent/lib/proto/client/evm.pbjson.dart b/useragent/lib/proto/client/evm.pbjson.dart index af9f349..6a1aa5e 100644 --- a/useragent/lib/proto/client/evm.pbjson.dart +++ b/useragent/lib/proto/client/evm.pbjson.dart @@ -1,86 +1,86 @@ -// This is a generated file - do not edit. -// -// Generated from client/evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use requestDescriptor instead') -const Request$json = { - '1': 'Request', - '2': [ - { - '1': 'sign_transaction', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmSignTransactionRequest', - '9': 0, - '10': 'signTransaction' - }, - { - '1': 'analyze_transaction', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmAnalyzeTransactionRequest', - '9': 0, - '10': 'analyzeTransaction' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( - 'CgdSZXF1ZXN0ElMKEHNpZ25fdHJhbnNhY3Rpb24YASABKAsyJi5hcmJpdGVyLmV2bS5Fdm1TaW' - 'duVHJhbnNhY3Rpb25SZXF1ZXN0SABSD3NpZ25UcmFuc2FjdGlvbhJcChNhbmFseXplX3RyYW5z' - 'YWN0aW9uGAIgASgLMikuYXJiaXRlci5ldm0uRXZtQW5hbHl6ZVRyYW5zYWN0aW9uUmVxdWVzdE' - 'gAUhJhbmFseXplVHJhbnNhY3Rpb25CCQoHcGF5bG9hZA=='); - -@$core.Deprecated('Use responseDescriptor instead') -const Response$json = { - '1': 'Response', - '2': [ - { - '1': 'sign_transaction', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmSignTransactionResponse', - '9': 0, - '10': 'signTransaction' - }, - { - '1': 'analyze_transaction', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmAnalyzeTransactionResponse', - '9': 0, - '10': 'analyzeTransaction' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( - 'CghSZXNwb25zZRJUChBzaWduX3RyYW5zYWN0aW9uGAEgASgLMicuYXJiaXRlci5ldm0uRXZtU2' - 'lnblRyYW5zYWN0aW9uUmVzcG9uc2VIAFIPc2lnblRyYW5zYWN0aW9uEl0KE2FuYWx5emVfdHJh' - 'bnNhY3Rpb24YAiABKAsyKi5hcmJpdGVyLmV2bS5Fdm1BbmFseXplVHJhbnNhY3Rpb25SZXNwb2' - '5zZUgAUhJhbmFseXplVHJhbnNhY3Rpb25CCQoHcGF5bG9hZA=='); +// This is a generated file - do not edit. +// +// Generated from client/evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use requestDescriptor instead') +const Request$json = { + '1': 'Request', + '2': [ + { + '1': 'sign_transaction', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmSignTransactionRequest', + '9': 0, + '10': 'signTransaction' + }, + { + '1': 'analyze_transaction', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmAnalyzeTransactionRequest', + '9': 0, + '10': 'analyzeTransaction' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( + 'CgdSZXF1ZXN0ElMKEHNpZ25fdHJhbnNhY3Rpb24YASABKAsyJi5hcmJpdGVyLmV2bS5Fdm1TaW' + 'duVHJhbnNhY3Rpb25SZXF1ZXN0SABSD3NpZ25UcmFuc2FjdGlvbhJcChNhbmFseXplX3RyYW5z' + 'YWN0aW9uGAIgASgLMikuYXJiaXRlci5ldm0uRXZtQW5hbHl6ZVRyYW5zYWN0aW9uUmVxdWVzdE' + 'gAUhJhbmFseXplVHJhbnNhY3Rpb25CCQoHcGF5bG9hZA=='); + +@$core.Deprecated('Use responseDescriptor instead') +const Response$json = { + '1': 'Response', + '2': [ + { + '1': 'sign_transaction', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmSignTransactionResponse', + '9': 0, + '10': 'signTransaction' + }, + { + '1': 'analyze_transaction', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmAnalyzeTransactionResponse', + '9': 0, + '10': 'analyzeTransaction' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( + 'CghSZXNwb25zZRJUChBzaWduX3RyYW5zYWN0aW9uGAEgASgLMicuYXJiaXRlci5ldm0uRXZtU2' + 'lnblRyYW5zYWN0aW9uUmVzcG9uc2VIAFIPc2lnblRyYW5zYWN0aW9uEl0KE2FuYWx5emVfdHJh' + 'bnNhY3Rpb24YAiABKAsyKi5hcmJpdGVyLmV2bS5Fdm1BbmFseXplVHJhbnNhY3Rpb25SZXNwb2' + '5zZUgAUhJhbmFseXplVHJhbnNhY3Rpb25CCQoHcGF5bG9hZA=='); diff --git a/useragent/lib/proto/client/vault.pb.dart b/useragent/lib/proto/client/vault.pb.dart index c2eb972..9755fac 100644 --- a/useragent/lib/proto/client/vault.pb.dart +++ b/useragent/lib/proto/client/vault.pb.dart @@ -1,161 +1,161 @@ -// This is a generated file - do not edit. -// -// Generated from client/vault.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; -import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $0; - -import '../shared/vault.pbenum.dart' as $1; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -enum Request_Payload { queryState, notSet } - -class Request extends $pb.GeneratedMessage { - factory Request({ - $0.Empty? queryState, - }) { - final result = create(); - if (queryState != null) result.queryState = queryState; - return result; - } - - Request._(); - - factory Request.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Request.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { - 1: Request_Payload.queryState, - 0: Request_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Request', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.client.vault'), - createEmptyInstance: create) - ..oo(0, [1]) - ..aOM<$0.Empty>(1, _omitFieldNames ? '' : 'queryState', - subBuilder: $0.Empty.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request copyWith(void Function(Request) updates) => - super.copyWith((message) => updates(message as Request)) as Request; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Request create() => Request._(); - @$core.override - Request createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Request getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Request? _defaultInstance; - - @$pb.TagNumber(1) - Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $0.Empty get queryState => $_getN(0); - @$pb.TagNumber(1) - set queryState($0.Empty value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasQueryState() => $_has(0); - @$pb.TagNumber(1) - void clearQueryState() => $_clearField(1); - @$pb.TagNumber(1) - $0.Empty ensureQueryState() => $_ensure(0); -} - -enum Response_Payload { state, notSet } - -class Response extends $pb.GeneratedMessage { - factory Response({ - $1.VaultState? state, - }) { - final result = create(); - if (state != null) result.state = state; - return result; - } - - Response._(); - - factory Response.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Response.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { - 1: Response_Payload.state, - 0: Response_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Response', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.client.vault'), - createEmptyInstance: create) - ..oo(0, [1]) - ..aE<$1.VaultState>(1, _omitFieldNames ? '' : 'state', - enumValues: $1.VaultState.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response copyWith(void Function(Response) updates) => - super.copyWith((message) => updates(message as Response)) as Response; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Response create() => Response._(); - @$core.override - Response createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Response getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Response? _defaultInstance; - - @$pb.TagNumber(1) - Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $1.VaultState get state => $_getN(0); - @$pb.TagNumber(1) - set state($1.VaultState value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasState() => $_has(0); - @$pb.TagNumber(1) - void clearState() => $_clearField(1); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from client/vault.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $0; + +import '../shared/vault.pbenum.dart' as $1; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +enum Request_Payload { queryState, notSet } + +class Request extends $pb.GeneratedMessage { + factory Request({ + $0.Empty? queryState, + }) { + final result = create(); + if (queryState != null) result.queryState = queryState; + return result; + } + + Request._(); + + factory Request.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Request.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { + 1: Request_Payload.queryState, + 0: Request_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Request', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.client.vault'), + createEmptyInstance: create) + ..oo(0, [1]) + ..aOM<$0.Empty>(1, _omitFieldNames ? '' : 'queryState', + subBuilder: $0.Empty.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request copyWith(void Function(Request) updates) => + super.copyWith((message) => updates(message as Request)) as Request; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Request create() => Request._(); + @$core.override + Request createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Request getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Request? _defaultInstance; + + @$pb.TagNumber(1) + Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $0.Empty get queryState => $_getN(0); + @$pb.TagNumber(1) + set queryState($0.Empty value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasQueryState() => $_has(0); + @$pb.TagNumber(1) + void clearQueryState() => $_clearField(1); + @$pb.TagNumber(1) + $0.Empty ensureQueryState() => $_ensure(0); +} + +enum Response_Payload { state, notSet } + +class Response extends $pb.GeneratedMessage { + factory Response({ + $1.VaultState? state, + }) { + final result = create(); + if (state != null) result.state = state; + return result; + } + + Response._(); + + factory Response.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Response.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { + 1: Response_Payload.state, + 0: Response_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Response', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.client.vault'), + createEmptyInstance: create) + ..oo(0, [1]) + ..aE<$1.VaultState>(1, _omitFieldNames ? '' : 'state', + enumValues: $1.VaultState.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response copyWith(void Function(Response) updates) => + super.copyWith((message) => updates(message as Response)) as Response; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Response create() => Response._(); + @$core.override + Response createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Response getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Response? _defaultInstance; + + @$pb.TagNumber(1) + Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $1.VaultState get state => $_getN(0); + @$pb.TagNumber(1) + set state($1.VaultState value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasState() => $_has(0); + @$pb.TagNumber(1) + void clearState() => $_clearField(1); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/client/vault.pbenum.dart b/useragent/lib/proto/client/vault.pbenum.dart index ab70d5c..9cfa53b 100644 --- a/useragent/lib/proto/client/vault.pbenum.dart +++ b/useragent/lib/proto/client/vault.pbenum.dart @@ -1,11 +1,11 @@ -// This is a generated file - do not edit. -// -// Generated from client/vault.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// This is a generated file - do not edit. +// +// Generated from client/vault.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports diff --git a/useragent/lib/proto/client/vault.pbjson.dart b/useragent/lib/proto/client/vault.pbjson.dart index 64aad64..2f0f085 100644 --- a/useragent/lib/proto/client/vault.pbjson.dart +++ b/useragent/lib/proto/client/vault.pbjson.dart @@ -1,64 +1,64 @@ -// This is a generated file - do not edit. -// -// Generated from client/vault.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use requestDescriptor instead') -const Request$json = { - '1': 'Request', - '2': [ - { - '1': 'query_state', - '3': 1, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'queryState' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( - 'CgdSZXF1ZXN0EjkKC3F1ZXJ5X3N0YXRlGAEgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SA' - 'BSCnF1ZXJ5U3RhdGVCCQoHcGF5bG9hZA=='); - -@$core.Deprecated('Use responseDescriptor instead') -const Response$json = { - '1': 'Response', - '2': [ - { - '1': 'state', - '3': 1, - '4': 1, - '5': 14, - '6': '.arbiter.shared.VaultState', - '9': 0, - '10': 'state' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( - 'CghSZXNwb25zZRIyCgVzdGF0ZRgBIAEoDjIaLmFyYml0ZXIuc2hhcmVkLlZhdWx0U3RhdGVIAF' - 'IFc3RhdGVCCQoHcGF5bG9hZA=='); +// This is a generated file - do not edit. +// +// Generated from client/vault.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use requestDescriptor instead') +const Request$json = { + '1': 'Request', + '2': [ + { + '1': 'query_state', + '3': 1, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'queryState' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( + 'CgdSZXF1ZXN0EjkKC3F1ZXJ5X3N0YXRlGAEgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SA' + 'BSCnF1ZXJ5U3RhdGVCCQoHcGF5bG9hZA=='); + +@$core.Deprecated('Use responseDescriptor instead') +const Response$json = { + '1': 'Response', + '2': [ + { + '1': 'state', + '3': 1, + '4': 1, + '5': 14, + '6': '.arbiter.shared.VaultState', + '9': 0, + '10': 'state' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( + 'CghSZXNwb25zZRIyCgVzdGF0ZRgBIAEoDjIaLmFyYml0ZXIuc2hhcmVkLlZhdWx0U3RhdGVIAF' + 'IFc3RhdGVCCQoHcGF5bG9hZA=='); diff --git a/useragent/lib/proto/evm.pb.dart b/useragent/lib/proto/evm.pb.dart index 61fc3ae..9d8f339 100644 --- a/useragent/lib/proto/evm.pb.dart +++ b/useragent/lib/proto/evm.pb.dart @@ -1,1764 +1,1764 @@ -// This is a generated file - do not edit. -// -// Generated from evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:fixnum/fixnum.dart' as $fixnum; -import 'package:protobuf/protobuf.dart' as $pb; -import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $1; -import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart' - as $0; - -import 'evm.pbenum.dart'; -import 'shared/evm.pb.dart' as $2; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -export 'evm.pbenum.dart'; - -class WalletEntry extends $pb.GeneratedMessage { - factory WalletEntry({ - $core.int? id, - $core.List<$core.int>? address, - }) { - final result = create(); - if (id != null) result.id = id; - if (address != null) result.address = address; - return result; - } - - WalletEntry._(); - - factory WalletEntry.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory WalletEntry.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'WalletEntry', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'id') - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'address', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletEntry clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletEntry copyWith(void Function(WalletEntry) updates) => - super.copyWith((message) => updates(message as WalletEntry)) - as WalletEntry; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static WalletEntry create() => WalletEntry._(); - @$core.override - WalletEntry createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static WalletEntry getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static WalletEntry? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get id => $_getIZ(0); - @$pb.TagNumber(1) - set id($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasId() => $_has(0); - @$pb.TagNumber(1) - void clearId() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get address => $_getN(1); - @$pb.TagNumber(2) - set address($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasAddress() => $_has(1); - @$pb.TagNumber(2) - void clearAddress() => $_clearField(2); -} - -class WalletList extends $pb.GeneratedMessage { - factory WalletList({ - $core.Iterable? wallets, - }) { - final result = create(); - if (wallets != null) result.wallets.addAll(wallets); - return result; - } - - WalletList._(); - - factory WalletList.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory WalletList.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'WalletList', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..pPM(1, _omitFieldNames ? '' : 'wallets', - subBuilder: WalletEntry.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletList clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletList copyWith(void Function(WalletList) updates) => - super.copyWith((message) => updates(message as WalletList)) as WalletList; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static WalletList create() => WalletList._(); - @$core.override - WalletList createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static WalletList getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static WalletList? _defaultInstance; - - @$pb.TagNumber(1) - $pb.PbList get wallets => $_getList(0); -} - -enum WalletCreateResponse_Result { wallet, error, notSet } - -class WalletCreateResponse extends $pb.GeneratedMessage { - factory WalletCreateResponse({ - WalletEntry? wallet, - EvmError? error, - }) { - final result = create(); - if (wallet != null) result.wallet = wallet; - if (error != null) result.error = error; - return result; - } - - WalletCreateResponse._(); - - factory WalletCreateResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory WalletCreateResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, WalletCreateResponse_Result> - _WalletCreateResponse_ResultByTag = { - 1: WalletCreateResponse_Result.wallet, - 2: WalletCreateResponse_Result.error, - 0: WalletCreateResponse_Result.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'WalletCreateResponse', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'wallet', - subBuilder: WalletEntry.create) - ..aE(2, _omitFieldNames ? '' : 'error', - enumValues: EvmError.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletCreateResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletCreateResponse copyWith(void Function(WalletCreateResponse) updates) => - super.copyWith((message) => updates(message as WalletCreateResponse)) - as WalletCreateResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static WalletCreateResponse create() => WalletCreateResponse._(); - @$core.override - WalletCreateResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static WalletCreateResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static WalletCreateResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - WalletCreateResponse_Result whichResult() => - _WalletCreateResponse_ResultByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearResult() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - WalletEntry get wallet => $_getN(0); - @$pb.TagNumber(1) - set wallet(WalletEntry value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasWallet() => $_has(0); - @$pb.TagNumber(1) - void clearWallet() => $_clearField(1); - @$pb.TagNumber(1) - WalletEntry ensureWallet() => $_ensure(0); - - @$pb.TagNumber(2) - EvmError get error => $_getN(1); - @$pb.TagNumber(2) - set error(EvmError value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasError() => $_has(1); - @$pb.TagNumber(2) - void clearError() => $_clearField(2); -} - -enum WalletListResponse_Result { wallets, error, notSet } - -class WalletListResponse extends $pb.GeneratedMessage { - factory WalletListResponse({ - WalletList? wallets, - EvmError? error, - }) { - final result = create(); - if (wallets != null) result.wallets = wallets; - if (error != null) result.error = error; - return result; - } - - WalletListResponse._(); - - factory WalletListResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory WalletListResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, WalletListResponse_Result> - _WalletListResponse_ResultByTag = { - 1: WalletListResponse_Result.wallets, - 2: WalletListResponse_Result.error, - 0: WalletListResponse_Result.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'WalletListResponse', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'wallets', - subBuilder: WalletList.create) - ..aE(2, _omitFieldNames ? '' : 'error', - enumValues: EvmError.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletListResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletListResponse copyWith(void Function(WalletListResponse) updates) => - super.copyWith((message) => updates(message as WalletListResponse)) - as WalletListResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static WalletListResponse create() => WalletListResponse._(); - @$core.override - WalletListResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static WalletListResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static WalletListResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - WalletListResponse_Result whichResult() => - _WalletListResponse_ResultByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearResult() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - WalletList get wallets => $_getN(0); - @$pb.TagNumber(1) - set wallets(WalletList value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasWallets() => $_has(0); - @$pb.TagNumber(1) - void clearWallets() => $_clearField(1); - @$pb.TagNumber(1) - WalletList ensureWallets() => $_ensure(0); - - @$pb.TagNumber(2) - EvmError get error => $_getN(1); - @$pb.TagNumber(2) - set error(EvmError value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasError() => $_has(1); - @$pb.TagNumber(2) - void clearError() => $_clearField(2); -} - -class TransactionRateLimit extends $pb.GeneratedMessage { - factory TransactionRateLimit({ - $core.int? count, - $fixnum.Int64? windowSecs, - }) { - final result = create(); - if (count != null) result.count = count; - if (windowSecs != null) result.windowSecs = windowSecs; - return result; - } - - TransactionRateLimit._(); - - factory TransactionRateLimit.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory TransactionRateLimit.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'TransactionRateLimit', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'count', fieldType: $pb.PbFieldType.OU3) - ..aInt64(2, _omitFieldNames ? '' : 'windowSecs') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - TransactionRateLimit clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - TransactionRateLimit copyWith(void Function(TransactionRateLimit) updates) => - super.copyWith((message) => updates(message as TransactionRateLimit)) - as TransactionRateLimit; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static TransactionRateLimit create() => TransactionRateLimit._(); - @$core.override - TransactionRateLimit createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static TransactionRateLimit getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static TransactionRateLimit? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get count => $_getIZ(0); - @$pb.TagNumber(1) - set count($core.int value) => $_setUnsignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasCount() => $_has(0); - @$pb.TagNumber(1) - void clearCount() => $_clearField(1); - - @$pb.TagNumber(2) - $fixnum.Int64 get windowSecs => $_getI64(1); - @$pb.TagNumber(2) - set windowSecs($fixnum.Int64 value) => $_setInt64(1, value); - @$pb.TagNumber(2) - $core.bool hasWindowSecs() => $_has(1); - @$pb.TagNumber(2) - void clearWindowSecs() => $_clearField(2); -} - -class VolumeRateLimit extends $pb.GeneratedMessage { - factory VolumeRateLimit({ - $core.List<$core.int>? maxVolume, - $fixnum.Int64? windowSecs, - }) { - final result = create(); - if (maxVolume != null) result.maxVolume = maxVolume; - if (windowSecs != null) result.windowSecs = windowSecs; - return result; - } - - VolumeRateLimit._(); - - factory VolumeRateLimit.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory VolumeRateLimit.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'VolumeRateLimit', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'maxVolume', $pb.PbFieldType.OY) - ..aInt64(2, _omitFieldNames ? '' : 'windowSecs') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - VolumeRateLimit clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - VolumeRateLimit copyWith(void Function(VolumeRateLimit) updates) => - super.copyWith((message) => updates(message as VolumeRateLimit)) - as VolumeRateLimit; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static VolumeRateLimit create() => VolumeRateLimit._(); - @$core.override - VolumeRateLimit createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static VolumeRateLimit getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static VolumeRateLimit? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get maxVolume => $_getN(0); - @$pb.TagNumber(1) - set maxVolume($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasMaxVolume() => $_has(0); - @$pb.TagNumber(1) - void clearMaxVolume() => $_clearField(1); - - @$pb.TagNumber(2) - $fixnum.Int64 get windowSecs => $_getI64(1); - @$pb.TagNumber(2) - set windowSecs($fixnum.Int64 value) => $_setInt64(1, value); - @$pb.TagNumber(2) - $core.bool hasWindowSecs() => $_has(1); - @$pb.TagNumber(2) - void clearWindowSecs() => $_clearField(2); -} - -class SharedSettings extends $pb.GeneratedMessage { - factory SharedSettings({ - $core.int? walletAccessId, - $fixnum.Int64? chainId, - $0.Timestamp? validFrom, - $0.Timestamp? validUntil, - $core.List<$core.int>? maxGasFeePerGas, - $core.List<$core.int>? maxPriorityFeePerGas, - TransactionRateLimit? rateLimit, - }) { - final result = create(); - if (walletAccessId != null) result.walletAccessId = walletAccessId; - if (chainId != null) result.chainId = chainId; - if (validFrom != null) result.validFrom = validFrom; - if (validUntil != null) result.validUntil = validUntil; - if (maxGasFeePerGas != null) result.maxGasFeePerGas = maxGasFeePerGas; - if (maxPriorityFeePerGas != null) - result.maxPriorityFeePerGas = maxPriorityFeePerGas; - if (rateLimit != null) result.rateLimit = rateLimit; - return result; - } - - SharedSettings._(); - - factory SharedSettings.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory SharedSettings.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'SharedSettings', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'walletAccessId') - ..a<$fixnum.Int64>(2, _omitFieldNames ? '' : 'chainId', $pb.PbFieldType.OU6, - defaultOrMaker: $fixnum.Int64.ZERO) - ..aOM<$0.Timestamp>(3, _omitFieldNames ? '' : 'validFrom', - subBuilder: $0.Timestamp.create) - ..aOM<$0.Timestamp>(4, _omitFieldNames ? '' : 'validUntil', - subBuilder: $0.Timestamp.create) - ..a<$core.List<$core.int>>( - 5, _omitFieldNames ? '' : 'maxGasFeePerGas', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 6, _omitFieldNames ? '' : 'maxPriorityFeePerGas', $pb.PbFieldType.OY) - ..aOM(7, _omitFieldNames ? '' : 'rateLimit', - subBuilder: TransactionRateLimit.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - SharedSettings clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - SharedSettings copyWith(void Function(SharedSettings) updates) => - super.copyWith((message) => updates(message as SharedSettings)) - as SharedSettings; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static SharedSettings create() => SharedSettings._(); - @$core.override - SharedSettings createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static SharedSettings getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static SharedSettings? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get walletAccessId => $_getIZ(0); - @$pb.TagNumber(1) - set walletAccessId($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasWalletAccessId() => $_has(0); - @$pb.TagNumber(1) - void clearWalletAccessId() => $_clearField(1); - - @$pb.TagNumber(2) - $fixnum.Int64 get chainId => $_getI64(1); - @$pb.TagNumber(2) - set chainId($fixnum.Int64 value) => $_setInt64(1, value); - @$pb.TagNumber(2) - $core.bool hasChainId() => $_has(1); - @$pb.TagNumber(2) - void clearChainId() => $_clearField(2); - - @$pb.TagNumber(3) - $0.Timestamp get validFrom => $_getN(2); - @$pb.TagNumber(3) - set validFrom($0.Timestamp value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasValidFrom() => $_has(2); - @$pb.TagNumber(3) - void clearValidFrom() => $_clearField(3); - @$pb.TagNumber(3) - $0.Timestamp ensureValidFrom() => $_ensure(2); - - @$pb.TagNumber(4) - $0.Timestamp get validUntil => $_getN(3); - @$pb.TagNumber(4) - set validUntil($0.Timestamp value) => $_setField(4, value); - @$pb.TagNumber(4) - $core.bool hasValidUntil() => $_has(3); - @$pb.TagNumber(4) - void clearValidUntil() => $_clearField(4); - @$pb.TagNumber(4) - $0.Timestamp ensureValidUntil() => $_ensure(3); - - @$pb.TagNumber(5) - $core.List<$core.int> get maxGasFeePerGas => $_getN(4); - @$pb.TagNumber(5) - set maxGasFeePerGas($core.List<$core.int> value) => $_setBytes(4, value); - @$pb.TagNumber(5) - $core.bool hasMaxGasFeePerGas() => $_has(4); - @$pb.TagNumber(5) - void clearMaxGasFeePerGas() => $_clearField(5); - - @$pb.TagNumber(6) - $core.List<$core.int> get maxPriorityFeePerGas => $_getN(5); - @$pb.TagNumber(6) - set maxPriorityFeePerGas($core.List<$core.int> value) => $_setBytes(5, value); - @$pb.TagNumber(6) - $core.bool hasMaxPriorityFeePerGas() => $_has(5); - @$pb.TagNumber(6) - void clearMaxPriorityFeePerGas() => $_clearField(6); - - @$pb.TagNumber(7) - TransactionRateLimit get rateLimit => $_getN(6); - @$pb.TagNumber(7) - set rateLimit(TransactionRateLimit value) => $_setField(7, value); - @$pb.TagNumber(7) - $core.bool hasRateLimit() => $_has(6); - @$pb.TagNumber(7) - void clearRateLimit() => $_clearField(7); - @$pb.TagNumber(7) - TransactionRateLimit ensureRateLimit() => $_ensure(6); -} - -class EtherTransferSettings extends $pb.GeneratedMessage { - factory EtherTransferSettings({ - $core.Iterable<$core.List<$core.int>>? targets, - VolumeRateLimit? limit, - }) { - final result = create(); - if (targets != null) result.targets.addAll(targets); - if (limit != null) result.limit = limit; - return result; - } - - EtherTransferSettings._(); - - factory EtherTransferSettings.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EtherTransferSettings.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EtherTransferSettings', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..p<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'targets', $pb.PbFieldType.PY) - ..aOM(2, _omitFieldNames ? '' : 'limit', - subBuilder: VolumeRateLimit.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EtherTransferSettings clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EtherTransferSettings copyWith( - void Function(EtherTransferSettings) updates) => - super.copyWith((message) => updates(message as EtherTransferSettings)) - as EtherTransferSettings; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EtherTransferSettings create() => EtherTransferSettings._(); - @$core.override - EtherTransferSettings createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EtherTransferSettings getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EtherTransferSettings? _defaultInstance; - - @$pb.TagNumber(1) - $pb.PbList<$core.List<$core.int>> get targets => $_getList(0); - - @$pb.TagNumber(2) - VolumeRateLimit get limit => $_getN(1); - @$pb.TagNumber(2) - set limit(VolumeRateLimit value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasLimit() => $_has(1); - @$pb.TagNumber(2) - void clearLimit() => $_clearField(2); - @$pb.TagNumber(2) - VolumeRateLimit ensureLimit() => $_ensure(1); -} - -class TokenTransferSettings extends $pb.GeneratedMessage { - factory TokenTransferSettings({ - $core.List<$core.int>? tokenContract, - $core.List<$core.int>? target, - $core.Iterable? volumeLimits, - }) { - final result = create(); - if (tokenContract != null) result.tokenContract = tokenContract; - if (target != null) result.target = target; - if (volumeLimits != null) result.volumeLimits.addAll(volumeLimits); - return result; - } - - TokenTransferSettings._(); - - factory TokenTransferSettings.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory TokenTransferSettings.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'TokenTransferSettings', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'tokenContract', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'target', $pb.PbFieldType.OY) - ..pPM(3, _omitFieldNames ? '' : 'volumeLimits', - subBuilder: VolumeRateLimit.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - TokenTransferSettings clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - TokenTransferSettings copyWith( - void Function(TokenTransferSettings) updates) => - super.copyWith((message) => updates(message as TokenTransferSettings)) - as TokenTransferSettings; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static TokenTransferSettings create() => TokenTransferSettings._(); - @$core.override - TokenTransferSettings createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static TokenTransferSettings getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static TokenTransferSettings? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get tokenContract => $_getN(0); - @$pb.TagNumber(1) - set tokenContract($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasTokenContract() => $_has(0); - @$pb.TagNumber(1) - void clearTokenContract() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get target => $_getN(1); - @$pb.TagNumber(2) - set target($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasTarget() => $_has(1); - @$pb.TagNumber(2) - void clearTarget() => $_clearField(2); - - @$pb.TagNumber(3) - $pb.PbList get volumeLimits => $_getList(2); -} - -enum SpecificGrant_Grant { etherTransfer, tokenTransfer, notSet } - -class SpecificGrant extends $pb.GeneratedMessage { - factory SpecificGrant({ - EtherTransferSettings? etherTransfer, - TokenTransferSettings? tokenTransfer, - }) { - final result = create(); - if (etherTransfer != null) result.etherTransfer = etherTransfer; - if (tokenTransfer != null) result.tokenTransfer = tokenTransfer; - return result; - } - - SpecificGrant._(); - - factory SpecificGrant.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory SpecificGrant.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, SpecificGrant_Grant> - _SpecificGrant_GrantByTag = { - 1: SpecificGrant_Grant.etherTransfer, - 2: SpecificGrant_Grant.tokenTransfer, - 0: SpecificGrant_Grant.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'SpecificGrant', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'etherTransfer', - subBuilder: EtherTransferSettings.create) - ..aOM(2, _omitFieldNames ? '' : 'tokenTransfer', - subBuilder: TokenTransferSettings.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - SpecificGrant clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - SpecificGrant copyWith(void Function(SpecificGrant) updates) => - super.copyWith((message) => updates(message as SpecificGrant)) - as SpecificGrant; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static SpecificGrant create() => SpecificGrant._(); - @$core.override - SpecificGrant createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static SpecificGrant getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static SpecificGrant? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - SpecificGrant_Grant whichGrant() => - _SpecificGrant_GrantByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearGrant() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - EtherTransferSettings get etherTransfer => $_getN(0); - @$pb.TagNumber(1) - set etherTransfer(EtherTransferSettings value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasEtherTransfer() => $_has(0); - @$pb.TagNumber(1) - void clearEtherTransfer() => $_clearField(1); - @$pb.TagNumber(1) - EtherTransferSettings ensureEtherTransfer() => $_ensure(0); - - @$pb.TagNumber(2) - TokenTransferSettings get tokenTransfer => $_getN(1); - @$pb.TagNumber(2) - set tokenTransfer(TokenTransferSettings value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasTokenTransfer() => $_has(1); - @$pb.TagNumber(2) - void clearTokenTransfer() => $_clearField(2); - @$pb.TagNumber(2) - TokenTransferSettings ensureTokenTransfer() => $_ensure(1); -} - -/// --- UserAgent grant management --- -class EvmGrantCreateRequest extends $pb.GeneratedMessage { - factory EvmGrantCreateRequest({ - SharedSettings? shared, - SpecificGrant? specific, - }) { - final result = create(); - if (shared != null) result.shared = shared; - if (specific != null) result.specific = specific; - return result; - } - - EvmGrantCreateRequest._(); - - factory EvmGrantCreateRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmGrantCreateRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmGrantCreateRequest', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'shared', - subBuilder: SharedSettings.create) - ..aOM(2, _omitFieldNames ? '' : 'specific', - subBuilder: SpecificGrant.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantCreateRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantCreateRequest copyWith( - void Function(EvmGrantCreateRequest) updates) => - super.copyWith((message) => updates(message as EvmGrantCreateRequest)) - as EvmGrantCreateRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmGrantCreateRequest create() => EvmGrantCreateRequest._(); - @$core.override - EvmGrantCreateRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmGrantCreateRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmGrantCreateRequest? _defaultInstance; - - @$pb.TagNumber(1) - SharedSettings get shared => $_getN(0); - @$pb.TagNumber(1) - set shared(SharedSettings value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasShared() => $_has(0); - @$pb.TagNumber(1) - void clearShared() => $_clearField(1); - @$pb.TagNumber(1) - SharedSettings ensureShared() => $_ensure(0); - - @$pb.TagNumber(2) - SpecificGrant get specific => $_getN(1); - @$pb.TagNumber(2) - set specific(SpecificGrant value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasSpecific() => $_has(1); - @$pb.TagNumber(2) - void clearSpecific() => $_clearField(2); - @$pb.TagNumber(2) - SpecificGrant ensureSpecific() => $_ensure(1); -} - -enum EvmGrantCreateResponse_Result { grantId, error, notSet } - -class EvmGrantCreateResponse extends $pb.GeneratedMessage { - factory EvmGrantCreateResponse({ - $core.int? grantId, - EvmError? error, - }) { - final result = create(); - if (grantId != null) result.grantId = grantId; - if (error != null) result.error = error; - return result; - } - - EvmGrantCreateResponse._(); - - factory EvmGrantCreateResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmGrantCreateResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, EvmGrantCreateResponse_Result> - _EvmGrantCreateResponse_ResultByTag = { - 1: EvmGrantCreateResponse_Result.grantId, - 2: EvmGrantCreateResponse_Result.error, - 0: EvmGrantCreateResponse_Result.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmGrantCreateResponse', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aI(1, _omitFieldNames ? '' : 'grantId') - ..aE(2, _omitFieldNames ? '' : 'error', - enumValues: EvmError.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantCreateResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantCreateResponse copyWith( - void Function(EvmGrantCreateResponse) updates) => - super.copyWith((message) => updates(message as EvmGrantCreateResponse)) - as EvmGrantCreateResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmGrantCreateResponse create() => EvmGrantCreateResponse._(); - @$core.override - EvmGrantCreateResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmGrantCreateResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmGrantCreateResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - EvmGrantCreateResponse_Result whichResult() => - _EvmGrantCreateResponse_ResultByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearResult() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $core.int get grantId => $_getIZ(0); - @$pb.TagNumber(1) - set grantId($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasGrantId() => $_has(0); - @$pb.TagNumber(1) - void clearGrantId() => $_clearField(1); - - @$pb.TagNumber(2) - EvmError get error => $_getN(1); - @$pb.TagNumber(2) - set error(EvmError value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasError() => $_has(1); - @$pb.TagNumber(2) - void clearError() => $_clearField(2); -} - -class EvmGrantDeleteRequest extends $pb.GeneratedMessage { - factory EvmGrantDeleteRequest({ - $core.int? grantId, - }) { - final result = create(); - if (grantId != null) result.grantId = grantId; - return result; - } - - EvmGrantDeleteRequest._(); - - factory EvmGrantDeleteRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmGrantDeleteRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmGrantDeleteRequest', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'grantId') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantDeleteRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantDeleteRequest copyWith( - void Function(EvmGrantDeleteRequest) updates) => - super.copyWith((message) => updates(message as EvmGrantDeleteRequest)) - as EvmGrantDeleteRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmGrantDeleteRequest create() => EvmGrantDeleteRequest._(); - @$core.override - EvmGrantDeleteRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmGrantDeleteRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmGrantDeleteRequest? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get grantId => $_getIZ(0); - @$pb.TagNumber(1) - set grantId($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasGrantId() => $_has(0); - @$pb.TagNumber(1) - void clearGrantId() => $_clearField(1); -} - -enum EvmGrantDeleteResponse_Result { ok, error, notSet } - -class EvmGrantDeleteResponse extends $pb.GeneratedMessage { - factory EvmGrantDeleteResponse({ - $1.Empty? ok, - EvmError? error, - }) { - final result = create(); - if (ok != null) result.ok = ok; - if (error != null) result.error = error; - return result; - } - - EvmGrantDeleteResponse._(); - - factory EvmGrantDeleteResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmGrantDeleteResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, EvmGrantDeleteResponse_Result> - _EvmGrantDeleteResponse_ResultByTag = { - 1: EvmGrantDeleteResponse_Result.ok, - 2: EvmGrantDeleteResponse_Result.error, - 0: EvmGrantDeleteResponse_Result.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmGrantDeleteResponse', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM<$1.Empty>(1, _omitFieldNames ? '' : 'ok', subBuilder: $1.Empty.create) - ..aE(2, _omitFieldNames ? '' : 'error', - enumValues: EvmError.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantDeleteResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantDeleteResponse copyWith( - void Function(EvmGrantDeleteResponse) updates) => - super.copyWith((message) => updates(message as EvmGrantDeleteResponse)) - as EvmGrantDeleteResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmGrantDeleteResponse create() => EvmGrantDeleteResponse._(); - @$core.override - EvmGrantDeleteResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmGrantDeleteResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmGrantDeleteResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - EvmGrantDeleteResponse_Result whichResult() => - _EvmGrantDeleteResponse_ResultByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearResult() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $1.Empty get ok => $_getN(0); - @$pb.TagNumber(1) - set ok($1.Empty value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasOk() => $_has(0); - @$pb.TagNumber(1) - void clearOk() => $_clearField(1); - @$pb.TagNumber(1) - $1.Empty ensureOk() => $_ensure(0); - - @$pb.TagNumber(2) - EvmError get error => $_getN(1); - @$pb.TagNumber(2) - set error(EvmError value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasError() => $_has(1); - @$pb.TagNumber(2) - void clearError() => $_clearField(2); -} - -/// Basic grant info returned in grant listings -class GrantEntry extends $pb.GeneratedMessage { - factory GrantEntry({ - $core.int? id, - $core.int? walletAccessId, - SharedSettings? shared, - SpecificGrant? specific, - }) { - final result = create(); - if (id != null) result.id = id; - if (walletAccessId != null) result.walletAccessId = walletAccessId; - if (shared != null) result.shared = shared; - if (specific != null) result.specific = specific; - return result; - } - - GrantEntry._(); - - factory GrantEntry.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory GrantEntry.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'GrantEntry', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'id') - ..aI(2, _omitFieldNames ? '' : 'walletAccessId') - ..aOM(3, _omitFieldNames ? '' : 'shared', - subBuilder: SharedSettings.create) - ..aOM(4, _omitFieldNames ? '' : 'specific', - subBuilder: SpecificGrant.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - GrantEntry clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - GrantEntry copyWith(void Function(GrantEntry) updates) => - super.copyWith((message) => updates(message as GrantEntry)) as GrantEntry; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static GrantEntry create() => GrantEntry._(); - @$core.override - GrantEntry createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static GrantEntry getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static GrantEntry? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get id => $_getIZ(0); - @$pb.TagNumber(1) - set id($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasId() => $_has(0); - @$pb.TagNumber(1) - void clearId() => $_clearField(1); - - @$pb.TagNumber(2) - $core.int get walletAccessId => $_getIZ(1); - @$pb.TagNumber(2) - set walletAccessId($core.int value) => $_setSignedInt32(1, value); - @$pb.TagNumber(2) - $core.bool hasWalletAccessId() => $_has(1); - @$pb.TagNumber(2) - void clearWalletAccessId() => $_clearField(2); - - @$pb.TagNumber(3) - SharedSettings get shared => $_getN(2); - @$pb.TagNumber(3) - set shared(SharedSettings value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasShared() => $_has(2); - @$pb.TagNumber(3) - void clearShared() => $_clearField(3); - @$pb.TagNumber(3) - SharedSettings ensureShared() => $_ensure(2); - - @$pb.TagNumber(4) - SpecificGrant get specific => $_getN(3); - @$pb.TagNumber(4) - set specific(SpecificGrant value) => $_setField(4, value); - @$pb.TagNumber(4) - $core.bool hasSpecific() => $_has(3); - @$pb.TagNumber(4) - void clearSpecific() => $_clearField(4); - @$pb.TagNumber(4) - SpecificGrant ensureSpecific() => $_ensure(3); -} - -class EvmGrantListRequest extends $pb.GeneratedMessage { - factory EvmGrantListRequest({ - $core.int? walletAccessId, - }) { - final result = create(); - if (walletAccessId != null) result.walletAccessId = walletAccessId; - return result; - } - - EvmGrantListRequest._(); - - factory EvmGrantListRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmGrantListRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmGrantListRequest', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'walletAccessId') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantListRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantListRequest copyWith(void Function(EvmGrantListRequest) updates) => - super.copyWith((message) => updates(message as EvmGrantListRequest)) - as EvmGrantListRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmGrantListRequest create() => EvmGrantListRequest._(); - @$core.override - EvmGrantListRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmGrantListRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmGrantListRequest? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get walletAccessId => $_getIZ(0); - @$pb.TagNumber(1) - set walletAccessId($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasWalletAccessId() => $_has(0); - @$pb.TagNumber(1) - void clearWalletAccessId() => $_clearField(1); -} - -enum EvmGrantListResponse_Result { grants, error, notSet } - -class EvmGrantListResponse extends $pb.GeneratedMessage { - factory EvmGrantListResponse({ - EvmGrantList? grants, - EvmError? error, - }) { - final result = create(); - if (grants != null) result.grants = grants; - if (error != null) result.error = error; - return result; - } - - EvmGrantListResponse._(); - - factory EvmGrantListResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmGrantListResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, EvmGrantListResponse_Result> - _EvmGrantListResponse_ResultByTag = { - 1: EvmGrantListResponse_Result.grants, - 2: EvmGrantListResponse_Result.error, - 0: EvmGrantListResponse_Result.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmGrantListResponse', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'grants', - subBuilder: EvmGrantList.create) - ..aE(2, _omitFieldNames ? '' : 'error', - enumValues: EvmError.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantListResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantListResponse copyWith(void Function(EvmGrantListResponse) updates) => - super.copyWith((message) => updates(message as EvmGrantListResponse)) - as EvmGrantListResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmGrantListResponse create() => EvmGrantListResponse._(); - @$core.override - EvmGrantListResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmGrantListResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmGrantListResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - EvmGrantListResponse_Result whichResult() => - _EvmGrantListResponse_ResultByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearResult() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - EvmGrantList get grants => $_getN(0); - @$pb.TagNumber(1) - set grants(EvmGrantList value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasGrants() => $_has(0); - @$pb.TagNumber(1) - void clearGrants() => $_clearField(1); - @$pb.TagNumber(1) - EvmGrantList ensureGrants() => $_ensure(0); - - @$pb.TagNumber(2) - EvmError get error => $_getN(1); - @$pb.TagNumber(2) - set error(EvmError value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasError() => $_has(1); - @$pb.TagNumber(2) - void clearError() => $_clearField(2); -} - -class EvmGrantList extends $pb.GeneratedMessage { - factory EvmGrantList({ - $core.Iterable? grants, - }) { - final result = create(); - if (grants != null) result.grants.addAll(grants); - return result; - } - - EvmGrantList._(); - - factory EvmGrantList.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmGrantList.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmGrantList', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..pPM(1, _omitFieldNames ? '' : 'grants', - subBuilder: GrantEntry.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantList clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmGrantList copyWith(void Function(EvmGrantList) updates) => - super.copyWith((message) => updates(message as EvmGrantList)) - as EvmGrantList; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmGrantList create() => EvmGrantList._(); - @$core.override - EvmGrantList createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmGrantList getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmGrantList? _defaultInstance; - - @$pb.TagNumber(1) - $pb.PbList get grants => $_getList(0); -} - -class EvmSignTransactionRequest extends $pb.GeneratedMessage { - factory EvmSignTransactionRequest({ - $core.List<$core.int>? walletAddress, - $core.List<$core.int>? rlpTransaction, - }) { - final result = create(); - if (walletAddress != null) result.walletAddress = walletAddress; - if (rlpTransaction != null) result.rlpTransaction = rlpTransaction; - return result; - } - - EvmSignTransactionRequest._(); - - factory EvmSignTransactionRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmSignTransactionRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmSignTransactionRequest', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'walletAddress', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'rlpTransaction', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmSignTransactionRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmSignTransactionRequest copyWith( - void Function(EvmSignTransactionRequest) updates) => - super.copyWith((message) => updates(message as EvmSignTransactionRequest)) - as EvmSignTransactionRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmSignTransactionRequest create() => EvmSignTransactionRequest._(); - @$core.override - EvmSignTransactionRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmSignTransactionRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmSignTransactionRequest? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get walletAddress => $_getN(0); - @$pb.TagNumber(1) - set walletAddress($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasWalletAddress() => $_has(0); - @$pb.TagNumber(1) - void clearWalletAddress() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get rlpTransaction => $_getN(1); - @$pb.TagNumber(2) - set rlpTransaction($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasRlpTransaction() => $_has(1); - @$pb.TagNumber(2) - void clearRlpTransaction() => $_clearField(2); -} - -enum EvmSignTransactionResponse_Result { signature, evalError, error, notSet } - -/// oneof because signing and evaluation happen atomically — a signing failure -/// is always either an eval error or an internal error, never a partial success -class EvmSignTransactionResponse extends $pb.GeneratedMessage { - factory EvmSignTransactionResponse({ - $core.List<$core.int>? signature, - $2.TransactionEvalError? evalError, - EvmError? error, - }) { - final result = create(); - if (signature != null) result.signature = signature; - if (evalError != null) result.evalError = evalError; - if (error != null) result.error = error; - return result; - } - - EvmSignTransactionResponse._(); - - factory EvmSignTransactionResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmSignTransactionResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, EvmSignTransactionResponse_Result> - _EvmSignTransactionResponse_ResultByTag = { - 1: EvmSignTransactionResponse_Result.signature, - 2: EvmSignTransactionResponse_Result.evalError, - 3: EvmSignTransactionResponse_Result.error, - 0: EvmSignTransactionResponse_Result.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmSignTransactionResponse', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3]) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY) - ..aOM<$2.TransactionEvalError>(2, _omitFieldNames ? '' : 'evalError', - subBuilder: $2.TransactionEvalError.create) - ..aE(3, _omitFieldNames ? '' : 'error', - enumValues: EvmError.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmSignTransactionResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmSignTransactionResponse copyWith( - void Function(EvmSignTransactionResponse) updates) => - super.copyWith( - (message) => updates(message as EvmSignTransactionResponse)) - as EvmSignTransactionResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmSignTransactionResponse create() => EvmSignTransactionResponse._(); - @$core.override - EvmSignTransactionResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmSignTransactionResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmSignTransactionResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - EvmSignTransactionResponse_Result whichResult() => - _EvmSignTransactionResponse_ResultByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - void clearResult() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $core.List<$core.int> get signature => $_getN(0); - @$pb.TagNumber(1) - set signature($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasSignature() => $_has(0); - @$pb.TagNumber(1) - void clearSignature() => $_clearField(1); - - @$pb.TagNumber(2) - $2.TransactionEvalError get evalError => $_getN(1); - @$pb.TagNumber(2) - set evalError($2.TransactionEvalError value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasEvalError() => $_has(1); - @$pb.TagNumber(2) - void clearEvalError() => $_clearField(2); - @$pb.TagNumber(2) - $2.TransactionEvalError ensureEvalError() => $_ensure(1); - - @$pb.TagNumber(3) - EvmError get error => $_getN(2); - @$pb.TagNumber(3) - set error(EvmError value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasError() => $_has(2); - @$pb.TagNumber(3) - void clearError() => $_clearField(3); -} - -class EvmAnalyzeTransactionRequest extends $pb.GeneratedMessage { - factory EvmAnalyzeTransactionRequest({ - $core.List<$core.int>? walletAddress, - $core.List<$core.int>? rlpTransaction, - }) { - final result = create(); - if (walletAddress != null) result.walletAddress = walletAddress; - if (rlpTransaction != null) result.rlpTransaction = rlpTransaction; - return result; - } - - EvmAnalyzeTransactionRequest._(); - - factory EvmAnalyzeTransactionRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmAnalyzeTransactionRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmAnalyzeTransactionRequest', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'walletAddress', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'rlpTransaction', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmAnalyzeTransactionRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmAnalyzeTransactionRequest copyWith( - void Function(EvmAnalyzeTransactionRequest) updates) => - super.copyWith( - (message) => updates(message as EvmAnalyzeTransactionRequest)) - as EvmAnalyzeTransactionRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmAnalyzeTransactionRequest create() => - EvmAnalyzeTransactionRequest._(); - @$core.override - EvmAnalyzeTransactionRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmAnalyzeTransactionRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmAnalyzeTransactionRequest? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get walletAddress => $_getN(0); - @$pb.TagNumber(1) - set walletAddress($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasWalletAddress() => $_has(0); - @$pb.TagNumber(1) - void clearWalletAddress() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get rlpTransaction => $_getN(1); - @$pb.TagNumber(2) - set rlpTransaction($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasRlpTransaction() => $_has(1); - @$pb.TagNumber(2) - void clearRlpTransaction() => $_clearField(2); -} - -enum EvmAnalyzeTransactionResponse_Result { meaning, evalError, error, notSet } - -class EvmAnalyzeTransactionResponse extends $pb.GeneratedMessage { - factory EvmAnalyzeTransactionResponse({ - $2.SpecificMeaning? meaning, - $2.TransactionEvalError? evalError, - EvmError? error, - }) { - final result = create(); - if (meaning != null) result.meaning = meaning; - if (evalError != null) result.evalError = evalError; - if (error != null) result.error = error; - return result; - } - - EvmAnalyzeTransactionResponse._(); - - factory EvmAnalyzeTransactionResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvmAnalyzeTransactionResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, EvmAnalyzeTransactionResponse_Result> - _EvmAnalyzeTransactionResponse_ResultByTag = { - 1: EvmAnalyzeTransactionResponse_Result.meaning, - 2: EvmAnalyzeTransactionResponse_Result.evalError, - 3: EvmAnalyzeTransactionResponse_Result.error, - 0: EvmAnalyzeTransactionResponse_Result.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvmAnalyzeTransactionResponse', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3]) - ..aOM<$2.SpecificMeaning>(1, _omitFieldNames ? '' : 'meaning', - subBuilder: $2.SpecificMeaning.create) - ..aOM<$2.TransactionEvalError>(2, _omitFieldNames ? '' : 'evalError', - subBuilder: $2.TransactionEvalError.create) - ..aE(3, _omitFieldNames ? '' : 'error', - enumValues: EvmError.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmAnalyzeTransactionResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvmAnalyzeTransactionResponse copyWith( - void Function(EvmAnalyzeTransactionResponse) updates) => - super.copyWith( - (message) => updates(message as EvmAnalyzeTransactionResponse)) - as EvmAnalyzeTransactionResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvmAnalyzeTransactionResponse create() => - EvmAnalyzeTransactionResponse._(); - @$core.override - EvmAnalyzeTransactionResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvmAnalyzeTransactionResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvmAnalyzeTransactionResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - EvmAnalyzeTransactionResponse_Result whichResult() => - _EvmAnalyzeTransactionResponse_ResultByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - void clearResult() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $2.SpecificMeaning get meaning => $_getN(0); - @$pb.TagNumber(1) - set meaning($2.SpecificMeaning value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasMeaning() => $_has(0); - @$pb.TagNumber(1) - void clearMeaning() => $_clearField(1); - @$pb.TagNumber(1) - $2.SpecificMeaning ensureMeaning() => $_ensure(0); - - @$pb.TagNumber(2) - $2.TransactionEvalError get evalError => $_getN(1); - @$pb.TagNumber(2) - set evalError($2.TransactionEvalError value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasEvalError() => $_has(1); - @$pb.TagNumber(2) - void clearEvalError() => $_clearField(2); - @$pb.TagNumber(2) - $2.TransactionEvalError ensureEvalError() => $_ensure(1); - - @$pb.TagNumber(3) - EvmError get error => $_getN(2); - @$pb.TagNumber(3) - set error(EvmError value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasError() => $_has(2); - @$pb.TagNumber(3) - void clearError() => $_clearField(3); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $1; +import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart' + as $0; + +import 'evm.pbenum.dart'; +import 'shared/evm.pb.dart' as $2; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +export 'evm.pbenum.dart'; + +class WalletEntry extends $pb.GeneratedMessage { + factory WalletEntry({ + $core.int? id, + $core.List<$core.int>? address, + }) { + final result = create(); + if (id != null) result.id = id; + if (address != null) result.address = address; + return result; + } + + WalletEntry._(); + + factory WalletEntry.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory WalletEntry.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'WalletEntry', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'id') + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'address', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletEntry clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletEntry copyWith(void Function(WalletEntry) updates) => + super.copyWith((message) => updates(message as WalletEntry)) + as WalletEntry; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static WalletEntry create() => WalletEntry._(); + @$core.override + WalletEntry createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static WalletEntry getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static WalletEntry? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get id => $_getIZ(0); + @$pb.TagNumber(1) + set id($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get address => $_getN(1); + @$pb.TagNumber(2) + set address($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasAddress() => $_has(1); + @$pb.TagNumber(2) + void clearAddress() => $_clearField(2); +} + +class WalletList extends $pb.GeneratedMessage { + factory WalletList({ + $core.Iterable? wallets, + }) { + final result = create(); + if (wallets != null) result.wallets.addAll(wallets); + return result; + } + + WalletList._(); + + factory WalletList.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory WalletList.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'WalletList', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..pPM(1, _omitFieldNames ? '' : 'wallets', + subBuilder: WalletEntry.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletList clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletList copyWith(void Function(WalletList) updates) => + super.copyWith((message) => updates(message as WalletList)) as WalletList; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static WalletList create() => WalletList._(); + @$core.override + WalletList createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static WalletList getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static WalletList? _defaultInstance; + + @$pb.TagNumber(1) + $pb.PbList get wallets => $_getList(0); +} + +enum WalletCreateResponse_Result { wallet, error, notSet } + +class WalletCreateResponse extends $pb.GeneratedMessage { + factory WalletCreateResponse({ + WalletEntry? wallet, + EvmError? error, + }) { + final result = create(); + if (wallet != null) result.wallet = wallet; + if (error != null) result.error = error; + return result; + } + + WalletCreateResponse._(); + + factory WalletCreateResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory WalletCreateResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, WalletCreateResponse_Result> + _WalletCreateResponse_ResultByTag = { + 1: WalletCreateResponse_Result.wallet, + 2: WalletCreateResponse_Result.error, + 0: WalletCreateResponse_Result.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'WalletCreateResponse', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'wallet', + subBuilder: WalletEntry.create) + ..aE(2, _omitFieldNames ? '' : 'error', + enumValues: EvmError.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletCreateResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletCreateResponse copyWith(void Function(WalletCreateResponse) updates) => + super.copyWith((message) => updates(message as WalletCreateResponse)) + as WalletCreateResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static WalletCreateResponse create() => WalletCreateResponse._(); + @$core.override + WalletCreateResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static WalletCreateResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static WalletCreateResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + WalletCreateResponse_Result whichResult() => + _WalletCreateResponse_ResultByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearResult() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + WalletEntry get wallet => $_getN(0); + @$pb.TagNumber(1) + set wallet(WalletEntry value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasWallet() => $_has(0); + @$pb.TagNumber(1) + void clearWallet() => $_clearField(1); + @$pb.TagNumber(1) + WalletEntry ensureWallet() => $_ensure(0); + + @$pb.TagNumber(2) + EvmError get error => $_getN(1); + @$pb.TagNumber(2) + set error(EvmError value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasError() => $_has(1); + @$pb.TagNumber(2) + void clearError() => $_clearField(2); +} + +enum WalletListResponse_Result { wallets, error, notSet } + +class WalletListResponse extends $pb.GeneratedMessage { + factory WalletListResponse({ + WalletList? wallets, + EvmError? error, + }) { + final result = create(); + if (wallets != null) result.wallets = wallets; + if (error != null) result.error = error; + return result; + } + + WalletListResponse._(); + + factory WalletListResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory WalletListResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, WalletListResponse_Result> + _WalletListResponse_ResultByTag = { + 1: WalletListResponse_Result.wallets, + 2: WalletListResponse_Result.error, + 0: WalletListResponse_Result.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'WalletListResponse', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'wallets', + subBuilder: WalletList.create) + ..aE(2, _omitFieldNames ? '' : 'error', + enumValues: EvmError.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletListResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletListResponse copyWith(void Function(WalletListResponse) updates) => + super.copyWith((message) => updates(message as WalletListResponse)) + as WalletListResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static WalletListResponse create() => WalletListResponse._(); + @$core.override + WalletListResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static WalletListResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static WalletListResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + WalletListResponse_Result whichResult() => + _WalletListResponse_ResultByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearResult() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + WalletList get wallets => $_getN(0); + @$pb.TagNumber(1) + set wallets(WalletList value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasWallets() => $_has(0); + @$pb.TagNumber(1) + void clearWallets() => $_clearField(1); + @$pb.TagNumber(1) + WalletList ensureWallets() => $_ensure(0); + + @$pb.TagNumber(2) + EvmError get error => $_getN(1); + @$pb.TagNumber(2) + set error(EvmError value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasError() => $_has(1); + @$pb.TagNumber(2) + void clearError() => $_clearField(2); +} + +class TransactionRateLimit extends $pb.GeneratedMessage { + factory TransactionRateLimit({ + $core.int? count, + $fixnum.Int64? windowSecs, + }) { + final result = create(); + if (count != null) result.count = count; + if (windowSecs != null) result.windowSecs = windowSecs; + return result; + } + + TransactionRateLimit._(); + + factory TransactionRateLimit.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory TransactionRateLimit.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'TransactionRateLimit', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'count', fieldType: $pb.PbFieldType.OU3) + ..aInt64(2, _omitFieldNames ? '' : 'windowSecs') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TransactionRateLimit clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TransactionRateLimit copyWith(void Function(TransactionRateLimit) updates) => + super.copyWith((message) => updates(message as TransactionRateLimit)) + as TransactionRateLimit; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static TransactionRateLimit create() => TransactionRateLimit._(); + @$core.override + TransactionRateLimit createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static TransactionRateLimit getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static TransactionRateLimit? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get count => $_getIZ(0); + @$pb.TagNumber(1) + set count($core.int value) => $_setUnsignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasCount() => $_has(0); + @$pb.TagNumber(1) + void clearCount() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get windowSecs => $_getI64(1); + @$pb.TagNumber(2) + set windowSecs($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasWindowSecs() => $_has(1); + @$pb.TagNumber(2) + void clearWindowSecs() => $_clearField(2); +} + +class VolumeRateLimit extends $pb.GeneratedMessage { + factory VolumeRateLimit({ + $core.List<$core.int>? maxVolume, + $fixnum.Int64? windowSecs, + }) { + final result = create(); + if (maxVolume != null) result.maxVolume = maxVolume; + if (windowSecs != null) result.windowSecs = windowSecs; + return result; + } + + VolumeRateLimit._(); + + factory VolumeRateLimit.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory VolumeRateLimit.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'VolumeRateLimit', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'maxVolume', $pb.PbFieldType.OY) + ..aInt64(2, _omitFieldNames ? '' : 'windowSecs') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + VolumeRateLimit clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + VolumeRateLimit copyWith(void Function(VolumeRateLimit) updates) => + super.copyWith((message) => updates(message as VolumeRateLimit)) + as VolumeRateLimit; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static VolumeRateLimit create() => VolumeRateLimit._(); + @$core.override + VolumeRateLimit createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static VolumeRateLimit getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static VolumeRateLimit? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get maxVolume => $_getN(0); + @$pb.TagNumber(1) + set maxVolume($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasMaxVolume() => $_has(0); + @$pb.TagNumber(1) + void clearMaxVolume() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get windowSecs => $_getI64(1); + @$pb.TagNumber(2) + set windowSecs($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasWindowSecs() => $_has(1); + @$pb.TagNumber(2) + void clearWindowSecs() => $_clearField(2); +} + +class SharedSettings extends $pb.GeneratedMessage { + factory SharedSettings({ + $core.int? walletAccessId, + $fixnum.Int64? chainId, + $0.Timestamp? validFrom, + $0.Timestamp? validUntil, + $core.List<$core.int>? maxGasFeePerGas, + $core.List<$core.int>? maxPriorityFeePerGas, + TransactionRateLimit? rateLimit, + }) { + final result = create(); + if (walletAccessId != null) result.walletAccessId = walletAccessId; + if (chainId != null) result.chainId = chainId; + if (validFrom != null) result.validFrom = validFrom; + if (validUntil != null) result.validUntil = validUntil; + if (maxGasFeePerGas != null) result.maxGasFeePerGas = maxGasFeePerGas; + if (maxPriorityFeePerGas != null) + result.maxPriorityFeePerGas = maxPriorityFeePerGas; + if (rateLimit != null) result.rateLimit = rateLimit; + return result; + } + + SharedSettings._(); + + factory SharedSettings.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory SharedSettings.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'SharedSettings', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'walletAccessId') + ..a<$fixnum.Int64>(2, _omitFieldNames ? '' : 'chainId', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..aOM<$0.Timestamp>(3, _omitFieldNames ? '' : 'validFrom', + subBuilder: $0.Timestamp.create) + ..aOM<$0.Timestamp>(4, _omitFieldNames ? '' : 'validUntil', + subBuilder: $0.Timestamp.create) + ..a<$core.List<$core.int>>( + 5, _omitFieldNames ? '' : 'maxGasFeePerGas', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 6, _omitFieldNames ? '' : 'maxPriorityFeePerGas', $pb.PbFieldType.OY) + ..aOM(7, _omitFieldNames ? '' : 'rateLimit', + subBuilder: TransactionRateLimit.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + SharedSettings clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + SharedSettings copyWith(void Function(SharedSettings) updates) => + super.copyWith((message) => updates(message as SharedSettings)) + as SharedSettings; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static SharedSettings create() => SharedSettings._(); + @$core.override + SharedSettings createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static SharedSettings getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static SharedSettings? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get walletAccessId => $_getIZ(0); + @$pb.TagNumber(1) + set walletAccessId($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasWalletAccessId() => $_has(0); + @$pb.TagNumber(1) + void clearWalletAccessId() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get chainId => $_getI64(1); + @$pb.TagNumber(2) + set chainId($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasChainId() => $_has(1); + @$pb.TagNumber(2) + void clearChainId() => $_clearField(2); + + @$pb.TagNumber(3) + $0.Timestamp get validFrom => $_getN(2); + @$pb.TagNumber(3) + set validFrom($0.Timestamp value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasValidFrom() => $_has(2); + @$pb.TagNumber(3) + void clearValidFrom() => $_clearField(3); + @$pb.TagNumber(3) + $0.Timestamp ensureValidFrom() => $_ensure(2); + + @$pb.TagNumber(4) + $0.Timestamp get validUntil => $_getN(3); + @$pb.TagNumber(4) + set validUntil($0.Timestamp value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasValidUntil() => $_has(3); + @$pb.TagNumber(4) + void clearValidUntil() => $_clearField(4); + @$pb.TagNumber(4) + $0.Timestamp ensureValidUntil() => $_ensure(3); + + @$pb.TagNumber(5) + $core.List<$core.int> get maxGasFeePerGas => $_getN(4); + @$pb.TagNumber(5) + set maxGasFeePerGas($core.List<$core.int> value) => $_setBytes(4, value); + @$pb.TagNumber(5) + $core.bool hasMaxGasFeePerGas() => $_has(4); + @$pb.TagNumber(5) + void clearMaxGasFeePerGas() => $_clearField(5); + + @$pb.TagNumber(6) + $core.List<$core.int> get maxPriorityFeePerGas => $_getN(5); + @$pb.TagNumber(6) + set maxPriorityFeePerGas($core.List<$core.int> value) => $_setBytes(5, value); + @$pb.TagNumber(6) + $core.bool hasMaxPriorityFeePerGas() => $_has(5); + @$pb.TagNumber(6) + void clearMaxPriorityFeePerGas() => $_clearField(6); + + @$pb.TagNumber(7) + TransactionRateLimit get rateLimit => $_getN(6); + @$pb.TagNumber(7) + set rateLimit(TransactionRateLimit value) => $_setField(7, value); + @$pb.TagNumber(7) + $core.bool hasRateLimit() => $_has(6); + @$pb.TagNumber(7) + void clearRateLimit() => $_clearField(7); + @$pb.TagNumber(7) + TransactionRateLimit ensureRateLimit() => $_ensure(6); +} + +class EtherTransferSettings extends $pb.GeneratedMessage { + factory EtherTransferSettings({ + $core.Iterable<$core.List<$core.int>>? targets, + VolumeRateLimit? limit, + }) { + final result = create(); + if (targets != null) result.targets.addAll(targets); + if (limit != null) result.limit = limit; + return result; + } + + EtherTransferSettings._(); + + factory EtherTransferSettings.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EtherTransferSettings.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EtherTransferSettings', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..p<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'targets', $pb.PbFieldType.PY) + ..aOM(2, _omitFieldNames ? '' : 'limit', + subBuilder: VolumeRateLimit.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EtherTransferSettings clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EtherTransferSettings copyWith( + void Function(EtherTransferSettings) updates) => + super.copyWith((message) => updates(message as EtherTransferSettings)) + as EtherTransferSettings; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EtherTransferSettings create() => EtherTransferSettings._(); + @$core.override + EtherTransferSettings createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EtherTransferSettings getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EtherTransferSettings? _defaultInstance; + + @$pb.TagNumber(1) + $pb.PbList<$core.List<$core.int>> get targets => $_getList(0); + + @$pb.TagNumber(2) + VolumeRateLimit get limit => $_getN(1); + @$pb.TagNumber(2) + set limit(VolumeRateLimit value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasLimit() => $_has(1); + @$pb.TagNumber(2) + void clearLimit() => $_clearField(2); + @$pb.TagNumber(2) + VolumeRateLimit ensureLimit() => $_ensure(1); +} + +class TokenTransferSettings extends $pb.GeneratedMessage { + factory TokenTransferSettings({ + $core.List<$core.int>? tokenContract, + $core.List<$core.int>? target, + $core.Iterable? volumeLimits, + }) { + final result = create(); + if (tokenContract != null) result.tokenContract = tokenContract; + if (target != null) result.target = target; + if (volumeLimits != null) result.volumeLimits.addAll(volumeLimits); + return result; + } + + TokenTransferSettings._(); + + factory TokenTransferSettings.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory TokenTransferSettings.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'TokenTransferSettings', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'tokenContract', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'target', $pb.PbFieldType.OY) + ..pPM(3, _omitFieldNames ? '' : 'volumeLimits', + subBuilder: VolumeRateLimit.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TokenTransferSettings clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TokenTransferSettings copyWith( + void Function(TokenTransferSettings) updates) => + super.copyWith((message) => updates(message as TokenTransferSettings)) + as TokenTransferSettings; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static TokenTransferSettings create() => TokenTransferSettings._(); + @$core.override + TokenTransferSettings createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static TokenTransferSettings getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static TokenTransferSettings? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get tokenContract => $_getN(0); + @$pb.TagNumber(1) + set tokenContract($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasTokenContract() => $_has(0); + @$pb.TagNumber(1) + void clearTokenContract() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get target => $_getN(1); + @$pb.TagNumber(2) + set target($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasTarget() => $_has(1); + @$pb.TagNumber(2) + void clearTarget() => $_clearField(2); + + @$pb.TagNumber(3) + $pb.PbList get volumeLimits => $_getList(2); +} + +enum SpecificGrant_Grant { etherTransfer, tokenTransfer, notSet } + +class SpecificGrant extends $pb.GeneratedMessage { + factory SpecificGrant({ + EtherTransferSettings? etherTransfer, + TokenTransferSettings? tokenTransfer, + }) { + final result = create(); + if (etherTransfer != null) result.etherTransfer = etherTransfer; + if (tokenTransfer != null) result.tokenTransfer = tokenTransfer; + return result; + } + + SpecificGrant._(); + + factory SpecificGrant.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory SpecificGrant.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, SpecificGrant_Grant> + _SpecificGrant_GrantByTag = { + 1: SpecificGrant_Grant.etherTransfer, + 2: SpecificGrant_Grant.tokenTransfer, + 0: SpecificGrant_Grant.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'SpecificGrant', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'etherTransfer', + subBuilder: EtherTransferSettings.create) + ..aOM(2, _omitFieldNames ? '' : 'tokenTransfer', + subBuilder: TokenTransferSettings.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + SpecificGrant clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + SpecificGrant copyWith(void Function(SpecificGrant) updates) => + super.copyWith((message) => updates(message as SpecificGrant)) + as SpecificGrant; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static SpecificGrant create() => SpecificGrant._(); + @$core.override + SpecificGrant createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static SpecificGrant getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static SpecificGrant? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + SpecificGrant_Grant whichGrant() => + _SpecificGrant_GrantByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearGrant() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + EtherTransferSettings get etherTransfer => $_getN(0); + @$pb.TagNumber(1) + set etherTransfer(EtherTransferSettings value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasEtherTransfer() => $_has(0); + @$pb.TagNumber(1) + void clearEtherTransfer() => $_clearField(1); + @$pb.TagNumber(1) + EtherTransferSettings ensureEtherTransfer() => $_ensure(0); + + @$pb.TagNumber(2) + TokenTransferSettings get tokenTransfer => $_getN(1); + @$pb.TagNumber(2) + set tokenTransfer(TokenTransferSettings value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasTokenTransfer() => $_has(1); + @$pb.TagNumber(2) + void clearTokenTransfer() => $_clearField(2); + @$pb.TagNumber(2) + TokenTransferSettings ensureTokenTransfer() => $_ensure(1); +} + +/// --- UserAgent grant management --- +class EvmGrantCreateRequest extends $pb.GeneratedMessage { + factory EvmGrantCreateRequest({ + SharedSettings? shared, + SpecificGrant? specific, + }) { + final result = create(); + if (shared != null) result.shared = shared; + if (specific != null) result.specific = specific; + return result; + } + + EvmGrantCreateRequest._(); + + factory EvmGrantCreateRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmGrantCreateRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmGrantCreateRequest', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..aOM(1, _omitFieldNames ? '' : 'shared', + subBuilder: SharedSettings.create) + ..aOM(2, _omitFieldNames ? '' : 'specific', + subBuilder: SpecificGrant.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantCreateRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantCreateRequest copyWith( + void Function(EvmGrantCreateRequest) updates) => + super.copyWith((message) => updates(message as EvmGrantCreateRequest)) + as EvmGrantCreateRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmGrantCreateRequest create() => EvmGrantCreateRequest._(); + @$core.override + EvmGrantCreateRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmGrantCreateRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmGrantCreateRequest? _defaultInstance; + + @$pb.TagNumber(1) + SharedSettings get shared => $_getN(0); + @$pb.TagNumber(1) + set shared(SharedSettings value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasShared() => $_has(0); + @$pb.TagNumber(1) + void clearShared() => $_clearField(1); + @$pb.TagNumber(1) + SharedSettings ensureShared() => $_ensure(0); + + @$pb.TagNumber(2) + SpecificGrant get specific => $_getN(1); + @$pb.TagNumber(2) + set specific(SpecificGrant value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasSpecific() => $_has(1); + @$pb.TagNumber(2) + void clearSpecific() => $_clearField(2); + @$pb.TagNumber(2) + SpecificGrant ensureSpecific() => $_ensure(1); +} + +enum EvmGrantCreateResponse_Result { grantId, error, notSet } + +class EvmGrantCreateResponse extends $pb.GeneratedMessage { + factory EvmGrantCreateResponse({ + $core.int? grantId, + EvmError? error, + }) { + final result = create(); + if (grantId != null) result.grantId = grantId; + if (error != null) result.error = error; + return result; + } + + EvmGrantCreateResponse._(); + + factory EvmGrantCreateResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmGrantCreateResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, EvmGrantCreateResponse_Result> + _EvmGrantCreateResponse_ResultByTag = { + 1: EvmGrantCreateResponse_Result.grantId, + 2: EvmGrantCreateResponse_Result.error, + 0: EvmGrantCreateResponse_Result.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmGrantCreateResponse', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aI(1, _omitFieldNames ? '' : 'grantId') + ..aE(2, _omitFieldNames ? '' : 'error', + enumValues: EvmError.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantCreateResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantCreateResponse copyWith( + void Function(EvmGrantCreateResponse) updates) => + super.copyWith((message) => updates(message as EvmGrantCreateResponse)) + as EvmGrantCreateResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmGrantCreateResponse create() => EvmGrantCreateResponse._(); + @$core.override + EvmGrantCreateResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmGrantCreateResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmGrantCreateResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + EvmGrantCreateResponse_Result whichResult() => + _EvmGrantCreateResponse_ResultByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearResult() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $core.int get grantId => $_getIZ(0); + @$pb.TagNumber(1) + set grantId($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasGrantId() => $_has(0); + @$pb.TagNumber(1) + void clearGrantId() => $_clearField(1); + + @$pb.TagNumber(2) + EvmError get error => $_getN(1); + @$pb.TagNumber(2) + set error(EvmError value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasError() => $_has(1); + @$pb.TagNumber(2) + void clearError() => $_clearField(2); +} + +class EvmGrantDeleteRequest extends $pb.GeneratedMessage { + factory EvmGrantDeleteRequest({ + $core.int? grantId, + }) { + final result = create(); + if (grantId != null) result.grantId = grantId; + return result; + } + + EvmGrantDeleteRequest._(); + + factory EvmGrantDeleteRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmGrantDeleteRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmGrantDeleteRequest', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'grantId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantDeleteRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantDeleteRequest copyWith( + void Function(EvmGrantDeleteRequest) updates) => + super.copyWith((message) => updates(message as EvmGrantDeleteRequest)) + as EvmGrantDeleteRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmGrantDeleteRequest create() => EvmGrantDeleteRequest._(); + @$core.override + EvmGrantDeleteRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmGrantDeleteRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmGrantDeleteRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get grantId => $_getIZ(0); + @$pb.TagNumber(1) + set grantId($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasGrantId() => $_has(0); + @$pb.TagNumber(1) + void clearGrantId() => $_clearField(1); +} + +enum EvmGrantDeleteResponse_Result { ok, error, notSet } + +class EvmGrantDeleteResponse extends $pb.GeneratedMessage { + factory EvmGrantDeleteResponse({ + $1.Empty? ok, + EvmError? error, + }) { + final result = create(); + if (ok != null) result.ok = ok; + if (error != null) result.error = error; + return result; + } + + EvmGrantDeleteResponse._(); + + factory EvmGrantDeleteResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmGrantDeleteResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, EvmGrantDeleteResponse_Result> + _EvmGrantDeleteResponse_ResultByTag = { + 1: EvmGrantDeleteResponse_Result.ok, + 2: EvmGrantDeleteResponse_Result.error, + 0: EvmGrantDeleteResponse_Result.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmGrantDeleteResponse', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM<$1.Empty>(1, _omitFieldNames ? '' : 'ok', subBuilder: $1.Empty.create) + ..aE(2, _omitFieldNames ? '' : 'error', + enumValues: EvmError.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantDeleteResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantDeleteResponse copyWith( + void Function(EvmGrantDeleteResponse) updates) => + super.copyWith((message) => updates(message as EvmGrantDeleteResponse)) + as EvmGrantDeleteResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmGrantDeleteResponse create() => EvmGrantDeleteResponse._(); + @$core.override + EvmGrantDeleteResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmGrantDeleteResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmGrantDeleteResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + EvmGrantDeleteResponse_Result whichResult() => + _EvmGrantDeleteResponse_ResultByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearResult() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $1.Empty get ok => $_getN(0); + @$pb.TagNumber(1) + set ok($1.Empty value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasOk() => $_has(0); + @$pb.TagNumber(1) + void clearOk() => $_clearField(1); + @$pb.TagNumber(1) + $1.Empty ensureOk() => $_ensure(0); + + @$pb.TagNumber(2) + EvmError get error => $_getN(1); + @$pb.TagNumber(2) + set error(EvmError value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasError() => $_has(1); + @$pb.TagNumber(2) + void clearError() => $_clearField(2); +} + +/// Basic grant info returned in grant listings +class GrantEntry extends $pb.GeneratedMessage { + factory GrantEntry({ + $core.int? id, + $core.int? walletAccessId, + SharedSettings? shared, + SpecificGrant? specific, + }) { + final result = create(); + if (id != null) result.id = id; + if (walletAccessId != null) result.walletAccessId = walletAccessId; + if (shared != null) result.shared = shared; + if (specific != null) result.specific = specific; + return result; + } + + GrantEntry._(); + + factory GrantEntry.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory GrantEntry.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'GrantEntry', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'id') + ..aI(2, _omitFieldNames ? '' : 'walletAccessId') + ..aOM(3, _omitFieldNames ? '' : 'shared', + subBuilder: SharedSettings.create) + ..aOM(4, _omitFieldNames ? '' : 'specific', + subBuilder: SpecificGrant.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + GrantEntry clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + GrantEntry copyWith(void Function(GrantEntry) updates) => + super.copyWith((message) => updates(message as GrantEntry)) as GrantEntry; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static GrantEntry create() => GrantEntry._(); + @$core.override + GrantEntry createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static GrantEntry getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static GrantEntry? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get id => $_getIZ(0); + @$pb.TagNumber(1) + set id($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => $_clearField(1); + + @$pb.TagNumber(2) + $core.int get walletAccessId => $_getIZ(1); + @$pb.TagNumber(2) + set walletAccessId($core.int value) => $_setSignedInt32(1, value); + @$pb.TagNumber(2) + $core.bool hasWalletAccessId() => $_has(1); + @$pb.TagNumber(2) + void clearWalletAccessId() => $_clearField(2); + + @$pb.TagNumber(3) + SharedSettings get shared => $_getN(2); + @$pb.TagNumber(3) + set shared(SharedSettings value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasShared() => $_has(2); + @$pb.TagNumber(3) + void clearShared() => $_clearField(3); + @$pb.TagNumber(3) + SharedSettings ensureShared() => $_ensure(2); + + @$pb.TagNumber(4) + SpecificGrant get specific => $_getN(3); + @$pb.TagNumber(4) + set specific(SpecificGrant value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasSpecific() => $_has(3); + @$pb.TagNumber(4) + void clearSpecific() => $_clearField(4); + @$pb.TagNumber(4) + SpecificGrant ensureSpecific() => $_ensure(3); +} + +class EvmGrantListRequest extends $pb.GeneratedMessage { + factory EvmGrantListRequest({ + $core.int? walletAccessId, + }) { + final result = create(); + if (walletAccessId != null) result.walletAccessId = walletAccessId; + return result; + } + + EvmGrantListRequest._(); + + factory EvmGrantListRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmGrantListRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmGrantListRequest', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'walletAccessId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantListRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantListRequest copyWith(void Function(EvmGrantListRequest) updates) => + super.copyWith((message) => updates(message as EvmGrantListRequest)) + as EvmGrantListRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmGrantListRequest create() => EvmGrantListRequest._(); + @$core.override + EvmGrantListRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmGrantListRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmGrantListRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get walletAccessId => $_getIZ(0); + @$pb.TagNumber(1) + set walletAccessId($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasWalletAccessId() => $_has(0); + @$pb.TagNumber(1) + void clearWalletAccessId() => $_clearField(1); +} + +enum EvmGrantListResponse_Result { grants, error, notSet } + +class EvmGrantListResponse extends $pb.GeneratedMessage { + factory EvmGrantListResponse({ + EvmGrantList? grants, + EvmError? error, + }) { + final result = create(); + if (grants != null) result.grants = grants; + if (error != null) result.error = error; + return result; + } + + EvmGrantListResponse._(); + + factory EvmGrantListResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmGrantListResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, EvmGrantListResponse_Result> + _EvmGrantListResponse_ResultByTag = { + 1: EvmGrantListResponse_Result.grants, + 2: EvmGrantListResponse_Result.error, + 0: EvmGrantListResponse_Result.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmGrantListResponse', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'grants', + subBuilder: EvmGrantList.create) + ..aE(2, _omitFieldNames ? '' : 'error', + enumValues: EvmError.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantListResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantListResponse copyWith(void Function(EvmGrantListResponse) updates) => + super.copyWith((message) => updates(message as EvmGrantListResponse)) + as EvmGrantListResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmGrantListResponse create() => EvmGrantListResponse._(); + @$core.override + EvmGrantListResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmGrantListResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmGrantListResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + EvmGrantListResponse_Result whichResult() => + _EvmGrantListResponse_ResultByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearResult() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + EvmGrantList get grants => $_getN(0); + @$pb.TagNumber(1) + set grants(EvmGrantList value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasGrants() => $_has(0); + @$pb.TagNumber(1) + void clearGrants() => $_clearField(1); + @$pb.TagNumber(1) + EvmGrantList ensureGrants() => $_ensure(0); + + @$pb.TagNumber(2) + EvmError get error => $_getN(1); + @$pb.TagNumber(2) + set error(EvmError value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasError() => $_has(1); + @$pb.TagNumber(2) + void clearError() => $_clearField(2); +} + +class EvmGrantList extends $pb.GeneratedMessage { + factory EvmGrantList({ + $core.Iterable? grants, + }) { + final result = create(); + if (grants != null) result.grants.addAll(grants); + return result; + } + + EvmGrantList._(); + + factory EvmGrantList.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmGrantList.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmGrantList', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..pPM(1, _omitFieldNames ? '' : 'grants', + subBuilder: GrantEntry.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantList clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmGrantList copyWith(void Function(EvmGrantList) updates) => + super.copyWith((message) => updates(message as EvmGrantList)) + as EvmGrantList; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmGrantList create() => EvmGrantList._(); + @$core.override + EvmGrantList createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmGrantList getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmGrantList? _defaultInstance; + + @$pb.TagNumber(1) + $pb.PbList get grants => $_getList(0); +} + +class EvmSignTransactionRequest extends $pb.GeneratedMessage { + factory EvmSignTransactionRequest({ + $core.List<$core.int>? walletAddress, + $core.List<$core.int>? rlpTransaction, + }) { + final result = create(); + if (walletAddress != null) result.walletAddress = walletAddress; + if (rlpTransaction != null) result.rlpTransaction = rlpTransaction; + return result; + } + + EvmSignTransactionRequest._(); + + factory EvmSignTransactionRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmSignTransactionRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmSignTransactionRequest', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'walletAddress', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'rlpTransaction', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmSignTransactionRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmSignTransactionRequest copyWith( + void Function(EvmSignTransactionRequest) updates) => + super.copyWith((message) => updates(message as EvmSignTransactionRequest)) + as EvmSignTransactionRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmSignTransactionRequest create() => EvmSignTransactionRequest._(); + @$core.override + EvmSignTransactionRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmSignTransactionRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmSignTransactionRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get walletAddress => $_getN(0); + @$pb.TagNumber(1) + set walletAddress($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasWalletAddress() => $_has(0); + @$pb.TagNumber(1) + void clearWalletAddress() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get rlpTransaction => $_getN(1); + @$pb.TagNumber(2) + set rlpTransaction($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasRlpTransaction() => $_has(1); + @$pb.TagNumber(2) + void clearRlpTransaction() => $_clearField(2); +} + +enum EvmSignTransactionResponse_Result { signature, evalError, error, notSet } + +/// oneof because signing and evaluation happen atomically — a signing failure +/// is always either an eval error or an internal error, never a partial success +class EvmSignTransactionResponse extends $pb.GeneratedMessage { + factory EvmSignTransactionResponse({ + $core.List<$core.int>? signature, + $2.TransactionEvalError? evalError, + EvmError? error, + }) { + final result = create(); + if (signature != null) result.signature = signature; + if (evalError != null) result.evalError = evalError; + if (error != null) result.error = error; + return result; + } + + EvmSignTransactionResponse._(); + + factory EvmSignTransactionResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmSignTransactionResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, EvmSignTransactionResponse_Result> + _EvmSignTransactionResponse_ResultByTag = { + 1: EvmSignTransactionResponse_Result.signature, + 2: EvmSignTransactionResponse_Result.evalError, + 3: EvmSignTransactionResponse_Result.error, + 0: EvmSignTransactionResponse_Result.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmSignTransactionResponse', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3]) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY) + ..aOM<$2.TransactionEvalError>(2, _omitFieldNames ? '' : 'evalError', + subBuilder: $2.TransactionEvalError.create) + ..aE(3, _omitFieldNames ? '' : 'error', + enumValues: EvmError.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmSignTransactionResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmSignTransactionResponse copyWith( + void Function(EvmSignTransactionResponse) updates) => + super.copyWith( + (message) => updates(message as EvmSignTransactionResponse)) + as EvmSignTransactionResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmSignTransactionResponse create() => EvmSignTransactionResponse._(); + @$core.override + EvmSignTransactionResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmSignTransactionResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmSignTransactionResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + EvmSignTransactionResponse_Result whichResult() => + _EvmSignTransactionResponse_ResultByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + void clearResult() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $core.List<$core.int> get signature => $_getN(0); + @$pb.TagNumber(1) + set signature($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasSignature() => $_has(0); + @$pb.TagNumber(1) + void clearSignature() => $_clearField(1); + + @$pb.TagNumber(2) + $2.TransactionEvalError get evalError => $_getN(1); + @$pb.TagNumber(2) + set evalError($2.TransactionEvalError value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasEvalError() => $_has(1); + @$pb.TagNumber(2) + void clearEvalError() => $_clearField(2); + @$pb.TagNumber(2) + $2.TransactionEvalError ensureEvalError() => $_ensure(1); + + @$pb.TagNumber(3) + EvmError get error => $_getN(2); + @$pb.TagNumber(3) + set error(EvmError value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasError() => $_has(2); + @$pb.TagNumber(3) + void clearError() => $_clearField(3); +} + +class EvmAnalyzeTransactionRequest extends $pb.GeneratedMessage { + factory EvmAnalyzeTransactionRequest({ + $core.List<$core.int>? walletAddress, + $core.List<$core.int>? rlpTransaction, + }) { + final result = create(); + if (walletAddress != null) result.walletAddress = walletAddress; + if (rlpTransaction != null) result.rlpTransaction = rlpTransaction; + return result; + } + + EvmAnalyzeTransactionRequest._(); + + factory EvmAnalyzeTransactionRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmAnalyzeTransactionRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmAnalyzeTransactionRequest', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'walletAddress', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'rlpTransaction', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmAnalyzeTransactionRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmAnalyzeTransactionRequest copyWith( + void Function(EvmAnalyzeTransactionRequest) updates) => + super.copyWith( + (message) => updates(message as EvmAnalyzeTransactionRequest)) + as EvmAnalyzeTransactionRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmAnalyzeTransactionRequest create() => + EvmAnalyzeTransactionRequest._(); + @$core.override + EvmAnalyzeTransactionRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmAnalyzeTransactionRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmAnalyzeTransactionRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get walletAddress => $_getN(0); + @$pb.TagNumber(1) + set walletAddress($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasWalletAddress() => $_has(0); + @$pb.TagNumber(1) + void clearWalletAddress() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get rlpTransaction => $_getN(1); + @$pb.TagNumber(2) + set rlpTransaction($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasRlpTransaction() => $_has(1); + @$pb.TagNumber(2) + void clearRlpTransaction() => $_clearField(2); +} + +enum EvmAnalyzeTransactionResponse_Result { meaning, evalError, error, notSet } + +class EvmAnalyzeTransactionResponse extends $pb.GeneratedMessage { + factory EvmAnalyzeTransactionResponse({ + $2.SpecificMeaning? meaning, + $2.TransactionEvalError? evalError, + EvmError? error, + }) { + final result = create(); + if (meaning != null) result.meaning = meaning; + if (evalError != null) result.evalError = evalError; + if (error != null) result.error = error; + return result; + } + + EvmAnalyzeTransactionResponse._(); + + factory EvmAnalyzeTransactionResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvmAnalyzeTransactionResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, EvmAnalyzeTransactionResponse_Result> + _EvmAnalyzeTransactionResponse_ResultByTag = { + 1: EvmAnalyzeTransactionResponse_Result.meaning, + 2: EvmAnalyzeTransactionResponse_Result.evalError, + 3: EvmAnalyzeTransactionResponse_Result.error, + 0: EvmAnalyzeTransactionResponse_Result.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvmAnalyzeTransactionResponse', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3]) + ..aOM<$2.SpecificMeaning>(1, _omitFieldNames ? '' : 'meaning', + subBuilder: $2.SpecificMeaning.create) + ..aOM<$2.TransactionEvalError>(2, _omitFieldNames ? '' : 'evalError', + subBuilder: $2.TransactionEvalError.create) + ..aE(3, _omitFieldNames ? '' : 'error', + enumValues: EvmError.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmAnalyzeTransactionResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvmAnalyzeTransactionResponse copyWith( + void Function(EvmAnalyzeTransactionResponse) updates) => + super.copyWith( + (message) => updates(message as EvmAnalyzeTransactionResponse)) + as EvmAnalyzeTransactionResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvmAnalyzeTransactionResponse create() => + EvmAnalyzeTransactionResponse._(); + @$core.override + EvmAnalyzeTransactionResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvmAnalyzeTransactionResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvmAnalyzeTransactionResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + EvmAnalyzeTransactionResponse_Result whichResult() => + _EvmAnalyzeTransactionResponse_ResultByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + void clearResult() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $2.SpecificMeaning get meaning => $_getN(0); + @$pb.TagNumber(1) + set meaning($2.SpecificMeaning value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasMeaning() => $_has(0); + @$pb.TagNumber(1) + void clearMeaning() => $_clearField(1); + @$pb.TagNumber(1) + $2.SpecificMeaning ensureMeaning() => $_ensure(0); + + @$pb.TagNumber(2) + $2.TransactionEvalError get evalError => $_getN(1); + @$pb.TagNumber(2) + set evalError($2.TransactionEvalError value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasEvalError() => $_has(1); + @$pb.TagNumber(2) + void clearEvalError() => $_clearField(2); + @$pb.TagNumber(2) + $2.TransactionEvalError ensureEvalError() => $_ensure(1); + + @$pb.TagNumber(3) + EvmError get error => $_getN(2); + @$pb.TagNumber(3) + set error(EvmError value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasError() => $_has(2); + @$pb.TagNumber(3) + void clearError() => $_clearField(3); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/evm.pbenum.dart b/useragent/lib/proto/evm.pbenum.dart index 3146b4d..079fe9a 100644 --- a/useragent/lib/proto/evm.pbenum.dart +++ b/useragent/lib/proto/evm.pbenum.dart @@ -1,40 +1,40 @@ -// This is a generated file - do not edit. -// -// Generated from evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -class EvmError extends $pb.ProtobufEnum { - static const EvmError EVM_ERROR_UNSPECIFIED = - EvmError._(0, _omitEnumNames ? '' : 'EVM_ERROR_UNSPECIFIED'); - static const EvmError EVM_ERROR_VAULT_SEALED = - EvmError._(1, _omitEnumNames ? '' : 'EVM_ERROR_VAULT_SEALED'); - static const EvmError EVM_ERROR_INTERNAL = - EvmError._(2, _omitEnumNames ? '' : 'EVM_ERROR_INTERNAL'); - - static const $core.List values = [ - EVM_ERROR_UNSPECIFIED, - EVM_ERROR_VAULT_SEALED, - EVM_ERROR_INTERNAL, - ]; - - static final $core.List _byValue = - $pb.ProtobufEnum.$_initByValueList(values, 2); - static EvmError? valueOf($core.int value) => - value < 0 || value >= _byValue.length ? null : _byValue[value]; - - const EvmError._(super.value, super.name); -} - -const $core.bool _omitEnumNames = - $core.bool.fromEnvironment('protobuf.omit_enum_names'); +// This is a generated file - do not edit. +// +// Generated from evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class EvmError extends $pb.ProtobufEnum { + static const EvmError EVM_ERROR_UNSPECIFIED = + EvmError._(0, _omitEnumNames ? '' : 'EVM_ERROR_UNSPECIFIED'); + static const EvmError EVM_ERROR_VAULT_SEALED = + EvmError._(1, _omitEnumNames ? '' : 'EVM_ERROR_VAULT_SEALED'); + static const EvmError EVM_ERROR_INTERNAL = + EvmError._(2, _omitEnumNames ? '' : 'EVM_ERROR_INTERNAL'); + + static const $core.List values = [ + EVM_ERROR_UNSPECIFIED, + EVM_ERROR_VAULT_SEALED, + EVM_ERROR_INTERNAL, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 2); + static EvmError? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const EvmError._(super.value, super.name); +} + +const $core.bool _omitEnumNames = + $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/useragent/lib/proto/evm.pbjson.dart b/useragent/lib/proto/evm.pbjson.dart index 9fa347c..c1d2637 100644 --- a/useragent/lib/proto/evm.pbjson.dart +++ b/useragent/lib/proto/evm.pbjson.dart @@ -1,650 +1,650 @@ -// This is a generated file - do not edit. -// -// Generated from evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use evmErrorDescriptor instead') -const EvmError$json = { - '1': 'EvmError', - '2': [ - {'1': 'EVM_ERROR_UNSPECIFIED', '2': 0}, - {'1': 'EVM_ERROR_VAULT_SEALED', '2': 1}, - {'1': 'EVM_ERROR_INTERNAL', '2': 2}, - ], -}; - -/// Descriptor for `EvmError`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List evmErrorDescriptor = $convert.base64Decode( - 'CghFdm1FcnJvchIZChVFVk1fRVJST1JfVU5TUEVDSUZJRUQQABIaChZFVk1fRVJST1JfVkFVTF' - 'RfU0VBTEVEEAESFgoSRVZNX0VSUk9SX0lOVEVSTkFMEAI='); - -@$core.Deprecated('Use walletEntryDescriptor instead') -const WalletEntry$json = { - '1': 'WalletEntry', - '2': [ - {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, - {'1': 'address', '3': 2, '4': 1, '5': 12, '10': 'address'}, - ], -}; - -/// Descriptor for `WalletEntry`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List walletEntryDescriptor = $convert.base64Decode( - 'CgtXYWxsZXRFbnRyeRIOCgJpZBgBIAEoBVICaWQSGAoHYWRkcmVzcxgCIAEoDFIHYWRkcmVzcw' - '=='); - -@$core.Deprecated('Use walletListDescriptor instead') -const WalletList$json = { - '1': 'WalletList', - '2': [ - { - '1': 'wallets', - '3': 1, - '4': 3, - '5': 11, - '6': '.arbiter.evm.WalletEntry', - '10': 'wallets' - }, - ], -}; - -/// Descriptor for `WalletList`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List walletListDescriptor = $convert.base64Decode( - 'CgpXYWxsZXRMaXN0EjIKB3dhbGxldHMYASADKAsyGC5hcmJpdGVyLmV2bS5XYWxsZXRFbnRyeV' - 'IHd2FsbGV0cw=='); - -@$core.Deprecated('Use walletCreateResponseDescriptor instead') -const WalletCreateResponse$json = { - '1': 'WalletCreateResponse', - '2': [ - { - '1': 'wallet', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.evm.WalletEntry', - '9': 0, - '10': 'wallet' - }, - { - '1': 'error', - '3': 2, - '4': 1, - '5': 14, - '6': '.arbiter.evm.EvmError', - '9': 0, - '10': 'error' - }, - ], - '8': [ - {'1': 'result'}, - ], -}; - -/// Descriptor for `WalletCreateResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List walletCreateResponseDescriptor = $convert.base64Decode( - 'ChRXYWxsZXRDcmVhdGVSZXNwb25zZRIyCgZ3YWxsZXQYASABKAsyGC5hcmJpdGVyLmV2bS5XYW' - 'xsZXRFbnRyeUgAUgZ3YWxsZXQSLQoFZXJyb3IYAiABKA4yFS5hcmJpdGVyLmV2bS5Fdm1FcnJv' - 'ckgAUgVlcnJvckIICgZyZXN1bHQ='); - -@$core.Deprecated('Use walletListResponseDescriptor instead') -const WalletListResponse$json = { - '1': 'WalletListResponse', - '2': [ - { - '1': 'wallets', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.evm.WalletList', - '9': 0, - '10': 'wallets' - }, - { - '1': 'error', - '3': 2, - '4': 1, - '5': 14, - '6': '.arbiter.evm.EvmError', - '9': 0, - '10': 'error' - }, - ], - '8': [ - {'1': 'result'}, - ], -}; - -/// Descriptor for `WalletListResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List walletListResponseDescriptor = $convert.base64Decode( - 'ChJXYWxsZXRMaXN0UmVzcG9uc2USMwoHd2FsbGV0cxgBIAEoCzIXLmFyYml0ZXIuZXZtLldhbG' - 'xldExpc3RIAFIHd2FsbGV0cxItCgVlcnJvchgCIAEoDjIVLmFyYml0ZXIuZXZtLkV2bUVycm9y' - 'SABSBWVycm9yQggKBnJlc3VsdA=='); - -@$core.Deprecated('Use transactionRateLimitDescriptor instead') -const TransactionRateLimit$json = { - '1': 'TransactionRateLimit', - '2': [ - {'1': 'count', '3': 1, '4': 1, '5': 13, '10': 'count'}, - {'1': 'window_secs', '3': 2, '4': 1, '5': 3, '10': 'windowSecs'}, - ], -}; - -/// Descriptor for `TransactionRateLimit`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List transactionRateLimitDescriptor = $convert.base64Decode( - 'ChRUcmFuc2FjdGlvblJhdGVMaW1pdBIUCgVjb3VudBgBIAEoDVIFY291bnQSHwoLd2luZG93X3' - 'NlY3MYAiABKANSCndpbmRvd1NlY3M='); - -@$core.Deprecated('Use volumeRateLimitDescriptor instead') -const VolumeRateLimit$json = { - '1': 'VolumeRateLimit', - '2': [ - {'1': 'max_volume', '3': 1, '4': 1, '5': 12, '10': 'maxVolume'}, - {'1': 'window_secs', '3': 2, '4': 1, '5': 3, '10': 'windowSecs'}, - ], -}; - -/// Descriptor for `VolumeRateLimit`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List volumeRateLimitDescriptor = $convert.base64Decode( - 'Cg9Wb2x1bWVSYXRlTGltaXQSHQoKbWF4X3ZvbHVtZRgBIAEoDFIJbWF4Vm9sdW1lEh8KC3dpbm' - 'Rvd19zZWNzGAIgASgDUgp3aW5kb3dTZWNz'); - -@$core.Deprecated('Use sharedSettingsDescriptor instead') -const SharedSettings$json = { - '1': 'SharedSettings', - '2': [ - {'1': 'wallet_access_id', '3': 1, '4': 1, '5': 5, '10': 'walletAccessId'}, - {'1': 'chain_id', '3': 2, '4': 1, '5': 4, '10': 'chainId'}, - { - '1': 'valid_from', - '3': 3, - '4': 1, - '5': 11, - '6': '.google.protobuf.Timestamp', - '9': 0, - '10': 'validFrom', - '17': true - }, - { - '1': 'valid_until', - '3': 4, - '4': 1, - '5': 11, - '6': '.google.protobuf.Timestamp', - '9': 1, - '10': 'validUntil', - '17': true - }, - { - '1': 'max_gas_fee_per_gas', - '3': 5, - '4': 1, - '5': 12, - '9': 2, - '10': 'maxGasFeePerGas', - '17': true - }, - { - '1': 'max_priority_fee_per_gas', - '3': 6, - '4': 1, - '5': 12, - '9': 3, - '10': 'maxPriorityFeePerGas', - '17': true - }, - { - '1': 'rate_limit', - '3': 7, - '4': 1, - '5': 11, - '6': '.arbiter.evm.TransactionRateLimit', - '9': 4, - '10': 'rateLimit', - '17': true - }, - ], - '8': [ - {'1': '_valid_from'}, - {'1': '_valid_until'}, - {'1': '_max_gas_fee_per_gas'}, - {'1': '_max_priority_fee_per_gas'}, - {'1': '_rate_limit'}, - ], -}; - -/// Descriptor for `SharedSettings`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List sharedSettingsDescriptor = $convert.base64Decode( - 'Cg5TaGFyZWRTZXR0aW5ncxIoChB3YWxsZXRfYWNjZXNzX2lkGAEgASgFUg53YWxsZXRBY2Nlc3' - 'NJZBIZCghjaGFpbl9pZBgCIAEoBFIHY2hhaW5JZBI+Cgp2YWxpZF9mcm9tGAMgASgLMhouZ29v' - 'Z2xlLnByb3RvYnVmLlRpbWVzdGFtcEgAUgl2YWxpZEZyb22IAQESQAoLdmFsaWRfdW50aWwYBC' - 'ABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSAFSCnZhbGlkVW50aWyIAQESMQoTbWF4' - 'X2dhc19mZWVfcGVyX2dhcxgFIAEoDEgCUg9tYXhHYXNGZWVQZXJHYXOIAQESOwoYbWF4X3ByaW' - '9yaXR5X2ZlZV9wZXJfZ2FzGAYgASgMSANSFG1heFByaW9yaXR5RmVlUGVyR2FziAEBEkUKCnJh' - 'dGVfbGltaXQYByABKAsyIS5hcmJpdGVyLmV2bS5UcmFuc2FjdGlvblJhdGVMaW1pdEgEUglyYX' - 'RlTGltaXSIAQFCDQoLX3ZhbGlkX2Zyb21CDgoMX3ZhbGlkX3VudGlsQhYKFF9tYXhfZ2FzX2Zl' - 'ZV9wZXJfZ2FzQhsKGV9tYXhfcHJpb3JpdHlfZmVlX3Blcl9nYXNCDQoLX3JhdGVfbGltaXQ='); - -@$core.Deprecated('Use etherTransferSettingsDescriptor instead') -const EtherTransferSettings$json = { - '1': 'EtherTransferSettings', - '2': [ - {'1': 'targets', '3': 1, '4': 3, '5': 12, '10': 'targets'}, - { - '1': 'limit', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.evm.VolumeRateLimit', - '10': 'limit' - }, - ], -}; - -/// Descriptor for `EtherTransferSettings`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List etherTransferSettingsDescriptor = $convert.base64Decode( - 'ChVFdGhlclRyYW5zZmVyU2V0dGluZ3MSGAoHdGFyZ2V0cxgBIAMoDFIHdGFyZ2V0cxIyCgVsaW' - '1pdBgCIAEoCzIcLmFyYml0ZXIuZXZtLlZvbHVtZVJhdGVMaW1pdFIFbGltaXQ='); - -@$core.Deprecated('Use tokenTransferSettingsDescriptor instead') -const TokenTransferSettings$json = { - '1': 'TokenTransferSettings', - '2': [ - {'1': 'token_contract', '3': 1, '4': 1, '5': 12, '10': 'tokenContract'}, - { - '1': 'target', - '3': 2, - '4': 1, - '5': 12, - '9': 0, - '10': 'target', - '17': true - }, - { - '1': 'volume_limits', - '3': 3, - '4': 3, - '5': 11, - '6': '.arbiter.evm.VolumeRateLimit', - '10': 'volumeLimits' - }, - ], - '8': [ - {'1': '_target'}, - ], -}; - -/// Descriptor for `TokenTransferSettings`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List tokenTransferSettingsDescriptor = $convert.base64Decode( - 'ChVUb2tlblRyYW5zZmVyU2V0dGluZ3MSJQoOdG9rZW5fY29udHJhY3QYASABKAxSDXRva2VuQ2' - '9udHJhY3QSGwoGdGFyZ2V0GAIgASgMSABSBnRhcmdldIgBARJBCg12b2x1bWVfbGltaXRzGAMg' - 'AygLMhwuYXJiaXRlci5ldm0uVm9sdW1lUmF0ZUxpbWl0Ugx2b2x1bWVMaW1pdHNCCQoHX3Rhcm' - 'dldA=='); - -@$core.Deprecated('Use specificGrantDescriptor instead') -const SpecificGrant$json = { - '1': 'SpecificGrant', - '2': [ - { - '1': 'ether_transfer', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EtherTransferSettings', - '9': 0, - '10': 'etherTransfer' - }, - { - '1': 'token_transfer', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.evm.TokenTransferSettings', - '9': 0, - '10': 'tokenTransfer' - }, - ], - '8': [ - {'1': 'grant'}, - ], -}; - -/// Descriptor for `SpecificGrant`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List specificGrantDescriptor = $convert.base64Decode( - 'Cg1TcGVjaWZpY0dyYW50EksKDmV0aGVyX3RyYW5zZmVyGAEgASgLMiIuYXJiaXRlci5ldm0uRX' - 'RoZXJUcmFuc2ZlclNldHRpbmdzSABSDWV0aGVyVHJhbnNmZXISSwoOdG9rZW5fdHJhbnNmZXIY' - 'AiABKAsyIi5hcmJpdGVyLmV2bS5Ub2tlblRyYW5zZmVyU2V0dGluZ3NIAFINdG9rZW5UcmFuc2' - 'ZlckIHCgVncmFudA=='); - -@$core.Deprecated('Use evmGrantCreateRequestDescriptor instead') -const EvmGrantCreateRequest$json = { - '1': 'EvmGrantCreateRequest', - '2': [ - { - '1': 'shared', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.evm.SharedSettings', - '10': 'shared' - }, - { - '1': 'specific', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.evm.SpecificGrant', - '10': 'specific' - }, - ], -}; - -/// Descriptor for `EvmGrantCreateRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmGrantCreateRequestDescriptor = $convert.base64Decode( - 'ChVFdm1HcmFudENyZWF0ZVJlcXVlc3QSMwoGc2hhcmVkGAEgASgLMhsuYXJiaXRlci5ldm0uU2' - 'hhcmVkU2V0dGluZ3NSBnNoYXJlZBI2CghzcGVjaWZpYxgCIAEoCzIaLmFyYml0ZXIuZXZtLlNw' - 'ZWNpZmljR3JhbnRSCHNwZWNpZmlj'); - -@$core.Deprecated('Use evmGrantCreateResponseDescriptor instead') -const EvmGrantCreateResponse$json = { - '1': 'EvmGrantCreateResponse', - '2': [ - {'1': 'grant_id', '3': 1, '4': 1, '5': 5, '9': 0, '10': 'grantId'}, - { - '1': 'error', - '3': 2, - '4': 1, - '5': 14, - '6': '.arbiter.evm.EvmError', - '9': 0, - '10': 'error' - }, - ], - '8': [ - {'1': 'result'}, - ], -}; - -/// Descriptor for `EvmGrantCreateResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmGrantCreateResponseDescriptor = $convert.base64Decode( - 'ChZFdm1HcmFudENyZWF0ZVJlc3BvbnNlEhsKCGdyYW50X2lkGAEgASgFSABSB2dyYW50SWQSLQ' - 'oFZXJyb3IYAiABKA4yFS5hcmJpdGVyLmV2bS5Fdm1FcnJvckgAUgVlcnJvckIICgZyZXN1bHQ='); - -@$core.Deprecated('Use evmGrantDeleteRequestDescriptor instead') -const EvmGrantDeleteRequest$json = { - '1': 'EvmGrantDeleteRequest', - '2': [ - {'1': 'grant_id', '3': 1, '4': 1, '5': 5, '10': 'grantId'}, - ], -}; - -/// Descriptor for `EvmGrantDeleteRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmGrantDeleteRequestDescriptor = - $convert.base64Decode( - 'ChVFdm1HcmFudERlbGV0ZVJlcXVlc3QSGQoIZ3JhbnRfaWQYASABKAVSB2dyYW50SWQ='); - -@$core.Deprecated('Use evmGrantDeleteResponseDescriptor instead') -const EvmGrantDeleteResponse$json = { - '1': 'EvmGrantDeleteResponse', - '2': [ - { - '1': 'ok', - '3': 1, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'ok' - }, - { - '1': 'error', - '3': 2, - '4': 1, - '5': 14, - '6': '.arbiter.evm.EvmError', - '9': 0, - '10': 'error' - }, - ], - '8': [ - {'1': 'result'}, - ], -}; - -/// Descriptor for `EvmGrantDeleteResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmGrantDeleteResponseDescriptor = $convert.base64Decode( - 'ChZFdm1HcmFudERlbGV0ZVJlc3BvbnNlEigKAm9rGAEgASgLMhYuZ29vZ2xlLnByb3RvYnVmLk' - 'VtcHR5SABSAm9rEi0KBWVycm9yGAIgASgOMhUuYXJiaXRlci5ldm0uRXZtRXJyb3JIAFIFZXJy' - 'b3JCCAoGcmVzdWx0'); - -@$core.Deprecated('Use grantEntryDescriptor instead') -const GrantEntry$json = { - '1': 'GrantEntry', - '2': [ - {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, - {'1': 'wallet_access_id', '3': 2, '4': 1, '5': 5, '10': 'walletAccessId'}, - { - '1': 'shared', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.evm.SharedSettings', - '10': 'shared' - }, - { - '1': 'specific', - '3': 4, - '4': 1, - '5': 11, - '6': '.arbiter.evm.SpecificGrant', - '10': 'specific' - }, - ], -}; - -/// Descriptor for `GrantEntry`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List grantEntryDescriptor = $convert.base64Decode( - 'CgpHcmFudEVudHJ5Eg4KAmlkGAEgASgFUgJpZBIoChB3YWxsZXRfYWNjZXNzX2lkGAIgASgFUg' - '53YWxsZXRBY2Nlc3NJZBIzCgZzaGFyZWQYAyABKAsyGy5hcmJpdGVyLmV2bS5TaGFyZWRTZXR0' - 'aW5nc1IGc2hhcmVkEjYKCHNwZWNpZmljGAQgASgLMhouYXJiaXRlci5ldm0uU3BlY2lmaWNHcm' - 'FudFIIc3BlY2lmaWM='); - -@$core.Deprecated('Use evmGrantListRequestDescriptor instead') -const EvmGrantListRequest$json = { - '1': 'EvmGrantListRequest', - '2': [ - { - '1': 'wallet_access_id', - '3': 1, - '4': 1, - '5': 5, - '9': 0, - '10': 'walletAccessId', - '17': true - }, - ], - '8': [ - {'1': '_wallet_access_id'}, - ], -}; - -/// Descriptor for `EvmGrantListRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmGrantListRequestDescriptor = $convert.base64Decode( - 'ChNFdm1HcmFudExpc3RSZXF1ZXN0Ei0KEHdhbGxldF9hY2Nlc3NfaWQYASABKAVIAFIOd2FsbG' - 'V0QWNjZXNzSWSIAQFCEwoRX3dhbGxldF9hY2Nlc3NfaWQ='); - -@$core.Deprecated('Use evmGrantListResponseDescriptor instead') -const EvmGrantListResponse$json = { - '1': 'EvmGrantListResponse', - '2': [ - { - '1': 'grants', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmGrantList', - '9': 0, - '10': 'grants' - }, - { - '1': 'error', - '3': 2, - '4': 1, - '5': 14, - '6': '.arbiter.evm.EvmError', - '9': 0, - '10': 'error' - }, - ], - '8': [ - {'1': 'result'}, - ], -}; - -/// Descriptor for `EvmGrantListResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmGrantListResponseDescriptor = $convert.base64Decode( - 'ChRFdm1HcmFudExpc3RSZXNwb25zZRIzCgZncmFudHMYASABKAsyGS5hcmJpdGVyLmV2bS5Fdm' - '1HcmFudExpc3RIAFIGZ3JhbnRzEi0KBWVycm9yGAIgASgOMhUuYXJiaXRlci5ldm0uRXZtRXJy' - 'b3JIAFIFZXJyb3JCCAoGcmVzdWx0'); - -@$core.Deprecated('Use evmGrantListDescriptor instead') -const EvmGrantList$json = { - '1': 'EvmGrantList', - '2': [ - { - '1': 'grants', - '3': 1, - '4': 3, - '5': 11, - '6': '.arbiter.evm.GrantEntry', - '10': 'grants' - }, - ], -}; - -/// Descriptor for `EvmGrantList`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmGrantListDescriptor = $convert.base64Decode( - 'CgxFdm1HcmFudExpc3QSLwoGZ3JhbnRzGAEgAygLMhcuYXJiaXRlci5ldm0uR3JhbnRFbnRyeV' - 'IGZ3JhbnRz'); - -@$core.Deprecated('Use evmSignTransactionRequestDescriptor instead') -const EvmSignTransactionRequest$json = { - '1': 'EvmSignTransactionRequest', - '2': [ - {'1': 'wallet_address', '3': 1, '4': 1, '5': 12, '10': 'walletAddress'}, - {'1': 'rlp_transaction', '3': 2, '4': 1, '5': 12, '10': 'rlpTransaction'}, - ], -}; - -/// Descriptor for `EvmSignTransactionRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmSignTransactionRequestDescriptor = - $convert.base64Decode( - 'ChlFdm1TaWduVHJhbnNhY3Rpb25SZXF1ZXN0EiUKDndhbGxldF9hZGRyZXNzGAEgASgMUg13YW' - 'xsZXRBZGRyZXNzEicKD3JscF90cmFuc2FjdGlvbhgCIAEoDFIOcmxwVHJhbnNhY3Rpb24='); - -@$core.Deprecated('Use evmSignTransactionResponseDescriptor instead') -const EvmSignTransactionResponse$json = { - '1': 'EvmSignTransactionResponse', - '2': [ - {'1': 'signature', '3': 1, '4': 1, '5': 12, '9': 0, '10': 'signature'}, - { - '1': 'eval_error', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.TransactionEvalError', - '9': 0, - '10': 'evalError' - }, - { - '1': 'error', - '3': 3, - '4': 1, - '5': 14, - '6': '.arbiter.evm.EvmError', - '9': 0, - '10': 'error' - }, - ], - '8': [ - {'1': 'result'}, - ], -}; - -/// Descriptor for `EvmSignTransactionResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmSignTransactionResponseDescriptor = $convert.base64Decode( - 'ChpFdm1TaWduVHJhbnNhY3Rpb25SZXNwb25zZRIeCglzaWduYXR1cmUYASABKAxIAFIJc2lnbm' - 'F0dXJlEkkKCmV2YWxfZXJyb3IYAiABKAsyKC5hcmJpdGVyLnNoYXJlZC5ldm0uVHJhbnNhY3Rp' - 'b25FdmFsRXJyb3JIAFIJZXZhbEVycm9yEi0KBWVycm9yGAMgASgOMhUuYXJiaXRlci5ldm0uRX' - 'ZtRXJyb3JIAFIFZXJyb3JCCAoGcmVzdWx0'); - -@$core.Deprecated('Use evmAnalyzeTransactionRequestDescriptor instead') -const EvmAnalyzeTransactionRequest$json = { - '1': 'EvmAnalyzeTransactionRequest', - '2': [ - {'1': 'wallet_address', '3': 1, '4': 1, '5': 12, '10': 'walletAddress'}, - {'1': 'rlp_transaction', '3': 2, '4': 1, '5': 12, '10': 'rlpTransaction'}, - ], -}; - -/// Descriptor for `EvmAnalyzeTransactionRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmAnalyzeTransactionRequestDescriptor = - $convert.base64Decode( - 'ChxFdm1BbmFseXplVHJhbnNhY3Rpb25SZXF1ZXN0EiUKDndhbGxldF9hZGRyZXNzGAEgASgMUg' - '13YWxsZXRBZGRyZXNzEicKD3JscF90cmFuc2FjdGlvbhgCIAEoDFIOcmxwVHJhbnNhY3Rpb24='); - -@$core.Deprecated('Use evmAnalyzeTransactionResponseDescriptor instead') -const EvmAnalyzeTransactionResponse$json = { - '1': 'EvmAnalyzeTransactionResponse', - '2': [ - { - '1': 'meaning', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.SpecificMeaning', - '9': 0, - '10': 'meaning' - }, - { - '1': 'eval_error', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.TransactionEvalError', - '9': 0, - '10': 'evalError' - }, - { - '1': 'error', - '3': 3, - '4': 1, - '5': 14, - '6': '.arbiter.evm.EvmError', - '9': 0, - '10': 'error' - }, - ], - '8': [ - {'1': 'result'}, - ], -}; - -/// Descriptor for `EvmAnalyzeTransactionResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evmAnalyzeTransactionResponseDescriptor = $convert.base64Decode( - 'Ch1Fdm1BbmFseXplVHJhbnNhY3Rpb25SZXNwb25zZRI/CgdtZWFuaW5nGAEgASgLMiMuYXJiaX' - 'Rlci5zaGFyZWQuZXZtLlNwZWNpZmljTWVhbmluZ0gAUgdtZWFuaW5nEkkKCmV2YWxfZXJyb3IY' - 'AiABKAsyKC5hcmJpdGVyLnNoYXJlZC5ldm0uVHJhbnNhY3Rpb25FdmFsRXJyb3JIAFIJZXZhbE' - 'Vycm9yEi0KBWVycm9yGAMgASgOMhUuYXJiaXRlci5ldm0uRXZtRXJyb3JIAFIFZXJyb3JCCAoG' - 'cmVzdWx0'); +// This is a generated file - do not edit. +// +// Generated from evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use evmErrorDescriptor instead') +const EvmError$json = { + '1': 'EvmError', + '2': [ + {'1': 'EVM_ERROR_UNSPECIFIED', '2': 0}, + {'1': 'EVM_ERROR_VAULT_SEALED', '2': 1}, + {'1': 'EVM_ERROR_INTERNAL', '2': 2}, + ], +}; + +/// Descriptor for `EvmError`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List evmErrorDescriptor = $convert.base64Decode( + 'CghFdm1FcnJvchIZChVFVk1fRVJST1JfVU5TUEVDSUZJRUQQABIaChZFVk1fRVJST1JfVkFVTF' + 'RfU0VBTEVEEAESFgoSRVZNX0VSUk9SX0lOVEVSTkFMEAI='); + +@$core.Deprecated('Use walletEntryDescriptor instead') +const WalletEntry$json = { + '1': 'WalletEntry', + '2': [ + {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, + {'1': 'address', '3': 2, '4': 1, '5': 12, '10': 'address'}, + ], +}; + +/// Descriptor for `WalletEntry`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List walletEntryDescriptor = $convert.base64Decode( + 'CgtXYWxsZXRFbnRyeRIOCgJpZBgBIAEoBVICaWQSGAoHYWRkcmVzcxgCIAEoDFIHYWRkcmVzcw' + '=='); + +@$core.Deprecated('Use walletListDescriptor instead') +const WalletList$json = { + '1': 'WalletList', + '2': [ + { + '1': 'wallets', + '3': 1, + '4': 3, + '5': 11, + '6': '.arbiter.evm.WalletEntry', + '10': 'wallets' + }, + ], +}; + +/// Descriptor for `WalletList`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List walletListDescriptor = $convert.base64Decode( + 'CgpXYWxsZXRMaXN0EjIKB3dhbGxldHMYASADKAsyGC5hcmJpdGVyLmV2bS5XYWxsZXRFbnRyeV' + 'IHd2FsbGV0cw=='); + +@$core.Deprecated('Use walletCreateResponseDescriptor instead') +const WalletCreateResponse$json = { + '1': 'WalletCreateResponse', + '2': [ + { + '1': 'wallet', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.evm.WalletEntry', + '9': 0, + '10': 'wallet' + }, + { + '1': 'error', + '3': 2, + '4': 1, + '5': 14, + '6': '.arbiter.evm.EvmError', + '9': 0, + '10': 'error' + }, + ], + '8': [ + {'1': 'result'}, + ], +}; + +/// Descriptor for `WalletCreateResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List walletCreateResponseDescriptor = $convert.base64Decode( + 'ChRXYWxsZXRDcmVhdGVSZXNwb25zZRIyCgZ3YWxsZXQYASABKAsyGC5hcmJpdGVyLmV2bS5XYW' + 'xsZXRFbnRyeUgAUgZ3YWxsZXQSLQoFZXJyb3IYAiABKA4yFS5hcmJpdGVyLmV2bS5Fdm1FcnJv' + 'ckgAUgVlcnJvckIICgZyZXN1bHQ='); + +@$core.Deprecated('Use walletListResponseDescriptor instead') +const WalletListResponse$json = { + '1': 'WalletListResponse', + '2': [ + { + '1': 'wallets', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.evm.WalletList', + '9': 0, + '10': 'wallets' + }, + { + '1': 'error', + '3': 2, + '4': 1, + '5': 14, + '6': '.arbiter.evm.EvmError', + '9': 0, + '10': 'error' + }, + ], + '8': [ + {'1': 'result'}, + ], +}; + +/// Descriptor for `WalletListResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List walletListResponseDescriptor = $convert.base64Decode( + 'ChJXYWxsZXRMaXN0UmVzcG9uc2USMwoHd2FsbGV0cxgBIAEoCzIXLmFyYml0ZXIuZXZtLldhbG' + 'xldExpc3RIAFIHd2FsbGV0cxItCgVlcnJvchgCIAEoDjIVLmFyYml0ZXIuZXZtLkV2bUVycm9y' + 'SABSBWVycm9yQggKBnJlc3VsdA=='); + +@$core.Deprecated('Use transactionRateLimitDescriptor instead') +const TransactionRateLimit$json = { + '1': 'TransactionRateLimit', + '2': [ + {'1': 'count', '3': 1, '4': 1, '5': 13, '10': 'count'}, + {'1': 'window_secs', '3': 2, '4': 1, '5': 3, '10': 'windowSecs'}, + ], +}; + +/// Descriptor for `TransactionRateLimit`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List transactionRateLimitDescriptor = $convert.base64Decode( + 'ChRUcmFuc2FjdGlvblJhdGVMaW1pdBIUCgVjb3VudBgBIAEoDVIFY291bnQSHwoLd2luZG93X3' + 'NlY3MYAiABKANSCndpbmRvd1NlY3M='); + +@$core.Deprecated('Use volumeRateLimitDescriptor instead') +const VolumeRateLimit$json = { + '1': 'VolumeRateLimit', + '2': [ + {'1': 'max_volume', '3': 1, '4': 1, '5': 12, '10': 'maxVolume'}, + {'1': 'window_secs', '3': 2, '4': 1, '5': 3, '10': 'windowSecs'}, + ], +}; + +/// Descriptor for `VolumeRateLimit`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List volumeRateLimitDescriptor = $convert.base64Decode( + 'Cg9Wb2x1bWVSYXRlTGltaXQSHQoKbWF4X3ZvbHVtZRgBIAEoDFIJbWF4Vm9sdW1lEh8KC3dpbm' + 'Rvd19zZWNzGAIgASgDUgp3aW5kb3dTZWNz'); + +@$core.Deprecated('Use sharedSettingsDescriptor instead') +const SharedSettings$json = { + '1': 'SharedSettings', + '2': [ + {'1': 'wallet_access_id', '3': 1, '4': 1, '5': 5, '10': 'walletAccessId'}, + {'1': 'chain_id', '3': 2, '4': 1, '5': 4, '10': 'chainId'}, + { + '1': 'valid_from', + '3': 3, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '9': 0, + '10': 'validFrom', + '17': true + }, + { + '1': 'valid_until', + '3': 4, + '4': 1, + '5': 11, + '6': '.google.protobuf.Timestamp', + '9': 1, + '10': 'validUntil', + '17': true + }, + { + '1': 'max_gas_fee_per_gas', + '3': 5, + '4': 1, + '5': 12, + '9': 2, + '10': 'maxGasFeePerGas', + '17': true + }, + { + '1': 'max_priority_fee_per_gas', + '3': 6, + '4': 1, + '5': 12, + '9': 3, + '10': 'maxPriorityFeePerGas', + '17': true + }, + { + '1': 'rate_limit', + '3': 7, + '4': 1, + '5': 11, + '6': '.arbiter.evm.TransactionRateLimit', + '9': 4, + '10': 'rateLimit', + '17': true + }, + ], + '8': [ + {'1': '_valid_from'}, + {'1': '_valid_until'}, + {'1': '_max_gas_fee_per_gas'}, + {'1': '_max_priority_fee_per_gas'}, + {'1': '_rate_limit'}, + ], +}; + +/// Descriptor for `SharedSettings`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List sharedSettingsDescriptor = $convert.base64Decode( + 'Cg5TaGFyZWRTZXR0aW5ncxIoChB3YWxsZXRfYWNjZXNzX2lkGAEgASgFUg53YWxsZXRBY2Nlc3' + 'NJZBIZCghjaGFpbl9pZBgCIAEoBFIHY2hhaW5JZBI+Cgp2YWxpZF9mcm9tGAMgASgLMhouZ29v' + 'Z2xlLnByb3RvYnVmLlRpbWVzdGFtcEgAUgl2YWxpZEZyb22IAQESQAoLdmFsaWRfdW50aWwYBC' + 'ABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wSAFSCnZhbGlkVW50aWyIAQESMQoTbWF4' + 'X2dhc19mZWVfcGVyX2dhcxgFIAEoDEgCUg9tYXhHYXNGZWVQZXJHYXOIAQESOwoYbWF4X3ByaW' + '9yaXR5X2ZlZV9wZXJfZ2FzGAYgASgMSANSFG1heFByaW9yaXR5RmVlUGVyR2FziAEBEkUKCnJh' + 'dGVfbGltaXQYByABKAsyIS5hcmJpdGVyLmV2bS5UcmFuc2FjdGlvblJhdGVMaW1pdEgEUglyYX' + 'RlTGltaXSIAQFCDQoLX3ZhbGlkX2Zyb21CDgoMX3ZhbGlkX3VudGlsQhYKFF9tYXhfZ2FzX2Zl' + 'ZV9wZXJfZ2FzQhsKGV9tYXhfcHJpb3JpdHlfZmVlX3Blcl9nYXNCDQoLX3JhdGVfbGltaXQ='); + +@$core.Deprecated('Use etherTransferSettingsDescriptor instead') +const EtherTransferSettings$json = { + '1': 'EtherTransferSettings', + '2': [ + {'1': 'targets', '3': 1, '4': 3, '5': 12, '10': 'targets'}, + { + '1': 'limit', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.evm.VolumeRateLimit', + '10': 'limit' + }, + ], +}; + +/// Descriptor for `EtherTransferSettings`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List etherTransferSettingsDescriptor = $convert.base64Decode( + 'ChVFdGhlclRyYW5zZmVyU2V0dGluZ3MSGAoHdGFyZ2V0cxgBIAMoDFIHdGFyZ2V0cxIyCgVsaW' + '1pdBgCIAEoCzIcLmFyYml0ZXIuZXZtLlZvbHVtZVJhdGVMaW1pdFIFbGltaXQ='); + +@$core.Deprecated('Use tokenTransferSettingsDescriptor instead') +const TokenTransferSettings$json = { + '1': 'TokenTransferSettings', + '2': [ + {'1': 'token_contract', '3': 1, '4': 1, '5': 12, '10': 'tokenContract'}, + { + '1': 'target', + '3': 2, + '4': 1, + '5': 12, + '9': 0, + '10': 'target', + '17': true + }, + { + '1': 'volume_limits', + '3': 3, + '4': 3, + '5': 11, + '6': '.arbiter.evm.VolumeRateLimit', + '10': 'volumeLimits' + }, + ], + '8': [ + {'1': '_target'}, + ], +}; + +/// Descriptor for `TokenTransferSettings`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List tokenTransferSettingsDescriptor = $convert.base64Decode( + 'ChVUb2tlblRyYW5zZmVyU2V0dGluZ3MSJQoOdG9rZW5fY29udHJhY3QYASABKAxSDXRva2VuQ2' + '9udHJhY3QSGwoGdGFyZ2V0GAIgASgMSABSBnRhcmdldIgBARJBCg12b2x1bWVfbGltaXRzGAMg' + 'AygLMhwuYXJiaXRlci5ldm0uVm9sdW1lUmF0ZUxpbWl0Ugx2b2x1bWVMaW1pdHNCCQoHX3Rhcm' + 'dldA=='); + +@$core.Deprecated('Use specificGrantDescriptor instead') +const SpecificGrant$json = { + '1': 'SpecificGrant', + '2': [ + { + '1': 'ether_transfer', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EtherTransferSettings', + '9': 0, + '10': 'etherTransfer' + }, + { + '1': 'token_transfer', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.evm.TokenTransferSettings', + '9': 0, + '10': 'tokenTransfer' + }, + ], + '8': [ + {'1': 'grant'}, + ], +}; + +/// Descriptor for `SpecificGrant`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List specificGrantDescriptor = $convert.base64Decode( + 'Cg1TcGVjaWZpY0dyYW50EksKDmV0aGVyX3RyYW5zZmVyGAEgASgLMiIuYXJiaXRlci5ldm0uRX' + 'RoZXJUcmFuc2ZlclNldHRpbmdzSABSDWV0aGVyVHJhbnNmZXISSwoOdG9rZW5fdHJhbnNmZXIY' + 'AiABKAsyIi5hcmJpdGVyLmV2bS5Ub2tlblRyYW5zZmVyU2V0dGluZ3NIAFINdG9rZW5UcmFuc2' + 'ZlckIHCgVncmFudA=='); + +@$core.Deprecated('Use evmGrantCreateRequestDescriptor instead') +const EvmGrantCreateRequest$json = { + '1': 'EvmGrantCreateRequest', + '2': [ + { + '1': 'shared', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.evm.SharedSettings', + '10': 'shared' + }, + { + '1': 'specific', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.evm.SpecificGrant', + '10': 'specific' + }, + ], +}; + +/// Descriptor for `EvmGrantCreateRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmGrantCreateRequestDescriptor = $convert.base64Decode( + 'ChVFdm1HcmFudENyZWF0ZVJlcXVlc3QSMwoGc2hhcmVkGAEgASgLMhsuYXJiaXRlci5ldm0uU2' + 'hhcmVkU2V0dGluZ3NSBnNoYXJlZBI2CghzcGVjaWZpYxgCIAEoCzIaLmFyYml0ZXIuZXZtLlNw' + 'ZWNpZmljR3JhbnRSCHNwZWNpZmlj'); + +@$core.Deprecated('Use evmGrantCreateResponseDescriptor instead') +const EvmGrantCreateResponse$json = { + '1': 'EvmGrantCreateResponse', + '2': [ + {'1': 'grant_id', '3': 1, '4': 1, '5': 5, '9': 0, '10': 'grantId'}, + { + '1': 'error', + '3': 2, + '4': 1, + '5': 14, + '6': '.arbiter.evm.EvmError', + '9': 0, + '10': 'error' + }, + ], + '8': [ + {'1': 'result'}, + ], +}; + +/// Descriptor for `EvmGrantCreateResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmGrantCreateResponseDescriptor = $convert.base64Decode( + 'ChZFdm1HcmFudENyZWF0ZVJlc3BvbnNlEhsKCGdyYW50X2lkGAEgASgFSABSB2dyYW50SWQSLQ' + 'oFZXJyb3IYAiABKA4yFS5hcmJpdGVyLmV2bS5Fdm1FcnJvckgAUgVlcnJvckIICgZyZXN1bHQ='); + +@$core.Deprecated('Use evmGrantDeleteRequestDescriptor instead') +const EvmGrantDeleteRequest$json = { + '1': 'EvmGrantDeleteRequest', + '2': [ + {'1': 'grant_id', '3': 1, '4': 1, '5': 5, '10': 'grantId'}, + ], +}; + +/// Descriptor for `EvmGrantDeleteRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmGrantDeleteRequestDescriptor = + $convert.base64Decode( + 'ChVFdm1HcmFudERlbGV0ZVJlcXVlc3QSGQoIZ3JhbnRfaWQYASABKAVSB2dyYW50SWQ='); + +@$core.Deprecated('Use evmGrantDeleteResponseDescriptor instead') +const EvmGrantDeleteResponse$json = { + '1': 'EvmGrantDeleteResponse', + '2': [ + { + '1': 'ok', + '3': 1, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'ok' + }, + { + '1': 'error', + '3': 2, + '4': 1, + '5': 14, + '6': '.arbiter.evm.EvmError', + '9': 0, + '10': 'error' + }, + ], + '8': [ + {'1': 'result'}, + ], +}; + +/// Descriptor for `EvmGrantDeleteResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmGrantDeleteResponseDescriptor = $convert.base64Decode( + 'ChZFdm1HcmFudERlbGV0ZVJlc3BvbnNlEigKAm9rGAEgASgLMhYuZ29vZ2xlLnByb3RvYnVmLk' + 'VtcHR5SABSAm9rEi0KBWVycm9yGAIgASgOMhUuYXJiaXRlci5ldm0uRXZtRXJyb3JIAFIFZXJy' + 'b3JCCAoGcmVzdWx0'); + +@$core.Deprecated('Use grantEntryDescriptor instead') +const GrantEntry$json = { + '1': 'GrantEntry', + '2': [ + {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, + {'1': 'wallet_access_id', '3': 2, '4': 1, '5': 5, '10': 'walletAccessId'}, + { + '1': 'shared', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.evm.SharedSettings', + '10': 'shared' + }, + { + '1': 'specific', + '3': 4, + '4': 1, + '5': 11, + '6': '.arbiter.evm.SpecificGrant', + '10': 'specific' + }, + ], +}; + +/// Descriptor for `GrantEntry`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List grantEntryDescriptor = $convert.base64Decode( + 'CgpHcmFudEVudHJ5Eg4KAmlkGAEgASgFUgJpZBIoChB3YWxsZXRfYWNjZXNzX2lkGAIgASgFUg' + '53YWxsZXRBY2Nlc3NJZBIzCgZzaGFyZWQYAyABKAsyGy5hcmJpdGVyLmV2bS5TaGFyZWRTZXR0' + 'aW5nc1IGc2hhcmVkEjYKCHNwZWNpZmljGAQgASgLMhouYXJiaXRlci5ldm0uU3BlY2lmaWNHcm' + 'FudFIIc3BlY2lmaWM='); + +@$core.Deprecated('Use evmGrantListRequestDescriptor instead') +const EvmGrantListRequest$json = { + '1': 'EvmGrantListRequest', + '2': [ + { + '1': 'wallet_access_id', + '3': 1, + '4': 1, + '5': 5, + '9': 0, + '10': 'walletAccessId', + '17': true + }, + ], + '8': [ + {'1': '_wallet_access_id'}, + ], +}; + +/// Descriptor for `EvmGrantListRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmGrantListRequestDescriptor = $convert.base64Decode( + 'ChNFdm1HcmFudExpc3RSZXF1ZXN0Ei0KEHdhbGxldF9hY2Nlc3NfaWQYASABKAVIAFIOd2FsbG' + 'V0QWNjZXNzSWSIAQFCEwoRX3dhbGxldF9hY2Nlc3NfaWQ='); + +@$core.Deprecated('Use evmGrantListResponseDescriptor instead') +const EvmGrantListResponse$json = { + '1': 'EvmGrantListResponse', + '2': [ + { + '1': 'grants', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmGrantList', + '9': 0, + '10': 'grants' + }, + { + '1': 'error', + '3': 2, + '4': 1, + '5': 14, + '6': '.arbiter.evm.EvmError', + '9': 0, + '10': 'error' + }, + ], + '8': [ + {'1': 'result'}, + ], +}; + +/// Descriptor for `EvmGrantListResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmGrantListResponseDescriptor = $convert.base64Decode( + 'ChRFdm1HcmFudExpc3RSZXNwb25zZRIzCgZncmFudHMYASABKAsyGS5hcmJpdGVyLmV2bS5Fdm' + '1HcmFudExpc3RIAFIGZ3JhbnRzEi0KBWVycm9yGAIgASgOMhUuYXJiaXRlci5ldm0uRXZtRXJy' + 'b3JIAFIFZXJyb3JCCAoGcmVzdWx0'); + +@$core.Deprecated('Use evmGrantListDescriptor instead') +const EvmGrantList$json = { + '1': 'EvmGrantList', + '2': [ + { + '1': 'grants', + '3': 1, + '4': 3, + '5': 11, + '6': '.arbiter.evm.GrantEntry', + '10': 'grants' + }, + ], +}; + +/// Descriptor for `EvmGrantList`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmGrantListDescriptor = $convert.base64Decode( + 'CgxFdm1HcmFudExpc3QSLwoGZ3JhbnRzGAEgAygLMhcuYXJiaXRlci5ldm0uR3JhbnRFbnRyeV' + 'IGZ3JhbnRz'); + +@$core.Deprecated('Use evmSignTransactionRequestDescriptor instead') +const EvmSignTransactionRequest$json = { + '1': 'EvmSignTransactionRequest', + '2': [ + {'1': 'wallet_address', '3': 1, '4': 1, '5': 12, '10': 'walletAddress'}, + {'1': 'rlp_transaction', '3': 2, '4': 1, '5': 12, '10': 'rlpTransaction'}, + ], +}; + +/// Descriptor for `EvmSignTransactionRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmSignTransactionRequestDescriptor = + $convert.base64Decode( + 'ChlFdm1TaWduVHJhbnNhY3Rpb25SZXF1ZXN0EiUKDndhbGxldF9hZGRyZXNzGAEgASgMUg13YW' + 'xsZXRBZGRyZXNzEicKD3JscF90cmFuc2FjdGlvbhgCIAEoDFIOcmxwVHJhbnNhY3Rpb24='); + +@$core.Deprecated('Use evmSignTransactionResponseDescriptor instead') +const EvmSignTransactionResponse$json = { + '1': 'EvmSignTransactionResponse', + '2': [ + {'1': 'signature', '3': 1, '4': 1, '5': 12, '9': 0, '10': 'signature'}, + { + '1': 'eval_error', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.TransactionEvalError', + '9': 0, + '10': 'evalError' + }, + { + '1': 'error', + '3': 3, + '4': 1, + '5': 14, + '6': '.arbiter.evm.EvmError', + '9': 0, + '10': 'error' + }, + ], + '8': [ + {'1': 'result'}, + ], +}; + +/// Descriptor for `EvmSignTransactionResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmSignTransactionResponseDescriptor = $convert.base64Decode( + 'ChpFdm1TaWduVHJhbnNhY3Rpb25SZXNwb25zZRIeCglzaWduYXR1cmUYASABKAxIAFIJc2lnbm' + 'F0dXJlEkkKCmV2YWxfZXJyb3IYAiABKAsyKC5hcmJpdGVyLnNoYXJlZC5ldm0uVHJhbnNhY3Rp' + 'b25FdmFsRXJyb3JIAFIJZXZhbEVycm9yEi0KBWVycm9yGAMgASgOMhUuYXJiaXRlci5ldm0uRX' + 'ZtRXJyb3JIAFIFZXJyb3JCCAoGcmVzdWx0'); + +@$core.Deprecated('Use evmAnalyzeTransactionRequestDescriptor instead') +const EvmAnalyzeTransactionRequest$json = { + '1': 'EvmAnalyzeTransactionRequest', + '2': [ + {'1': 'wallet_address', '3': 1, '4': 1, '5': 12, '10': 'walletAddress'}, + {'1': 'rlp_transaction', '3': 2, '4': 1, '5': 12, '10': 'rlpTransaction'}, + ], +}; + +/// Descriptor for `EvmAnalyzeTransactionRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmAnalyzeTransactionRequestDescriptor = + $convert.base64Decode( + 'ChxFdm1BbmFseXplVHJhbnNhY3Rpb25SZXF1ZXN0EiUKDndhbGxldF9hZGRyZXNzGAEgASgMUg' + '13YWxsZXRBZGRyZXNzEicKD3JscF90cmFuc2FjdGlvbhgCIAEoDFIOcmxwVHJhbnNhY3Rpb24='); + +@$core.Deprecated('Use evmAnalyzeTransactionResponseDescriptor instead') +const EvmAnalyzeTransactionResponse$json = { + '1': 'EvmAnalyzeTransactionResponse', + '2': [ + { + '1': 'meaning', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.SpecificMeaning', + '9': 0, + '10': 'meaning' + }, + { + '1': 'eval_error', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.TransactionEvalError', + '9': 0, + '10': 'evalError' + }, + { + '1': 'error', + '3': 3, + '4': 1, + '5': 14, + '6': '.arbiter.evm.EvmError', + '9': 0, + '10': 'error' + }, + ], + '8': [ + {'1': 'result'}, + ], +}; + +/// Descriptor for `EvmAnalyzeTransactionResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evmAnalyzeTransactionResponseDescriptor = $convert.base64Decode( + 'Ch1Fdm1BbmFseXplVHJhbnNhY3Rpb25SZXNwb25zZRI/CgdtZWFuaW5nGAEgASgLMiMuYXJiaX' + 'Rlci5zaGFyZWQuZXZtLlNwZWNpZmljTWVhbmluZ0gAUgdtZWFuaW5nEkkKCmV2YWxfZXJyb3IY' + 'AiABKAsyKC5hcmJpdGVyLnNoYXJlZC5ldm0uVHJhbnNhY3Rpb25FdmFsRXJyb3JIAFIJZXZhbE' + 'Vycm9yEi0KBWVycm9yGAMgASgOMhUuYXJiaXRlci5ldm0uRXZtRXJyb3JIAFIFZXJyb3JCCAoG' + 'cmVzdWx0'); diff --git a/useragent/lib/proto/shared/client.pb.dart b/useragent/lib/proto/shared/client.pb.dart index cb4bdfb..7d94525 100644 --- a/useragent/lib/proto/shared/client.pb.dart +++ b/useragent/lib/proto/shared/client.pb.dart @@ -1,99 +1,99 @@ -// This is a generated file - do not edit. -// -// Generated from shared/client.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -class ClientInfo extends $pb.GeneratedMessage { - factory ClientInfo({ - $core.String? name, - $core.String? description, - $core.String? version, - }) { - final result = create(); - if (name != null) result.name = name; - if (description != null) result.description = description; - if (version != null) result.version = version; - return result; - } - - ClientInfo._(); - - factory ClientInfo.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory ClientInfo.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'ClientInfo', - package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared'), - createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'name') - ..aOS(2, _omitFieldNames ? '' : 'description') - ..aOS(3, _omitFieldNames ? '' : 'version') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ClientInfo clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ClientInfo copyWith(void Function(ClientInfo) updates) => - super.copyWith((message) => updates(message as ClientInfo)) as ClientInfo; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static ClientInfo create() => ClientInfo._(); - @$core.override - ClientInfo createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static ClientInfo getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static ClientInfo? _defaultInstance; - - @$pb.TagNumber(1) - $core.String get name => $_getSZ(0); - @$pb.TagNumber(1) - set name($core.String value) => $_setString(0, value); - @$pb.TagNumber(1) - $core.bool hasName() => $_has(0); - @$pb.TagNumber(1) - void clearName() => $_clearField(1); - - @$pb.TagNumber(2) - $core.String get description => $_getSZ(1); - @$pb.TagNumber(2) - set description($core.String value) => $_setString(1, value); - @$pb.TagNumber(2) - $core.bool hasDescription() => $_has(1); - @$pb.TagNumber(2) - void clearDescription() => $_clearField(2); - - @$pb.TagNumber(3) - $core.String get version => $_getSZ(2); - @$pb.TagNumber(3) - set version($core.String value) => $_setString(2, value); - @$pb.TagNumber(3) - $core.bool hasVersion() => $_has(2); - @$pb.TagNumber(3) - void clearVersion() => $_clearField(3); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from shared/client.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +class ClientInfo extends $pb.GeneratedMessage { + factory ClientInfo({ + $core.String? name, + $core.String? description, + $core.String? version, + }) { + final result = create(); + if (name != null) result.name = name; + if (description != null) result.description = description; + if (version != null) result.version = version; + return result; + } + + ClientInfo._(); + + factory ClientInfo.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory ClientInfo.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ClientInfo', + package: const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared'), + createEmptyInstance: create) + ..aOS(1, _omitFieldNames ? '' : 'name') + ..aOS(2, _omitFieldNames ? '' : 'description') + ..aOS(3, _omitFieldNames ? '' : 'version') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ClientInfo clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ClientInfo copyWith(void Function(ClientInfo) updates) => + super.copyWith((message) => updates(message as ClientInfo)) as ClientInfo; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ClientInfo create() => ClientInfo._(); + @$core.override + ClientInfo createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static ClientInfo getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static ClientInfo? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get name => $_getSZ(0); + @$pb.TagNumber(1) + set name($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasName() => $_has(0); + @$pb.TagNumber(1) + void clearName() => $_clearField(1); + + @$pb.TagNumber(2) + $core.String get description => $_getSZ(1); + @$pb.TagNumber(2) + set description($core.String value) => $_setString(1, value); + @$pb.TagNumber(2) + $core.bool hasDescription() => $_has(1); + @$pb.TagNumber(2) + void clearDescription() => $_clearField(2); + + @$pb.TagNumber(3) + $core.String get version => $_getSZ(2); + @$pb.TagNumber(3) + set version($core.String value) => $_setString(2, value); + @$pb.TagNumber(3) + $core.bool hasVersion() => $_has(2); + @$pb.TagNumber(3) + void clearVersion() => $_clearField(3); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/shared/client.pbenum.dart b/useragent/lib/proto/shared/client.pbenum.dart index 9b4f582..9fa3a91 100644 --- a/useragent/lib/proto/shared/client.pbenum.dart +++ b/useragent/lib/proto/shared/client.pbenum.dart @@ -1,11 +1,11 @@ -// This is a generated file - do not edit. -// -// Generated from shared/client.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// This is a generated file - do not edit. +// +// Generated from shared/client.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports diff --git a/useragent/lib/proto/shared/client.pbjson.dart b/useragent/lib/proto/shared/client.pbjson.dart index b868f5d..c82b4ac 100644 --- a/useragent/lib/proto/shared/client.pbjson.dart +++ b/useragent/lib/proto/shared/client.pbjson.dart @@ -1,52 +1,52 @@ -// This is a generated file - do not edit. -// -// Generated from shared/client.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use clientInfoDescriptor instead') -const ClientInfo$json = { - '1': 'ClientInfo', - '2': [ - {'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'}, - { - '1': 'description', - '3': 2, - '4': 1, - '5': 9, - '9': 0, - '10': 'description', - '17': true - }, - { - '1': 'version', - '3': 3, - '4': 1, - '5': 9, - '9': 1, - '10': 'version', - '17': true - }, - ], - '8': [ - {'1': '_description'}, - {'1': '_version'}, - ], -}; - -/// Descriptor for `ClientInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List clientInfoDescriptor = $convert.base64Decode( - 'CgpDbGllbnRJbmZvEhIKBG5hbWUYASABKAlSBG5hbWUSJQoLZGVzY3JpcHRpb24YAiABKAlIAF' - 'ILZGVzY3JpcHRpb26IAQESHQoHdmVyc2lvbhgDIAEoCUgBUgd2ZXJzaW9uiAEBQg4KDF9kZXNj' - 'cmlwdGlvbkIKCghfdmVyc2lvbg=='); +// This is a generated file - do not edit. +// +// Generated from shared/client.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use clientInfoDescriptor instead') +const ClientInfo$json = { + '1': 'ClientInfo', + '2': [ + {'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'}, + { + '1': 'description', + '3': 2, + '4': 1, + '5': 9, + '9': 0, + '10': 'description', + '17': true + }, + { + '1': 'version', + '3': 3, + '4': 1, + '5': 9, + '9': 1, + '10': 'version', + '17': true + }, + ], + '8': [ + {'1': '_description'}, + {'1': '_version'}, + ], +}; + +/// Descriptor for `ClientInfo`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List clientInfoDescriptor = $convert.base64Decode( + 'CgpDbGllbnRJbmZvEhIKBG5hbWUYASABKAlSBG5hbWUSJQoLZGVzY3JpcHRpb24YAiABKAlIAF' + 'ILZGVzY3JpcHRpb26IAQESHQoHdmVyc2lvbhgDIAEoCUgBUgd2ZXJzaW9uiAEBQg4KDF9kZXNj' + 'cmlwdGlvbkIKCghfdmVyc2lvbg=='); diff --git a/useragent/lib/proto/shared/evm.pb.dart b/useragent/lib/proto/shared/evm.pb.dart index cf2b7f9..e36b4b9 100644 --- a/useragent/lib/proto/shared/evm.pb.dart +++ b/useragent/lib/proto/shared/evm.pb.dart @@ -1,945 +1,945 @@ -// This is a generated file - do not edit. -// -// Generated from shared/evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:fixnum/fixnum.dart' as $fixnum; -import 'package:protobuf/protobuf.dart' as $pb; -import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $0; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -class EtherTransferMeaning extends $pb.GeneratedMessage { - factory EtherTransferMeaning({ - $core.List<$core.int>? to, - $core.List<$core.int>? value, - }) { - final result = create(); - if (to != null) result.to = to; - if (value != null) result.value = value; - return result; - } - - EtherTransferMeaning._(); - - factory EtherTransferMeaning.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EtherTransferMeaning.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EtherTransferMeaning', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'to', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EtherTransferMeaning clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EtherTransferMeaning copyWith(void Function(EtherTransferMeaning) updates) => - super.copyWith((message) => updates(message as EtherTransferMeaning)) - as EtherTransferMeaning; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EtherTransferMeaning create() => EtherTransferMeaning._(); - @$core.override - EtherTransferMeaning createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EtherTransferMeaning getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EtherTransferMeaning? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get to => $_getN(0); - @$pb.TagNumber(1) - set to($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasTo() => $_has(0); - @$pb.TagNumber(1) - void clearTo() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get value => $_getN(1); - @$pb.TagNumber(2) - set value($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasValue() => $_has(1); - @$pb.TagNumber(2) - void clearValue() => $_clearField(2); -} - -class TokenInfo extends $pb.GeneratedMessage { - factory TokenInfo({ - $core.String? symbol, - $core.List<$core.int>? address, - $fixnum.Int64? chainId, - }) { - final result = create(); - if (symbol != null) result.symbol = symbol; - if (address != null) result.address = address; - if (chainId != null) result.chainId = chainId; - return result; - } - - TokenInfo._(); - - factory TokenInfo.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory TokenInfo.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'TokenInfo', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), - createEmptyInstance: create) - ..aOS(1, _omitFieldNames ? '' : 'symbol') - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'address', $pb.PbFieldType.OY) - ..a<$fixnum.Int64>(3, _omitFieldNames ? '' : 'chainId', $pb.PbFieldType.OU6, - defaultOrMaker: $fixnum.Int64.ZERO) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - TokenInfo clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - TokenInfo copyWith(void Function(TokenInfo) updates) => - super.copyWith((message) => updates(message as TokenInfo)) as TokenInfo; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static TokenInfo create() => TokenInfo._(); - @$core.override - TokenInfo createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static TokenInfo getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static TokenInfo? _defaultInstance; - - @$pb.TagNumber(1) - $core.String get symbol => $_getSZ(0); - @$pb.TagNumber(1) - set symbol($core.String value) => $_setString(0, value); - @$pb.TagNumber(1) - $core.bool hasSymbol() => $_has(0); - @$pb.TagNumber(1) - void clearSymbol() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get address => $_getN(1); - @$pb.TagNumber(2) - set address($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasAddress() => $_has(1); - @$pb.TagNumber(2) - void clearAddress() => $_clearField(2); - - @$pb.TagNumber(3) - $fixnum.Int64 get chainId => $_getI64(2); - @$pb.TagNumber(3) - set chainId($fixnum.Int64 value) => $_setInt64(2, value); - @$pb.TagNumber(3) - $core.bool hasChainId() => $_has(2); - @$pb.TagNumber(3) - void clearChainId() => $_clearField(3); -} - -/// Mirror of token_transfers::Meaning -class TokenTransferMeaning extends $pb.GeneratedMessage { - factory TokenTransferMeaning({ - TokenInfo? token, - $core.List<$core.int>? to, - $core.List<$core.int>? value, - }) { - final result = create(); - if (token != null) result.token = token; - if (to != null) result.to = to; - if (value != null) result.value = value; - return result; - } - - TokenTransferMeaning._(); - - factory TokenTransferMeaning.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory TokenTransferMeaning.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'TokenTransferMeaning', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), - createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'token', - subBuilder: TokenInfo.create) - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'to', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 3, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - TokenTransferMeaning clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - TokenTransferMeaning copyWith(void Function(TokenTransferMeaning) updates) => - super.copyWith((message) => updates(message as TokenTransferMeaning)) - as TokenTransferMeaning; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static TokenTransferMeaning create() => TokenTransferMeaning._(); - @$core.override - TokenTransferMeaning createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static TokenTransferMeaning getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static TokenTransferMeaning? _defaultInstance; - - @$pb.TagNumber(1) - TokenInfo get token => $_getN(0); - @$pb.TagNumber(1) - set token(TokenInfo value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasToken() => $_has(0); - @$pb.TagNumber(1) - void clearToken() => $_clearField(1); - @$pb.TagNumber(1) - TokenInfo ensureToken() => $_ensure(0); - - @$pb.TagNumber(2) - $core.List<$core.int> get to => $_getN(1); - @$pb.TagNumber(2) - set to($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasTo() => $_has(1); - @$pb.TagNumber(2) - void clearTo() => $_clearField(2); - - @$pb.TagNumber(3) - $core.List<$core.int> get value => $_getN(2); - @$pb.TagNumber(3) - set value($core.List<$core.int> value) => $_setBytes(2, value); - @$pb.TagNumber(3) - $core.bool hasValue() => $_has(2); - @$pb.TagNumber(3) - void clearValue() => $_clearField(3); -} - -enum SpecificMeaning_Meaning { etherTransfer, tokenTransfer, notSet } - -/// Mirror of policies::SpecificMeaning -class SpecificMeaning extends $pb.GeneratedMessage { - factory SpecificMeaning({ - EtherTransferMeaning? etherTransfer, - TokenTransferMeaning? tokenTransfer, - }) { - final result = create(); - if (etherTransfer != null) result.etherTransfer = etherTransfer; - if (tokenTransfer != null) result.tokenTransfer = tokenTransfer; - return result; - } - - SpecificMeaning._(); - - factory SpecificMeaning.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory SpecificMeaning.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, SpecificMeaning_Meaning> - _SpecificMeaning_MeaningByTag = { - 1: SpecificMeaning_Meaning.etherTransfer, - 2: SpecificMeaning_Meaning.tokenTransfer, - 0: SpecificMeaning_Meaning.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'SpecificMeaning', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'etherTransfer', - subBuilder: EtherTransferMeaning.create) - ..aOM(2, _omitFieldNames ? '' : 'tokenTransfer', - subBuilder: TokenTransferMeaning.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - SpecificMeaning clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - SpecificMeaning copyWith(void Function(SpecificMeaning) updates) => - super.copyWith((message) => updates(message as SpecificMeaning)) - as SpecificMeaning; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static SpecificMeaning create() => SpecificMeaning._(); - @$core.override - SpecificMeaning createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static SpecificMeaning getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static SpecificMeaning? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - SpecificMeaning_Meaning whichMeaning() => - _SpecificMeaning_MeaningByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearMeaning() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - EtherTransferMeaning get etherTransfer => $_getN(0); - @$pb.TagNumber(1) - set etherTransfer(EtherTransferMeaning value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasEtherTransfer() => $_has(0); - @$pb.TagNumber(1) - void clearEtherTransfer() => $_clearField(1); - @$pb.TagNumber(1) - EtherTransferMeaning ensureEtherTransfer() => $_ensure(0); - - @$pb.TagNumber(2) - TokenTransferMeaning get tokenTransfer => $_getN(1); - @$pb.TagNumber(2) - set tokenTransfer(TokenTransferMeaning value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasTokenTransfer() => $_has(1); - @$pb.TagNumber(2) - void clearTokenTransfer() => $_clearField(2); - @$pb.TagNumber(2) - TokenTransferMeaning ensureTokenTransfer() => $_ensure(1); -} - -class GasLimitExceededViolation extends $pb.GeneratedMessage { - factory GasLimitExceededViolation({ - $core.List<$core.int>? maxGasFeePerGas, - $core.List<$core.int>? maxPriorityFeePerGas, - }) { - final result = create(); - if (maxGasFeePerGas != null) result.maxGasFeePerGas = maxGasFeePerGas; - if (maxPriorityFeePerGas != null) - result.maxPriorityFeePerGas = maxPriorityFeePerGas; - return result; - } - - GasLimitExceededViolation._(); - - factory GasLimitExceededViolation.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory GasLimitExceededViolation.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'GasLimitExceededViolation', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'maxGasFeePerGas', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'maxPriorityFeePerGas', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - GasLimitExceededViolation clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - GasLimitExceededViolation copyWith( - void Function(GasLimitExceededViolation) updates) => - super.copyWith((message) => updates(message as GasLimitExceededViolation)) - as GasLimitExceededViolation; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static GasLimitExceededViolation create() => GasLimitExceededViolation._(); - @$core.override - GasLimitExceededViolation createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static GasLimitExceededViolation getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static GasLimitExceededViolation? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get maxGasFeePerGas => $_getN(0); - @$pb.TagNumber(1) - set maxGasFeePerGas($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasMaxGasFeePerGas() => $_has(0); - @$pb.TagNumber(1) - void clearMaxGasFeePerGas() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get maxPriorityFeePerGas => $_getN(1); - @$pb.TagNumber(2) - set maxPriorityFeePerGas($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasMaxPriorityFeePerGas() => $_has(1); - @$pb.TagNumber(2) - void clearMaxPriorityFeePerGas() => $_clearField(2); -} - -class EvalViolation_ChainIdMismatch extends $pb.GeneratedMessage { - factory EvalViolation_ChainIdMismatch({ - $fixnum.Int64? expected, - $fixnum.Int64? actual, - }) { - final result = create(); - if (expected != null) result.expected = expected; - if (actual != null) result.actual = actual; - return result; - } - - EvalViolation_ChainIdMismatch._(); - - factory EvalViolation_ChainIdMismatch.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvalViolation_ChainIdMismatch.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvalViolation.ChainIdMismatch', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), - createEmptyInstance: create) - ..a<$fixnum.Int64>( - 1, _omitFieldNames ? '' : 'expected', $pb.PbFieldType.OU6, - defaultOrMaker: $fixnum.Int64.ZERO) - ..a<$fixnum.Int64>(2, _omitFieldNames ? '' : 'actual', $pb.PbFieldType.OU6, - defaultOrMaker: $fixnum.Int64.ZERO) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvalViolation_ChainIdMismatch clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvalViolation_ChainIdMismatch copyWith( - void Function(EvalViolation_ChainIdMismatch) updates) => - super.copyWith( - (message) => updates(message as EvalViolation_ChainIdMismatch)) - as EvalViolation_ChainIdMismatch; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvalViolation_ChainIdMismatch create() => - EvalViolation_ChainIdMismatch._(); - @$core.override - EvalViolation_ChainIdMismatch createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvalViolation_ChainIdMismatch getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvalViolation_ChainIdMismatch? _defaultInstance; - - @$pb.TagNumber(1) - $fixnum.Int64 get expected => $_getI64(0); - @$pb.TagNumber(1) - set expected($fixnum.Int64 value) => $_setInt64(0, value); - @$pb.TagNumber(1) - $core.bool hasExpected() => $_has(0); - @$pb.TagNumber(1) - void clearExpected() => $_clearField(1); - - @$pb.TagNumber(2) - $fixnum.Int64 get actual => $_getI64(1); - @$pb.TagNumber(2) - set actual($fixnum.Int64 value) => $_setInt64(1, value); - @$pb.TagNumber(2) - $core.bool hasActual() => $_has(1); - @$pb.TagNumber(2) - void clearActual() => $_clearField(2); -} - -enum EvalViolation_Kind { - invalidTarget, - gasLimitExceeded, - rateLimitExceeded, - volumetricLimitExceeded, - invalidTime, - invalidTransactionType, - chainIdMismatch, - notSet -} - -class EvalViolation extends $pb.GeneratedMessage { - factory EvalViolation({ - $core.List<$core.int>? invalidTarget, - GasLimitExceededViolation? gasLimitExceeded, - $0.Empty? rateLimitExceeded, - $0.Empty? volumetricLimitExceeded, - $0.Empty? invalidTime, - $0.Empty? invalidTransactionType, - EvalViolation_ChainIdMismatch? chainIdMismatch, - }) { - final result = create(); - if (invalidTarget != null) result.invalidTarget = invalidTarget; - if (gasLimitExceeded != null) result.gasLimitExceeded = gasLimitExceeded; - if (rateLimitExceeded != null) result.rateLimitExceeded = rateLimitExceeded; - if (volumetricLimitExceeded != null) - result.volumetricLimitExceeded = volumetricLimitExceeded; - if (invalidTime != null) result.invalidTime = invalidTime; - if (invalidTransactionType != null) - result.invalidTransactionType = invalidTransactionType; - if (chainIdMismatch != null) result.chainIdMismatch = chainIdMismatch; - return result; - } - - EvalViolation._(); - - factory EvalViolation.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory EvalViolation.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, EvalViolation_Kind> - _EvalViolation_KindByTag = { - 1: EvalViolation_Kind.invalidTarget, - 2: EvalViolation_Kind.gasLimitExceeded, - 3: EvalViolation_Kind.rateLimitExceeded, - 4: EvalViolation_Kind.volumetricLimitExceeded, - 5: EvalViolation_Kind.invalidTime, - 6: EvalViolation_Kind.invalidTransactionType, - 7: EvalViolation_Kind.chainIdMismatch, - 0: EvalViolation_Kind.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'EvalViolation', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4, 5, 6, 7]) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'invalidTarget', $pb.PbFieldType.OY) - ..aOM( - 2, _omitFieldNames ? '' : 'gasLimitExceeded', - subBuilder: GasLimitExceededViolation.create) - ..aOM<$0.Empty>(3, _omitFieldNames ? '' : 'rateLimitExceeded', - subBuilder: $0.Empty.create) - ..aOM<$0.Empty>(4, _omitFieldNames ? '' : 'volumetricLimitExceeded', - subBuilder: $0.Empty.create) - ..aOM<$0.Empty>(5, _omitFieldNames ? '' : 'invalidTime', - subBuilder: $0.Empty.create) - ..aOM<$0.Empty>(6, _omitFieldNames ? '' : 'invalidTransactionType', - subBuilder: $0.Empty.create) - ..aOM( - 7, _omitFieldNames ? '' : 'chainIdMismatch', - subBuilder: EvalViolation_ChainIdMismatch.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvalViolation clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - EvalViolation copyWith(void Function(EvalViolation) updates) => - super.copyWith((message) => updates(message as EvalViolation)) - as EvalViolation; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static EvalViolation create() => EvalViolation._(); - @$core.override - EvalViolation createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static EvalViolation getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static EvalViolation? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - @$pb.TagNumber(5) - @$pb.TagNumber(6) - @$pb.TagNumber(7) - EvalViolation_Kind whichKind() => _EvalViolation_KindByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - @$pb.TagNumber(5) - @$pb.TagNumber(6) - @$pb.TagNumber(7) - void clearKind() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $core.List<$core.int> get invalidTarget => $_getN(0); - @$pb.TagNumber(1) - set invalidTarget($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasInvalidTarget() => $_has(0); - @$pb.TagNumber(1) - void clearInvalidTarget() => $_clearField(1); - - @$pb.TagNumber(2) - GasLimitExceededViolation get gasLimitExceeded => $_getN(1); - @$pb.TagNumber(2) - set gasLimitExceeded(GasLimitExceededViolation value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasGasLimitExceeded() => $_has(1); - @$pb.TagNumber(2) - void clearGasLimitExceeded() => $_clearField(2); - @$pb.TagNumber(2) - GasLimitExceededViolation ensureGasLimitExceeded() => $_ensure(1); - - @$pb.TagNumber(3) - $0.Empty get rateLimitExceeded => $_getN(2); - @$pb.TagNumber(3) - set rateLimitExceeded($0.Empty value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasRateLimitExceeded() => $_has(2); - @$pb.TagNumber(3) - void clearRateLimitExceeded() => $_clearField(3); - @$pb.TagNumber(3) - $0.Empty ensureRateLimitExceeded() => $_ensure(2); - - @$pb.TagNumber(4) - $0.Empty get volumetricLimitExceeded => $_getN(3); - @$pb.TagNumber(4) - set volumetricLimitExceeded($0.Empty value) => $_setField(4, value); - @$pb.TagNumber(4) - $core.bool hasVolumetricLimitExceeded() => $_has(3); - @$pb.TagNumber(4) - void clearVolumetricLimitExceeded() => $_clearField(4); - @$pb.TagNumber(4) - $0.Empty ensureVolumetricLimitExceeded() => $_ensure(3); - - @$pb.TagNumber(5) - $0.Empty get invalidTime => $_getN(4); - @$pb.TagNumber(5) - set invalidTime($0.Empty value) => $_setField(5, value); - @$pb.TagNumber(5) - $core.bool hasInvalidTime() => $_has(4); - @$pb.TagNumber(5) - void clearInvalidTime() => $_clearField(5); - @$pb.TagNumber(5) - $0.Empty ensureInvalidTime() => $_ensure(4); - - @$pb.TagNumber(6) - $0.Empty get invalidTransactionType => $_getN(5); - @$pb.TagNumber(6) - set invalidTransactionType($0.Empty value) => $_setField(6, value); - @$pb.TagNumber(6) - $core.bool hasInvalidTransactionType() => $_has(5); - @$pb.TagNumber(6) - void clearInvalidTransactionType() => $_clearField(6); - @$pb.TagNumber(6) - $0.Empty ensureInvalidTransactionType() => $_ensure(5); - - @$pb.TagNumber(7) - EvalViolation_ChainIdMismatch get chainIdMismatch => $_getN(6); - @$pb.TagNumber(7) - set chainIdMismatch(EvalViolation_ChainIdMismatch value) => - $_setField(7, value); - @$pb.TagNumber(7) - $core.bool hasChainIdMismatch() => $_has(6); - @$pb.TagNumber(7) - void clearChainIdMismatch() => $_clearField(7); - @$pb.TagNumber(7) - EvalViolation_ChainIdMismatch ensureChainIdMismatch() => $_ensure(6); -} - -/// Transaction was classified but no grant covers it -class NoMatchingGrantError extends $pb.GeneratedMessage { - factory NoMatchingGrantError({ - SpecificMeaning? meaning, - }) { - final result = create(); - if (meaning != null) result.meaning = meaning; - return result; - } - - NoMatchingGrantError._(); - - factory NoMatchingGrantError.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory NoMatchingGrantError.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'NoMatchingGrantError', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), - createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'meaning', - subBuilder: SpecificMeaning.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - NoMatchingGrantError clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - NoMatchingGrantError copyWith(void Function(NoMatchingGrantError) updates) => - super.copyWith((message) => updates(message as NoMatchingGrantError)) - as NoMatchingGrantError; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static NoMatchingGrantError create() => NoMatchingGrantError._(); - @$core.override - NoMatchingGrantError createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static NoMatchingGrantError getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static NoMatchingGrantError? _defaultInstance; - - @$pb.TagNumber(1) - SpecificMeaning get meaning => $_getN(0); - @$pb.TagNumber(1) - set meaning(SpecificMeaning value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasMeaning() => $_has(0); - @$pb.TagNumber(1) - void clearMeaning() => $_clearField(1); - @$pb.TagNumber(1) - SpecificMeaning ensureMeaning() => $_ensure(0); -} - -/// Transaction was classified and a grant was found, but constraints were violated -class PolicyViolationsError extends $pb.GeneratedMessage { - factory PolicyViolationsError({ - SpecificMeaning? meaning, - $core.Iterable? violations, - }) { - final result = create(); - if (meaning != null) result.meaning = meaning; - if (violations != null) result.violations.addAll(violations); - return result; - } - - PolicyViolationsError._(); - - factory PolicyViolationsError.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory PolicyViolationsError.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'PolicyViolationsError', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), - createEmptyInstance: create) - ..aOM(1, _omitFieldNames ? '' : 'meaning', - subBuilder: SpecificMeaning.create) - ..pPM(2, _omitFieldNames ? '' : 'violations', - subBuilder: EvalViolation.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - PolicyViolationsError clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - PolicyViolationsError copyWith( - void Function(PolicyViolationsError) updates) => - super.copyWith((message) => updates(message as PolicyViolationsError)) - as PolicyViolationsError; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static PolicyViolationsError create() => PolicyViolationsError._(); - @$core.override - PolicyViolationsError createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static PolicyViolationsError getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static PolicyViolationsError? _defaultInstance; - - @$pb.TagNumber(1) - SpecificMeaning get meaning => $_getN(0); - @$pb.TagNumber(1) - set meaning(SpecificMeaning value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasMeaning() => $_has(0); - @$pb.TagNumber(1) - void clearMeaning() => $_clearField(1); - @$pb.TagNumber(1) - SpecificMeaning ensureMeaning() => $_ensure(0); - - @$pb.TagNumber(2) - $pb.PbList get violations => $_getList(1); -} - -enum TransactionEvalError_Kind { - contractCreationNotSupported, - unsupportedTransactionType, - noMatchingGrant, - policyViolations, - notSet -} - -/// top-level error returned when transaction evaluation fails -class TransactionEvalError extends $pb.GeneratedMessage { - factory TransactionEvalError({ - $0.Empty? contractCreationNotSupported, - $0.Empty? unsupportedTransactionType, - NoMatchingGrantError? noMatchingGrant, - PolicyViolationsError? policyViolations, - }) { - final result = create(); - if (contractCreationNotSupported != null) - result.contractCreationNotSupported = contractCreationNotSupported; - if (unsupportedTransactionType != null) - result.unsupportedTransactionType = unsupportedTransactionType; - if (noMatchingGrant != null) result.noMatchingGrant = noMatchingGrant; - if (policyViolations != null) result.policyViolations = policyViolations; - return result; - } - - TransactionEvalError._(); - - factory TransactionEvalError.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory TransactionEvalError.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, TransactionEvalError_Kind> - _TransactionEvalError_KindByTag = { - 1: TransactionEvalError_Kind.contractCreationNotSupported, - 2: TransactionEvalError_Kind.unsupportedTransactionType, - 3: TransactionEvalError_Kind.noMatchingGrant, - 4: TransactionEvalError_Kind.policyViolations, - 0: TransactionEvalError_Kind.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'TransactionEvalError', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4]) - ..aOM<$0.Empty>(1, _omitFieldNames ? '' : 'contractCreationNotSupported', - subBuilder: $0.Empty.create) - ..aOM<$0.Empty>(2, _omitFieldNames ? '' : 'unsupportedTransactionType', - subBuilder: $0.Empty.create) - ..aOM(3, _omitFieldNames ? '' : 'noMatchingGrant', - subBuilder: NoMatchingGrantError.create) - ..aOM(4, _omitFieldNames ? '' : 'policyViolations', - subBuilder: PolicyViolationsError.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - TransactionEvalError clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - TransactionEvalError copyWith(void Function(TransactionEvalError) updates) => - super.copyWith((message) => updates(message as TransactionEvalError)) - as TransactionEvalError; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static TransactionEvalError create() => TransactionEvalError._(); - @$core.override - TransactionEvalError createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static TransactionEvalError getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static TransactionEvalError? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - TransactionEvalError_Kind whichKind() => - _TransactionEvalError_KindByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - void clearKind() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $0.Empty get contractCreationNotSupported => $_getN(0); - @$pb.TagNumber(1) - set contractCreationNotSupported($0.Empty value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasContractCreationNotSupported() => $_has(0); - @$pb.TagNumber(1) - void clearContractCreationNotSupported() => $_clearField(1); - @$pb.TagNumber(1) - $0.Empty ensureContractCreationNotSupported() => $_ensure(0); - - @$pb.TagNumber(2) - $0.Empty get unsupportedTransactionType => $_getN(1); - @$pb.TagNumber(2) - set unsupportedTransactionType($0.Empty value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasUnsupportedTransactionType() => $_has(1); - @$pb.TagNumber(2) - void clearUnsupportedTransactionType() => $_clearField(2); - @$pb.TagNumber(2) - $0.Empty ensureUnsupportedTransactionType() => $_ensure(1); - - @$pb.TagNumber(3) - NoMatchingGrantError get noMatchingGrant => $_getN(2); - @$pb.TagNumber(3) - set noMatchingGrant(NoMatchingGrantError value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasNoMatchingGrant() => $_has(2); - @$pb.TagNumber(3) - void clearNoMatchingGrant() => $_clearField(3); - @$pb.TagNumber(3) - NoMatchingGrantError ensureNoMatchingGrant() => $_ensure(2); - - @$pb.TagNumber(4) - PolicyViolationsError get policyViolations => $_getN(3); - @$pb.TagNumber(4) - set policyViolations(PolicyViolationsError value) => $_setField(4, value); - @$pb.TagNumber(4) - $core.bool hasPolicyViolations() => $_has(3); - @$pb.TagNumber(4) - void clearPolicyViolations() => $_clearField(4); - @$pb.TagNumber(4) - PolicyViolationsError ensurePolicyViolations() => $_ensure(3); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from shared/evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $0; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +class EtherTransferMeaning extends $pb.GeneratedMessage { + factory EtherTransferMeaning({ + $core.List<$core.int>? to, + $core.List<$core.int>? value, + }) { + final result = create(); + if (to != null) result.to = to; + if (value != null) result.value = value; + return result; + } + + EtherTransferMeaning._(); + + factory EtherTransferMeaning.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EtherTransferMeaning.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EtherTransferMeaning', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'to', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EtherTransferMeaning clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EtherTransferMeaning copyWith(void Function(EtherTransferMeaning) updates) => + super.copyWith((message) => updates(message as EtherTransferMeaning)) + as EtherTransferMeaning; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EtherTransferMeaning create() => EtherTransferMeaning._(); + @$core.override + EtherTransferMeaning createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EtherTransferMeaning getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EtherTransferMeaning? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get to => $_getN(0); + @$pb.TagNumber(1) + set to($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasTo() => $_has(0); + @$pb.TagNumber(1) + void clearTo() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get value => $_getN(1); + @$pb.TagNumber(2) + set value($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasValue() => $_has(1); + @$pb.TagNumber(2) + void clearValue() => $_clearField(2); +} + +class TokenInfo extends $pb.GeneratedMessage { + factory TokenInfo({ + $core.String? symbol, + $core.List<$core.int>? address, + $fixnum.Int64? chainId, + }) { + final result = create(); + if (symbol != null) result.symbol = symbol; + if (address != null) result.address = address; + if (chainId != null) result.chainId = chainId; + return result; + } + + TokenInfo._(); + + factory TokenInfo.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory TokenInfo.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'TokenInfo', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), + createEmptyInstance: create) + ..aOS(1, _omitFieldNames ? '' : 'symbol') + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'address', $pb.PbFieldType.OY) + ..a<$fixnum.Int64>(3, _omitFieldNames ? '' : 'chainId', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TokenInfo clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TokenInfo copyWith(void Function(TokenInfo) updates) => + super.copyWith((message) => updates(message as TokenInfo)) as TokenInfo; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static TokenInfo create() => TokenInfo._(); + @$core.override + TokenInfo createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static TokenInfo getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static TokenInfo? _defaultInstance; + + @$pb.TagNumber(1) + $core.String get symbol => $_getSZ(0); + @$pb.TagNumber(1) + set symbol($core.String value) => $_setString(0, value); + @$pb.TagNumber(1) + $core.bool hasSymbol() => $_has(0); + @$pb.TagNumber(1) + void clearSymbol() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get address => $_getN(1); + @$pb.TagNumber(2) + set address($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasAddress() => $_has(1); + @$pb.TagNumber(2) + void clearAddress() => $_clearField(2); + + @$pb.TagNumber(3) + $fixnum.Int64 get chainId => $_getI64(2); + @$pb.TagNumber(3) + set chainId($fixnum.Int64 value) => $_setInt64(2, value); + @$pb.TagNumber(3) + $core.bool hasChainId() => $_has(2); + @$pb.TagNumber(3) + void clearChainId() => $_clearField(3); +} + +/// Mirror of token_transfers::Meaning +class TokenTransferMeaning extends $pb.GeneratedMessage { + factory TokenTransferMeaning({ + TokenInfo? token, + $core.List<$core.int>? to, + $core.List<$core.int>? value, + }) { + final result = create(); + if (token != null) result.token = token; + if (to != null) result.to = to; + if (value != null) result.value = value; + return result; + } + + TokenTransferMeaning._(); + + factory TokenTransferMeaning.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory TokenTransferMeaning.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'TokenTransferMeaning', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), + createEmptyInstance: create) + ..aOM(1, _omitFieldNames ? '' : 'token', + subBuilder: TokenInfo.create) + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'to', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 3, _omitFieldNames ? '' : 'value', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TokenTransferMeaning clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TokenTransferMeaning copyWith(void Function(TokenTransferMeaning) updates) => + super.copyWith((message) => updates(message as TokenTransferMeaning)) + as TokenTransferMeaning; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static TokenTransferMeaning create() => TokenTransferMeaning._(); + @$core.override + TokenTransferMeaning createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static TokenTransferMeaning getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static TokenTransferMeaning? _defaultInstance; + + @$pb.TagNumber(1) + TokenInfo get token => $_getN(0); + @$pb.TagNumber(1) + set token(TokenInfo value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasToken() => $_has(0); + @$pb.TagNumber(1) + void clearToken() => $_clearField(1); + @$pb.TagNumber(1) + TokenInfo ensureToken() => $_ensure(0); + + @$pb.TagNumber(2) + $core.List<$core.int> get to => $_getN(1); + @$pb.TagNumber(2) + set to($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasTo() => $_has(1); + @$pb.TagNumber(2) + void clearTo() => $_clearField(2); + + @$pb.TagNumber(3) + $core.List<$core.int> get value => $_getN(2); + @$pb.TagNumber(3) + set value($core.List<$core.int> value) => $_setBytes(2, value); + @$pb.TagNumber(3) + $core.bool hasValue() => $_has(2); + @$pb.TagNumber(3) + void clearValue() => $_clearField(3); +} + +enum SpecificMeaning_Meaning { etherTransfer, tokenTransfer, notSet } + +/// Mirror of policies::SpecificMeaning +class SpecificMeaning extends $pb.GeneratedMessage { + factory SpecificMeaning({ + EtherTransferMeaning? etherTransfer, + TokenTransferMeaning? tokenTransfer, + }) { + final result = create(); + if (etherTransfer != null) result.etherTransfer = etherTransfer; + if (tokenTransfer != null) result.tokenTransfer = tokenTransfer; + return result; + } + + SpecificMeaning._(); + + factory SpecificMeaning.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory SpecificMeaning.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, SpecificMeaning_Meaning> + _SpecificMeaning_MeaningByTag = { + 1: SpecificMeaning_Meaning.etherTransfer, + 2: SpecificMeaning_Meaning.tokenTransfer, + 0: SpecificMeaning_Meaning.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'SpecificMeaning', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'etherTransfer', + subBuilder: EtherTransferMeaning.create) + ..aOM(2, _omitFieldNames ? '' : 'tokenTransfer', + subBuilder: TokenTransferMeaning.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + SpecificMeaning clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + SpecificMeaning copyWith(void Function(SpecificMeaning) updates) => + super.copyWith((message) => updates(message as SpecificMeaning)) + as SpecificMeaning; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static SpecificMeaning create() => SpecificMeaning._(); + @$core.override + SpecificMeaning createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static SpecificMeaning getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static SpecificMeaning? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + SpecificMeaning_Meaning whichMeaning() => + _SpecificMeaning_MeaningByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearMeaning() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + EtherTransferMeaning get etherTransfer => $_getN(0); + @$pb.TagNumber(1) + set etherTransfer(EtherTransferMeaning value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasEtherTransfer() => $_has(0); + @$pb.TagNumber(1) + void clearEtherTransfer() => $_clearField(1); + @$pb.TagNumber(1) + EtherTransferMeaning ensureEtherTransfer() => $_ensure(0); + + @$pb.TagNumber(2) + TokenTransferMeaning get tokenTransfer => $_getN(1); + @$pb.TagNumber(2) + set tokenTransfer(TokenTransferMeaning value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasTokenTransfer() => $_has(1); + @$pb.TagNumber(2) + void clearTokenTransfer() => $_clearField(2); + @$pb.TagNumber(2) + TokenTransferMeaning ensureTokenTransfer() => $_ensure(1); +} + +class GasLimitExceededViolation extends $pb.GeneratedMessage { + factory GasLimitExceededViolation({ + $core.List<$core.int>? maxGasFeePerGas, + $core.List<$core.int>? maxPriorityFeePerGas, + }) { + final result = create(); + if (maxGasFeePerGas != null) result.maxGasFeePerGas = maxGasFeePerGas; + if (maxPriorityFeePerGas != null) + result.maxPriorityFeePerGas = maxPriorityFeePerGas; + return result; + } + + GasLimitExceededViolation._(); + + factory GasLimitExceededViolation.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory GasLimitExceededViolation.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'GasLimitExceededViolation', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'maxGasFeePerGas', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'maxPriorityFeePerGas', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + GasLimitExceededViolation clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + GasLimitExceededViolation copyWith( + void Function(GasLimitExceededViolation) updates) => + super.copyWith((message) => updates(message as GasLimitExceededViolation)) + as GasLimitExceededViolation; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static GasLimitExceededViolation create() => GasLimitExceededViolation._(); + @$core.override + GasLimitExceededViolation createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static GasLimitExceededViolation getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static GasLimitExceededViolation? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get maxGasFeePerGas => $_getN(0); + @$pb.TagNumber(1) + set maxGasFeePerGas($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasMaxGasFeePerGas() => $_has(0); + @$pb.TagNumber(1) + void clearMaxGasFeePerGas() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get maxPriorityFeePerGas => $_getN(1); + @$pb.TagNumber(2) + set maxPriorityFeePerGas($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasMaxPriorityFeePerGas() => $_has(1); + @$pb.TagNumber(2) + void clearMaxPriorityFeePerGas() => $_clearField(2); +} + +class EvalViolation_ChainIdMismatch extends $pb.GeneratedMessage { + factory EvalViolation_ChainIdMismatch({ + $fixnum.Int64? expected, + $fixnum.Int64? actual, + }) { + final result = create(); + if (expected != null) result.expected = expected; + if (actual != null) result.actual = actual; + return result; + } + + EvalViolation_ChainIdMismatch._(); + + factory EvalViolation_ChainIdMismatch.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvalViolation_ChainIdMismatch.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvalViolation.ChainIdMismatch', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), + createEmptyInstance: create) + ..a<$fixnum.Int64>( + 1, _omitFieldNames ? '' : 'expected', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..a<$fixnum.Int64>(2, _omitFieldNames ? '' : 'actual', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvalViolation_ChainIdMismatch clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvalViolation_ChainIdMismatch copyWith( + void Function(EvalViolation_ChainIdMismatch) updates) => + super.copyWith( + (message) => updates(message as EvalViolation_ChainIdMismatch)) + as EvalViolation_ChainIdMismatch; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvalViolation_ChainIdMismatch create() => + EvalViolation_ChainIdMismatch._(); + @$core.override + EvalViolation_ChainIdMismatch createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvalViolation_ChainIdMismatch getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvalViolation_ChainIdMismatch? _defaultInstance; + + @$pb.TagNumber(1) + $fixnum.Int64 get expected => $_getI64(0); + @$pb.TagNumber(1) + set expected($fixnum.Int64 value) => $_setInt64(0, value); + @$pb.TagNumber(1) + $core.bool hasExpected() => $_has(0); + @$pb.TagNumber(1) + void clearExpected() => $_clearField(1); + + @$pb.TagNumber(2) + $fixnum.Int64 get actual => $_getI64(1); + @$pb.TagNumber(2) + set actual($fixnum.Int64 value) => $_setInt64(1, value); + @$pb.TagNumber(2) + $core.bool hasActual() => $_has(1); + @$pb.TagNumber(2) + void clearActual() => $_clearField(2); +} + +enum EvalViolation_Kind { + invalidTarget, + gasLimitExceeded, + rateLimitExceeded, + volumetricLimitExceeded, + invalidTime, + invalidTransactionType, + chainIdMismatch, + notSet +} + +class EvalViolation extends $pb.GeneratedMessage { + factory EvalViolation({ + $core.List<$core.int>? invalidTarget, + GasLimitExceededViolation? gasLimitExceeded, + $0.Empty? rateLimitExceeded, + $0.Empty? volumetricLimitExceeded, + $0.Empty? invalidTime, + $0.Empty? invalidTransactionType, + EvalViolation_ChainIdMismatch? chainIdMismatch, + }) { + final result = create(); + if (invalidTarget != null) result.invalidTarget = invalidTarget; + if (gasLimitExceeded != null) result.gasLimitExceeded = gasLimitExceeded; + if (rateLimitExceeded != null) result.rateLimitExceeded = rateLimitExceeded; + if (volumetricLimitExceeded != null) + result.volumetricLimitExceeded = volumetricLimitExceeded; + if (invalidTime != null) result.invalidTime = invalidTime; + if (invalidTransactionType != null) + result.invalidTransactionType = invalidTransactionType; + if (chainIdMismatch != null) result.chainIdMismatch = chainIdMismatch; + return result; + } + + EvalViolation._(); + + factory EvalViolation.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory EvalViolation.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, EvalViolation_Kind> + _EvalViolation_KindByTag = { + 1: EvalViolation_Kind.invalidTarget, + 2: EvalViolation_Kind.gasLimitExceeded, + 3: EvalViolation_Kind.rateLimitExceeded, + 4: EvalViolation_Kind.volumetricLimitExceeded, + 5: EvalViolation_Kind.invalidTime, + 6: EvalViolation_Kind.invalidTransactionType, + 7: EvalViolation_Kind.chainIdMismatch, + 0: EvalViolation_Kind.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'EvalViolation', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3, 4, 5, 6, 7]) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'invalidTarget', $pb.PbFieldType.OY) + ..aOM( + 2, _omitFieldNames ? '' : 'gasLimitExceeded', + subBuilder: GasLimitExceededViolation.create) + ..aOM<$0.Empty>(3, _omitFieldNames ? '' : 'rateLimitExceeded', + subBuilder: $0.Empty.create) + ..aOM<$0.Empty>(4, _omitFieldNames ? '' : 'volumetricLimitExceeded', + subBuilder: $0.Empty.create) + ..aOM<$0.Empty>(5, _omitFieldNames ? '' : 'invalidTime', + subBuilder: $0.Empty.create) + ..aOM<$0.Empty>(6, _omitFieldNames ? '' : 'invalidTransactionType', + subBuilder: $0.Empty.create) + ..aOM( + 7, _omitFieldNames ? '' : 'chainIdMismatch', + subBuilder: EvalViolation_ChainIdMismatch.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvalViolation clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + EvalViolation copyWith(void Function(EvalViolation) updates) => + super.copyWith((message) => updates(message as EvalViolation)) + as EvalViolation; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static EvalViolation create() => EvalViolation._(); + @$core.override + EvalViolation createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static EvalViolation getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static EvalViolation? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + @$pb.TagNumber(5) + @$pb.TagNumber(6) + @$pb.TagNumber(7) + EvalViolation_Kind whichKind() => _EvalViolation_KindByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + @$pb.TagNumber(5) + @$pb.TagNumber(6) + @$pb.TagNumber(7) + void clearKind() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $core.List<$core.int> get invalidTarget => $_getN(0); + @$pb.TagNumber(1) + set invalidTarget($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasInvalidTarget() => $_has(0); + @$pb.TagNumber(1) + void clearInvalidTarget() => $_clearField(1); + + @$pb.TagNumber(2) + GasLimitExceededViolation get gasLimitExceeded => $_getN(1); + @$pb.TagNumber(2) + set gasLimitExceeded(GasLimitExceededViolation value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasGasLimitExceeded() => $_has(1); + @$pb.TagNumber(2) + void clearGasLimitExceeded() => $_clearField(2); + @$pb.TagNumber(2) + GasLimitExceededViolation ensureGasLimitExceeded() => $_ensure(1); + + @$pb.TagNumber(3) + $0.Empty get rateLimitExceeded => $_getN(2); + @$pb.TagNumber(3) + set rateLimitExceeded($0.Empty value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasRateLimitExceeded() => $_has(2); + @$pb.TagNumber(3) + void clearRateLimitExceeded() => $_clearField(3); + @$pb.TagNumber(3) + $0.Empty ensureRateLimitExceeded() => $_ensure(2); + + @$pb.TagNumber(4) + $0.Empty get volumetricLimitExceeded => $_getN(3); + @$pb.TagNumber(4) + set volumetricLimitExceeded($0.Empty value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasVolumetricLimitExceeded() => $_has(3); + @$pb.TagNumber(4) + void clearVolumetricLimitExceeded() => $_clearField(4); + @$pb.TagNumber(4) + $0.Empty ensureVolumetricLimitExceeded() => $_ensure(3); + + @$pb.TagNumber(5) + $0.Empty get invalidTime => $_getN(4); + @$pb.TagNumber(5) + set invalidTime($0.Empty value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasInvalidTime() => $_has(4); + @$pb.TagNumber(5) + void clearInvalidTime() => $_clearField(5); + @$pb.TagNumber(5) + $0.Empty ensureInvalidTime() => $_ensure(4); + + @$pb.TagNumber(6) + $0.Empty get invalidTransactionType => $_getN(5); + @$pb.TagNumber(6) + set invalidTransactionType($0.Empty value) => $_setField(6, value); + @$pb.TagNumber(6) + $core.bool hasInvalidTransactionType() => $_has(5); + @$pb.TagNumber(6) + void clearInvalidTransactionType() => $_clearField(6); + @$pb.TagNumber(6) + $0.Empty ensureInvalidTransactionType() => $_ensure(5); + + @$pb.TagNumber(7) + EvalViolation_ChainIdMismatch get chainIdMismatch => $_getN(6); + @$pb.TagNumber(7) + set chainIdMismatch(EvalViolation_ChainIdMismatch value) => + $_setField(7, value); + @$pb.TagNumber(7) + $core.bool hasChainIdMismatch() => $_has(6); + @$pb.TagNumber(7) + void clearChainIdMismatch() => $_clearField(7); + @$pb.TagNumber(7) + EvalViolation_ChainIdMismatch ensureChainIdMismatch() => $_ensure(6); +} + +/// Transaction was classified but no grant covers it +class NoMatchingGrantError extends $pb.GeneratedMessage { + factory NoMatchingGrantError({ + SpecificMeaning? meaning, + }) { + final result = create(); + if (meaning != null) result.meaning = meaning; + return result; + } + + NoMatchingGrantError._(); + + factory NoMatchingGrantError.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory NoMatchingGrantError.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'NoMatchingGrantError', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), + createEmptyInstance: create) + ..aOM(1, _omitFieldNames ? '' : 'meaning', + subBuilder: SpecificMeaning.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + NoMatchingGrantError clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + NoMatchingGrantError copyWith(void Function(NoMatchingGrantError) updates) => + super.copyWith((message) => updates(message as NoMatchingGrantError)) + as NoMatchingGrantError; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static NoMatchingGrantError create() => NoMatchingGrantError._(); + @$core.override + NoMatchingGrantError createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static NoMatchingGrantError getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static NoMatchingGrantError? _defaultInstance; + + @$pb.TagNumber(1) + SpecificMeaning get meaning => $_getN(0); + @$pb.TagNumber(1) + set meaning(SpecificMeaning value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasMeaning() => $_has(0); + @$pb.TagNumber(1) + void clearMeaning() => $_clearField(1); + @$pb.TagNumber(1) + SpecificMeaning ensureMeaning() => $_ensure(0); +} + +/// Transaction was classified and a grant was found, but constraints were violated +class PolicyViolationsError extends $pb.GeneratedMessage { + factory PolicyViolationsError({ + SpecificMeaning? meaning, + $core.Iterable? violations, + }) { + final result = create(); + if (meaning != null) result.meaning = meaning; + if (violations != null) result.violations.addAll(violations); + return result; + } + + PolicyViolationsError._(); + + factory PolicyViolationsError.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory PolicyViolationsError.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'PolicyViolationsError', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), + createEmptyInstance: create) + ..aOM(1, _omitFieldNames ? '' : 'meaning', + subBuilder: SpecificMeaning.create) + ..pPM(2, _omitFieldNames ? '' : 'violations', + subBuilder: EvalViolation.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + PolicyViolationsError clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + PolicyViolationsError copyWith( + void Function(PolicyViolationsError) updates) => + super.copyWith((message) => updates(message as PolicyViolationsError)) + as PolicyViolationsError; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static PolicyViolationsError create() => PolicyViolationsError._(); + @$core.override + PolicyViolationsError createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static PolicyViolationsError getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static PolicyViolationsError? _defaultInstance; + + @$pb.TagNumber(1) + SpecificMeaning get meaning => $_getN(0); + @$pb.TagNumber(1) + set meaning(SpecificMeaning value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasMeaning() => $_has(0); + @$pb.TagNumber(1) + void clearMeaning() => $_clearField(1); + @$pb.TagNumber(1) + SpecificMeaning ensureMeaning() => $_ensure(0); + + @$pb.TagNumber(2) + $pb.PbList get violations => $_getList(1); +} + +enum TransactionEvalError_Kind { + contractCreationNotSupported, + unsupportedTransactionType, + noMatchingGrant, + policyViolations, + notSet +} + +/// top-level error returned when transaction evaluation fails +class TransactionEvalError extends $pb.GeneratedMessage { + factory TransactionEvalError({ + $0.Empty? contractCreationNotSupported, + $0.Empty? unsupportedTransactionType, + NoMatchingGrantError? noMatchingGrant, + PolicyViolationsError? policyViolations, + }) { + final result = create(); + if (contractCreationNotSupported != null) + result.contractCreationNotSupported = contractCreationNotSupported; + if (unsupportedTransactionType != null) + result.unsupportedTransactionType = unsupportedTransactionType; + if (noMatchingGrant != null) result.noMatchingGrant = noMatchingGrant; + if (policyViolations != null) result.policyViolations = policyViolations; + return result; + } + + TransactionEvalError._(); + + factory TransactionEvalError.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory TransactionEvalError.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, TransactionEvalError_Kind> + _TransactionEvalError_KindByTag = { + 1: TransactionEvalError_Kind.contractCreationNotSupported, + 2: TransactionEvalError_Kind.unsupportedTransactionType, + 3: TransactionEvalError_Kind.noMatchingGrant, + 4: TransactionEvalError_Kind.policyViolations, + 0: TransactionEvalError_Kind.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'TransactionEvalError', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.shared.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3, 4]) + ..aOM<$0.Empty>(1, _omitFieldNames ? '' : 'contractCreationNotSupported', + subBuilder: $0.Empty.create) + ..aOM<$0.Empty>(2, _omitFieldNames ? '' : 'unsupportedTransactionType', + subBuilder: $0.Empty.create) + ..aOM(3, _omitFieldNames ? '' : 'noMatchingGrant', + subBuilder: NoMatchingGrantError.create) + ..aOM(4, _omitFieldNames ? '' : 'policyViolations', + subBuilder: PolicyViolationsError.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TransactionEvalError clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + TransactionEvalError copyWith(void Function(TransactionEvalError) updates) => + super.copyWith((message) => updates(message as TransactionEvalError)) + as TransactionEvalError; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static TransactionEvalError create() => TransactionEvalError._(); + @$core.override + TransactionEvalError createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static TransactionEvalError getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static TransactionEvalError? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + TransactionEvalError_Kind whichKind() => + _TransactionEvalError_KindByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + void clearKind() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $0.Empty get contractCreationNotSupported => $_getN(0); + @$pb.TagNumber(1) + set contractCreationNotSupported($0.Empty value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasContractCreationNotSupported() => $_has(0); + @$pb.TagNumber(1) + void clearContractCreationNotSupported() => $_clearField(1); + @$pb.TagNumber(1) + $0.Empty ensureContractCreationNotSupported() => $_ensure(0); + + @$pb.TagNumber(2) + $0.Empty get unsupportedTransactionType => $_getN(1); + @$pb.TagNumber(2) + set unsupportedTransactionType($0.Empty value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasUnsupportedTransactionType() => $_has(1); + @$pb.TagNumber(2) + void clearUnsupportedTransactionType() => $_clearField(2); + @$pb.TagNumber(2) + $0.Empty ensureUnsupportedTransactionType() => $_ensure(1); + + @$pb.TagNumber(3) + NoMatchingGrantError get noMatchingGrant => $_getN(2); + @$pb.TagNumber(3) + set noMatchingGrant(NoMatchingGrantError value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasNoMatchingGrant() => $_has(2); + @$pb.TagNumber(3) + void clearNoMatchingGrant() => $_clearField(3); + @$pb.TagNumber(3) + NoMatchingGrantError ensureNoMatchingGrant() => $_ensure(2); + + @$pb.TagNumber(4) + PolicyViolationsError get policyViolations => $_getN(3); + @$pb.TagNumber(4) + set policyViolations(PolicyViolationsError value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasPolicyViolations() => $_has(3); + @$pb.TagNumber(4) + void clearPolicyViolations() => $_clearField(4); + @$pb.TagNumber(4) + PolicyViolationsError ensurePolicyViolations() => $_ensure(3); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/shared/evm.pbenum.dart b/useragent/lib/proto/shared/evm.pbenum.dart index 2175f8a..e562416 100644 --- a/useragent/lib/proto/shared/evm.pbenum.dart +++ b/useragent/lib/proto/shared/evm.pbenum.dart @@ -1,11 +1,11 @@ -// This is a generated file - do not edit. -// -// Generated from shared/evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// This is a generated file - do not edit. +// +// Generated from shared/evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports diff --git a/useragent/lib/proto/shared/evm.pbjson.dart b/useragent/lib/proto/shared/evm.pbjson.dart index 77c31ec..72c00ba 100644 --- a/useragent/lib/proto/shared/evm.pbjson.dart +++ b/useragent/lib/proto/shared/evm.pbjson.dart @@ -1,342 +1,342 @@ -// This is a generated file - do not edit. -// -// Generated from shared/evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use etherTransferMeaningDescriptor instead') -const EtherTransferMeaning$json = { - '1': 'EtherTransferMeaning', - '2': [ - {'1': 'to', '3': 1, '4': 1, '5': 12, '10': 'to'}, - {'1': 'value', '3': 2, '4': 1, '5': 12, '10': 'value'}, - ], -}; - -/// Descriptor for `EtherTransferMeaning`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List etherTransferMeaningDescriptor = $convert.base64Decode( - 'ChRFdGhlclRyYW5zZmVyTWVhbmluZxIOCgJ0bxgBIAEoDFICdG8SFAoFdmFsdWUYAiABKAxSBX' - 'ZhbHVl'); - -@$core.Deprecated('Use tokenInfoDescriptor instead') -const TokenInfo$json = { - '1': 'TokenInfo', - '2': [ - {'1': 'symbol', '3': 1, '4': 1, '5': 9, '10': 'symbol'}, - {'1': 'address', '3': 2, '4': 1, '5': 12, '10': 'address'}, - {'1': 'chain_id', '3': 3, '4': 1, '5': 4, '10': 'chainId'}, - ], -}; - -/// Descriptor for `TokenInfo`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List tokenInfoDescriptor = $convert.base64Decode( - 'CglUb2tlbkluZm8SFgoGc3ltYm9sGAEgASgJUgZzeW1ib2wSGAoHYWRkcmVzcxgCIAEoDFIHYW' - 'RkcmVzcxIZCghjaGFpbl9pZBgDIAEoBFIHY2hhaW5JZA=='); - -@$core.Deprecated('Use tokenTransferMeaningDescriptor instead') -const TokenTransferMeaning$json = { - '1': 'TokenTransferMeaning', - '2': [ - { - '1': 'token', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.TokenInfo', - '10': 'token' - }, - {'1': 'to', '3': 2, '4': 1, '5': 12, '10': 'to'}, - {'1': 'value', '3': 3, '4': 1, '5': 12, '10': 'value'}, - ], -}; - -/// Descriptor for `TokenTransferMeaning`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List tokenTransferMeaningDescriptor = $convert.base64Decode( - 'ChRUb2tlblRyYW5zZmVyTWVhbmluZxIzCgV0b2tlbhgBIAEoCzIdLmFyYml0ZXIuc2hhcmVkLm' - 'V2bS5Ub2tlbkluZm9SBXRva2VuEg4KAnRvGAIgASgMUgJ0bxIUCgV2YWx1ZRgDIAEoDFIFdmFs' - 'dWU='); - -@$core.Deprecated('Use specificMeaningDescriptor instead') -const SpecificMeaning$json = { - '1': 'SpecificMeaning', - '2': [ - { - '1': 'ether_transfer', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.EtherTransferMeaning', - '9': 0, - '10': 'etherTransfer' - }, - { - '1': 'token_transfer', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.TokenTransferMeaning', - '9': 0, - '10': 'tokenTransfer' - }, - ], - '8': [ - {'1': 'meaning'}, - ], -}; - -/// Descriptor for `SpecificMeaning`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List specificMeaningDescriptor = $convert.base64Decode( - 'Cg9TcGVjaWZpY01lYW5pbmcSUQoOZXRoZXJfdHJhbnNmZXIYASABKAsyKC5hcmJpdGVyLnNoYX' - 'JlZC5ldm0uRXRoZXJUcmFuc2Zlck1lYW5pbmdIAFINZXRoZXJUcmFuc2ZlchJRCg50b2tlbl90' - 'cmFuc2ZlchgCIAEoCzIoLmFyYml0ZXIuc2hhcmVkLmV2bS5Ub2tlblRyYW5zZmVyTWVhbmluZ0' - 'gAUg10b2tlblRyYW5zZmVyQgkKB21lYW5pbmc='); - -@$core.Deprecated('Use gasLimitExceededViolationDescriptor instead') -const GasLimitExceededViolation$json = { - '1': 'GasLimitExceededViolation', - '2': [ - { - '1': 'max_gas_fee_per_gas', - '3': 1, - '4': 1, - '5': 12, - '9': 0, - '10': 'maxGasFeePerGas', - '17': true - }, - { - '1': 'max_priority_fee_per_gas', - '3': 2, - '4': 1, - '5': 12, - '9': 1, - '10': 'maxPriorityFeePerGas', - '17': true - }, - ], - '8': [ - {'1': '_max_gas_fee_per_gas'}, - {'1': '_max_priority_fee_per_gas'}, - ], -}; - -/// Descriptor for `GasLimitExceededViolation`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List gasLimitExceededViolationDescriptor = $convert.base64Decode( - 'ChlHYXNMaW1pdEV4Y2VlZGVkVmlvbGF0aW9uEjEKE21heF9nYXNfZmVlX3Blcl9nYXMYASABKA' - 'xIAFIPbWF4R2FzRmVlUGVyR2FziAEBEjsKGG1heF9wcmlvcml0eV9mZWVfcGVyX2dhcxgCIAEo' - 'DEgBUhRtYXhQcmlvcml0eUZlZVBlckdhc4gBAUIWChRfbWF4X2dhc19mZWVfcGVyX2dhc0IbCh' - 'lfbWF4X3ByaW9yaXR5X2ZlZV9wZXJfZ2Fz'); - -@$core.Deprecated('Use evalViolationDescriptor instead') -const EvalViolation$json = { - '1': 'EvalViolation', - '2': [ - { - '1': 'invalid_target', - '3': 1, - '4': 1, - '5': 12, - '9': 0, - '10': 'invalidTarget' - }, - { - '1': 'gas_limit_exceeded', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.GasLimitExceededViolation', - '9': 0, - '10': 'gasLimitExceeded' - }, - { - '1': 'rate_limit_exceeded', - '3': 3, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'rateLimitExceeded' - }, - { - '1': 'volumetric_limit_exceeded', - '3': 4, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'volumetricLimitExceeded' - }, - { - '1': 'invalid_time', - '3': 5, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'invalidTime' - }, - { - '1': 'invalid_transaction_type', - '3': 6, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'invalidTransactionType' - }, - { - '1': 'chain_id_mismatch', - '3': 7, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.EvalViolation.ChainIdMismatch', - '9': 0, - '10': 'chainIdMismatch' - }, - ], - '3': [EvalViolation_ChainIdMismatch$json], - '8': [ - {'1': 'kind'}, - ], -}; - -@$core.Deprecated('Use evalViolationDescriptor instead') -const EvalViolation_ChainIdMismatch$json = { - '1': 'ChainIdMismatch', - '2': [ - {'1': 'expected', '3': 1, '4': 1, '5': 4, '10': 'expected'}, - {'1': 'actual', '3': 2, '4': 1, '5': 4, '10': 'actual'}, - ], -}; - -/// Descriptor for `EvalViolation`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List evalViolationDescriptor = $convert.base64Decode( - 'Cg1FdmFsVmlvbGF0aW9uEicKDmludmFsaWRfdGFyZ2V0GAEgASgMSABSDWludmFsaWRUYXJnZX' - 'QSXQoSZ2FzX2xpbWl0X2V4Y2VlZGVkGAIgASgLMi0uYXJiaXRlci5zaGFyZWQuZXZtLkdhc0xp' - 'bWl0RXhjZWVkZWRWaW9sYXRpb25IAFIQZ2FzTGltaXRFeGNlZWRlZBJIChNyYXRlX2xpbWl0X2' - 'V4Y2VlZGVkGAMgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSEXJhdGVMaW1pdEV4Y2Vl' - 'ZGVkElQKGXZvbHVtZXRyaWNfbGltaXRfZXhjZWVkZWQYBCABKAsyFi5nb29nbGUucHJvdG9idW' - 'YuRW1wdHlIAFIXdm9sdW1ldHJpY0xpbWl0RXhjZWVkZWQSOwoMaW52YWxpZF90aW1lGAUgASgL' - 'MhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSC2ludmFsaWRUaW1lElIKGGludmFsaWRfdHJhbn' - 'NhY3Rpb25fdHlwZRgGIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAUhZpbnZhbGlkVHJh' - 'bnNhY3Rpb25UeXBlEl8KEWNoYWluX2lkX21pc21hdGNoGAcgASgLMjEuYXJiaXRlci5zaGFyZW' - 'QuZXZtLkV2YWxWaW9sYXRpb24uQ2hhaW5JZE1pc21hdGNoSABSD2NoYWluSWRNaXNtYXRjaBpF' - 'Cg9DaGFpbklkTWlzbWF0Y2gSGgoIZXhwZWN0ZWQYASABKARSCGV4cGVjdGVkEhYKBmFjdHVhbB' - 'gCIAEoBFIGYWN0dWFsQgYKBGtpbmQ='); - -@$core.Deprecated('Use noMatchingGrantErrorDescriptor instead') -const NoMatchingGrantError$json = { - '1': 'NoMatchingGrantError', - '2': [ - { - '1': 'meaning', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.SpecificMeaning', - '10': 'meaning' - }, - ], -}; - -/// Descriptor for `NoMatchingGrantError`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List noMatchingGrantErrorDescriptor = $convert.base64Decode( - 'ChROb01hdGNoaW5nR3JhbnRFcnJvchI9CgdtZWFuaW5nGAEgASgLMiMuYXJiaXRlci5zaGFyZW' - 'QuZXZtLlNwZWNpZmljTWVhbmluZ1IHbWVhbmluZw=='); - -@$core.Deprecated('Use policyViolationsErrorDescriptor instead') -const PolicyViolationsError$json = { - '1': 'PolicyViolationsError', - '2': [ - { - '1': 'meaning', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.SpecificMeaning', - '10': 'meaning' - }, - { - '1': 'violations', - '3': 2, - '4': 3, - '5': 11, - '6': '.arbiter.shared.evm.EvalViolation', - '10': 'violations' - }, - ], -}; - -/// Descriptor for `PolicyViolationsError`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List policyViolationsErrorDescriptor = $convert.base64Decode( - 'ChVQb2xpY3lWaW9sYXRpb25zRXJyb3ISPQoHbWVhbmluZxgBIAEoCzIjLmFyYml0ZXIuc2hhcm' - 'VkLmV2bS5TcGVjaWZpY01lYW5pbmdSB21lYW5pbmcSQQoKdmlvbGF0aW9ucxgCIAMoCzIhLmFy' - 'Yml0ZXIuc2hhcmVkLmV2bS5FdmFsVmlvbGF0aW9uUgp2aW9sYXRpb25z'); - -@$core.Deprecated('Use transactionEvalErrorDescriptor instead') -const TransactionEvalError$json = { - '1': 'TransactionEvalError', - '2': [ - { - '1': 'contract_creation_not_supported', - '3': 1, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'contractCreationNotSupported' - }, - { - '1': 'unsupported_transaction_type', - '3': 2, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'unsupportedTransactionType' - }, - { - '1': 'no_matching_grant', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.NoMatchingGrantError', - '9': 0, - '10': 'noMatchingGrant' - }, - { - '1': 'policy_violations', - '3': 4, - '4': 1, - '5': 11, - '6': '.arbiter.shared.evm.PolicyViolationsError', - '9': 0, - '10': 'policyViolations' - }, - ], - '8': [ - {'1': 'kind'}, - ], -}; - -/// Descriptor for `TransactionEvalError`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List transactionEvalErrorDescriptor = $convert.base64Decode( - 'ChRUcmFuc2FjdGlvbkV2YWxFcnJvchJfCh9jb250cmFjdF9jcmVhdGlvbl9ub3Rfc3VwcG9ydG' - 'VkGAEgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSHGNvbnRyYWN0Q3JlYXRpb25Ob3RT' - 'dXBwb3J0ZWQSWgocdW5zdXBwb3J0ZWRfdHJhbnNhY3Rpb25fdHlwZRgCIAEoCzIWLmdvb2dsZS' - '5wcm90b2J1Zi5FbXB0eUgAUhp1bnN1cHBvcnRlZFRyYW5zYWN0aW9uVHlwZRJWChFub19tYXRj' - 'aGluZ19ncmFudBgDIAEoCzIoLmFyYml0ZXIuc2hhcmVkLmV2bS5Ob01hdGNoaW5nR3JhbnRFcn' - 'JvckgAUg9ub01hdGNoaW5nR3JhbnQSWAoRcG9saWN5X3Zpb2xhdGlvbnMYBCABKAsyKS5hcmJp' - 'dGVyLnNoYXJlZC5ldm0uUG9saWN5VmlvbGF0aW9uc0Vycm9ySABSEHBvbGljeVZpb2xhdGlvbn' - 'NCBgoEa2luZA=='); +// This is a generated file - do not edit. +// +// Generated from shared/evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use etherTransferMeaningDescriptor instead') +const EtherTransferMeaning$json = { + '1': 'EtherTransferMeaning', + '2': [ + {'1': 'to', '3': 1, '4': 1, '5': 12, '10': 'to'}, + {'1': 'value', '3': 2, '4': 1, '5': 12, '10': 'value'}, + ], +}; + +/// Descriptor for `EtherTransferMeaning`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List etherTransferMeaningDescriptor = $convert.base64Decode( + 'ChRFdGhlclRyYW5zZmVyTWVhbmluZxIOCgJ0bxgBIAEoDFICdG8SFAoFdmFsdWUYAiABKAxSBX' + 'ZhbHVl'); + +@$core.Deprecated('Use tokenInfoDescriptor instead') +const TokenInfo$json = { + '1': 'TokenInfo', + '2': [ + {'1': 'symbol', '3': 1, '4': 1, '5': 9, '10': 'symbol'}, + {'1': 'address', '3': 2, '4': 1, '5': 12, '10': 'address'}, + {'1': 'chain_id', '3': 3, '4': 1, '5': 4, '10': 'chainId'}, + ], +}; + +/// Descriptor for `TokenInfo`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List tokenInfoDescriptor = $convert.base64Decode( + 'CglUb2tlbkluZm8SFgoGc3ltYm9sGAEgASgJUgZzeW1ib2wSGAoHYWRkcmVzcxgCIAEoDFIHYW' + 'RkcmVzcxIZCghjaGFpbl9pZBgDIAEoBFIHY2hhaW5JZA=='); + +@$core.Deprecated('Use tokenTransferMeaningDescriptor instead') +const TokenTransferMeaning$json = { + '1': 'TokenTransferMeaning', + '2': [ + { + '1': 'token', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.TokenInfo', + '10': 'token' + }, + {'1': 'to', '3': 2, '4': 1, '5': 12, '10': 'to'}, + {'1': 'value', '3': 3, '4': 1, '5': 12, '10': 'value'}, + ], +}; + +/// Descriptor for `TokenTransferMeaning`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List tokenTransferMeaningDescriptor = $convert.base64Decode( + 'ChRUb2tlblRyYW5zZmVyTWVhbmluZxIzCgV0b2tlbhgBIAEoCzIdLmFyYml0ZXIuc2hhcmVkLm' + 'V2bS5Ub2tlbkluZm9SBXRva2VuEg4KAnRvGAIgASgMUgJ0bxIUCgV2YWx1ZRgDIAEoDFIFdmFs' + 'dWU='); + +@$core.Deprecated('Use specificMeaningDescriptor instead') +const SpecificMeaning$json = { + '1': 'SpecificMeaning', + '2': [ + { + '1': 'ether_transfer', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.EtherTransferMeaning', + '9': 0, + '10': 'etherTransfer' + }, + { + '1': 'token_transfer', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.TokenTransferMeaning', + '9': 0, + '10': 'tokenTransfer' + }, + ], + '8': [ + {'1': 'meaning'}, + ], +}; + +/// Descriptor for `SpecificMeaning`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List specificMeaningDescriptor = $convert.base64Decode( + 'Cg9TcGVjaWZpY01lYW5pbmcSUQoOZXRoZXJfdHJhbnNmZXIYASABKAsyKC5hcmJpdGVyLnNoYX' + 'JlZC5ldm0uRXRoZXJUcmFuc2Zlck1lYW5pbmdIAFINZXRoZXJUcmFuc2ZlchJRCg50b2tlbl90' + 'cmFuc2ZlchgCIAEoCzIoLmFyYml0ZXIuc2hhcmVkLmV2bS5Ub2tlblRyYW5zZmVyTWVhbmluZ0' + 'gAUg10b2tlblRyYW5zZmVyQgkKB21lYW5pbmc='); + +@$core.Deprecated('Use gasLimitExceededViolationDescriptor instead') +const GasLimitExceededViolation$json = { + '1': 'GasLimitExceededViolation', + '2': [ + { + '1': 'max_gas_fee_per_gas', + '3': 1, + '4': 1, + '5': 12, + '9': 0, + '10': 'maxGasFeePerGas', + '17': true + }, + { + '1': 'max_priority_fee_per_gas', + '3': 2, + '4': 1, + '5': 12, + '9': 1, + '10': 'maxPriorityFeePerGas', + '17': true + }, + ], + '8': [ + {'1': '_max_gas_fee_per_gas'}, + {'1': '_max_priority_fee_per_gas'}, + ], +}; + +/// Descriptor for `GasLimitExceededViolation`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List gasLimitExceededViolationDescriptor = $convert.base64Decode( + 'ChlHYXNMaW1pdEV4Y2VlZGVkVmlvbGF0aW9uEjEKE21heF9nYXNfZmVlX3Blcl9nYXMYASABKA' + 'xIAFIPbWF4R2FzRmVlUGVyR2FziAEBEjsKGG1heF9wcmlvcml0eV9mZWVfcGVyX2dhcxgCIAEo' + 'DEgBUhRtYXhQcmlvcml0eUZlZVBlckdhc4gBAUIWChRfbWF4X2dhc19mZWVfcGVyX2dhc0IbCh' + 'lfbWF4X3ByaW9yaXR5X2ZlZV9wZXJfZ2Fz'); + +@$core.Deprecated('Use evalViolationDescriptor instead') +const EvalViolation$json = { + '1': 'EvalViolation', + '2': [ + { + '1': 'invalid_target', + '3': 1, + '4': 1, + '5': 12, + '9': 0, + '10': 'invalidTarget' + }, + { + '1': 'gas_limit_exceeded', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.GasLimitExceededViolation', + '9': 0, + '10': 'gasLimitExceeded' + }, + { + '1': 'rate_limit_exceeded', + '3': 3, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'rateLimitExceeded' + }, + { + '1': 'volumetric_limit_exceeded', + '3': 4, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'volumetricLimitExceeded' + }, + { + '1': 'invalid_time', + '3': 5, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'invalidTime' + }, + { + '1': 'invalid_transaction_type', + '3': 6, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'invalidTransactionType' + }, + { + '1': 'chain_id_mismatch', + '3': 7, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.EvalViolation.ChainIdMismatch', + '9': 0, + '10': 'chainIdMismatch' + }, + ], + '3': [EvalViolation_ChainIdMismatch$json], + '8': [ + {'1': 'kind'}, + ], +}; + +@$core.Deprecated('Use evalViolationDescriptor instead') +const EvalViolation_ChainIdMismatch$json = { + '1': 'ChainIdMismatch', + '2': [ + {'1': 'expected', '3': 1, '4': 1, '5': 4, '10': 'expected'}, + {'1': 'actual', '3': 2, '4': 1, '5': 4, '10': 'actual'}, + ], +}; + +/// Descriptor for `EvalViolation`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List evalViolationDescriptor = $convert.base64Decode( + 'Cg1FdmFsVmlvbGF0aW9uEicKDmludmFsaWRfdGFyZ2V0GAEgASgMSABSDWludmFsaWRUYXJnZX' + 'QSXQoSZ2FzX2xpbWl0X2V4Y2VlZGVkGAIgASgLMi0uYXJiaXRlci5zaGFyZWQuZXZtLkdhc0xp' + 'bWl0RXhjZWVkZWRWaW9sYXRpb25IAFIQZ2FzTGltaXRFeGNlZWRlZBJIChNyYXRlX2xpbWl0X2' + 'V4Y2VlZGVkGAMgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSEXJhdGVMaW1pdEV4Y2Vl' + 'ZGVkElQKGXZvbHVtZXRyaWNfbGltaXRfZXhjZWVkZWQYBCABKAsyFi5nb29nbGUucHJvdG9idW' + 'YuRW1wdHlIAFIXdm9sdW1ldHJpY0xpbWl0RXhjZWVkZWQSOwoMaW52YWxpZF90aW1lGAUgASgL' + 'MhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSC2ludmFsaWRUaW1lElIKGGludmFsaWRfdHJhbn' + 'NhY3Rpb25fdHlwZRgGIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAUhZpbnZhbGlkVHJh' + 'bnNhY3Rpb25UeXBlEl8KEWNoYWluX2lkX21pc21hdGNoGAcgASgLMjEuYXJiaXRlci5zaGFyZW' + 'QuZXZtLkV2YWxWaW9sYXRpb24uQ2hhaW5JZE1pc21hdGNoSABSD2NoYWluSWRNaXNtYXRjaBpF' + 'Cg9DaGFpbklkTWlzbWF0Y2gSGgoIZXhwZWN0ZWQYASABKARSCGV4cGVjdGVkEhYKBmFjdHVhbB' + 'gCIAEoBFIGYWN0dWFsQgYKBGtpbmQ='); + +@$core.Deprecated('Use noMatchingGrantErrorDescriptor instead') +const NoMatchingGrantError$json = { + '1': 'NoMatchingGrantError', + '2': [ + { + '1': 'meaning', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.SpecificMeaning', + '10': 'meaning' + }, + ], +}; + +/// Descriptor for `NoMatchingGrantError`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List noMatchingGrantErrorDescriptor = $convert.base64Decode( + 'ChROb01hdGNoaW5nR3JhbnRFcnJvchI9CgdtZWFuaW5nGAEgASgLMiMuYXJiaXRlci5zaGFyZW' + 'QuZXZtLlNwZWNpZmljTWVhbmluZ1IHbWVhbmluZw=='); + +@$core.Deprecated('Use policyViolationsErrorDescriptor instead') +const PolicyViolationsError$json = { + '1': 'PolicyViolationsError', + '2': [ + { + '1': 'meaning', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.SpecificMeaning', + '10': 'meaning' + }, + { + '1': 'violations', + '3': 2, + '4': 3, + '5': 11, + '6': '.arbiter.shared.evm.EvalViolation', + '10': 'violations' + }, + ], +}; + +/// Descriptor for `PolicyViolationsError`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List policyViolationsErrorDescriptor = $convert.base64Decode( + 'ChVQb2xpY3lWaW9sYXRpb25zRXJyb3ISPQoHbWVhbmluZxgBIAEoCzIjLmFyYml0ZXIuc2hhcm' + 'VkLmV2bS5TcGVjaWZpY01lYW5pbmdSB21lYW5pbmcSQQoKdmlvbGF0aW9ucxgCIAMoCzIhLmFy' + 'Yml0ZXIuc2hhcmVkLmV2bS5FdmFsVmlvbGF0aW9uUgp2aW9sYXRpb25z'); + +@$core.Deprecated('Use transactionEvalErrorDescriptor instead') +const TransactionEvalError$json = { + '1': 'TransactionEvalError', + '2': [ + { + '1': 'contract_creation_not_supported', + '3': 1, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'contractCreationNotSupported' + }, + { + '1': 'unsupported_transaction_type', + '3': 2, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'unsupportedTransactionType' + }, + { + '1': 'no_matching_grant', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.NoMatchingGrantError', + '9': 0, + '10': 'noMatchingGrant' + }, + { + '1': 'policy_violations', + '3': 4, + '4': 1, + '5': 11, + '6': '.arbiter.shared.evm.PolicyViolationsError', + '9': 0, + '10': 'policyViolations' + }, + ], + '8': [ + {'1': 'kind'}, + ], +}; + +/// Descriptor for `TransactionEvalError`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List transactionEvalErrorDescriptor = $convert.base64Decode( + 'ChRUcmFuc2FjdGlvbkV2YWxFcnJvchJfCh9jb250cmFjdF9jcmVhdGlvbl9ub3Rfc3VwcG9ydG' + 'VkGAEgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SABSHGNvbnRyYWN0Q3JlYXRpb25Ob3RT' + 'dXBwb3J0ZWQSWgocdW5zdXBwb3J0ZWRfdHJhbnNhY3Rpb25fdHlwZRgCIAEoCzIWLmdvb2dsZS' + '5wcm90b2J1Zi5FbXB0eUgAUhp1bnN1cHBvcnRlZFRyYW5zYWN0aW9uVHlwZRJWChFub19tYXRj' + 'aGluZ19ncmFudBgDIAEoCzIoLmFyYml0ZXIuc2hhcmVkLmV2bS5Ob01hdGNoaW5nR3JhbnRFcn' + 'JvckgAUg9ub01hdGNoaW5nR3JhbnQSWAoRcG9saWN5X3Zpb2xhdGlvbnMYBCABKAsyKS5hcmJp' + 'dGVyLnNoYXJlZC5ldm0uUG9saWN5VmlvbGF0aW9uc0Vycm9ySABSEHBvbGljeVZpb2xhdGlvbn' + 'NCBgoEa2luZA=='); diff --git a/useragent/lib/proto/shared/vault.pb.dart b/useragent/lib/proto/shared/vault.pb.dart index 10e9074..ba6f1a6 100644 --- a/useragent/lib/proto/shared/vault.pb.dart +++ b/useragent/lib/proto/shared/vault.pb.dart @@ -1,17 +1,17 @@ -// This is a generated file - do not edit. -// -// Generated from shared/vault.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -export 'vault.pbenum.dart'; +// This is a generated file - do not edit. +// +// Generated from shared/vault.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +export 'vault.pbenum.dart'; diff --git a/useragent/lib/proto/shared/vault.pbenum.dart b/useragent/lib/proto/shared/vault.pbenum.dart index 640138e..0bb24aa 100644 --- a/useragent/lib/proto/shared/vault.pbenum.dart +++ b/useragent/lib/proto/shared/vault.pbenum.dart @@ -1,46 +1,46 @@ -// This is a generated file - do not edit. -// -// Generated from shared/vault.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -class VaultState extends $pb.ProtobufEnum { - static const VaultState VAULT_STATE_UNSPECIFIED = - VaultState._(0, _omitEnumNames ? '' : 'VAULT_STATE_UNSPECIFIED'); - static const VaultState VAULT_STATE_UNBOOTSTRAPPED = - VaultState._(1, _omitEnumNames ? '' : 'VAULT_STATE_UNBOOTSTRAPPED'); - static const VaultState VAULT_STATE_SEALED = - VaultState._(2, _omitEnumNames ? '' : 'VAULT_STATE_SEALED'); - static const VaultState VAULT_STATE_UNSEALED = - VaultState._(3, _omitEnumNames ? '' : 'VAULT_STATE_UNSEALED'); - static const VaultState VAULT_STATE_ERROR = - VaultState._(4, _omitEnumNames ? '' : 'VAULT_STATE_ERROR'); - - static const $core.List values = [ - VAULT_STATE_UNSPECIFIED, - VAULT_STATE_UNBOOTSTRAPPED, - VAULT_STATE_SEALED, - VAULT_STATE_UNSEALED, - VAULT_STATE_ERROR, - ]; - - static final $core.List _byValue = - $pb.ProtobufEnum.$_initByValueList(values, 4); - static VaultState? valueOf($core.int value) => - value < 0 || value >= _byValue.length ? null : _byValue[value]; - - const VaultState._(super.value, super.name); -} - -const $core.bool _omitEnumNames = - $core.bool.fromEnvironment('protobuf.omit_enum_names'); +// This is a generated file - do not edit. +// +// Generated from shared/vault.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class VaultState extends $pb.ProtobufEnum { + static const VaultState VAULT_STATE_UNSPECIFIED = + VaultState._(0, _omitEnumNames ? '' : 'VAULT_STATE_UNSPECIFIED'); + static const VaultState VAULT_STATE_UNBOOTSTRAPPED = + VaultState._(1, _omitEnumNames ? '' : 'VAULT_STATE_UNBOOTSTRAPPED'); + static const VaultState VAULT_STATE_SEALED = + VaultState._(2, _omitEnumNames ? '' : 'VAULT_STATE_SEALED'); + static const VaultState VAULT_STATE_UNSEALED = + VaultState._(3, _omitEnumNames ? '' : 'VAULT_STATE_UNSEALED'); + static const VaultState VAULT_STATE_ERROR = + VaultState._(4, _omitEnumNames ? '' : 'VAULT_STATE_ERROR'); + + static const $core.List values = [ + VAULT_STATE_UNSPECIFIED, + VAULT_STATE_UNBOOTSTRAPPED, + VAULT_STATE_SEALED, + VAULT_STATE_UNSEALED, + VAULT_STATE_ERROR, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 4); + static VaultState? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const VaultState._(super.value, super.name); +} + +const $core.bool _omitEnumNames = + $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/useragent/lib/proto/shared/vault.pbjson.dart b/useragent/lib/proto/shared/vault.pbjson.dart index db77ab0..0fe4016 100644 --- a/useragent/lib/proto/shared/vault.pbjson.dart +++ b/useragent/lib/proto/shared/vault.pbjson.dart @@ -1,34 +1,34 @@ -// This is a generated file - do not edit. -// -// Generated from shared/vault.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use vaultStateDescriptor instead') -const VaultState$json = { - '1': 'VaultState', - '2': [ - {'1': 'VAULT_STATE_UNSPECIFIED', '2': 0}, - {'1': 'VAULT_STATE_UNBOOTSTRAPPED', '2': 1}, - {'1': 'VAULT_STATE_SEALED', '2': 2}, - {'1': 'VAULT_STATE_UNSEALED', '2': 3}, - {'1': 'VAULT_STATE_ERROR', '2': 4}, - ], -}; - -/// Descriptor for `VaultState`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List vaultStateDescriptor = $convert.base64Decode( - 'CgpWYXVsdFN0YXRlEhsKF1ZBVUxUX1NUQVRFX1VOU1BFQ0lGSUVEEAASHgoaVkFVTFRfU1RBVE' - 'VfVU5CT09UU1RSQVBQRUQQARIWChJWQVVMVF9TVEFURV9TRUFMRUQQAhIYChRWQVVMVF9TVEFU' - 'RV9VTlNFQUxFRBADEhUKEVZBVUxUX1NUQVRFX0VSUk9SEAQ='); +// This is a generated file - do not edit. +// +// Generated from shared/vault.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use vaultStateDescriptor instead') +const VaultState$json = { + '1': 'VaultState', + '2': [ + {'1': 'VAULT_STATE_UNSPECIFIED', '2': 0}, + {'1': 'VAULT_STATE_UNBOOTSTRAPPED', '2': 1}, + {'1': 'VAULT_STATE_SEALED', '2': 2}, + {'1': 'VAULT_STATE_UNSEALED', '2': 3}, + {'1': 'VAULT_STATE_ERROR', '2': 4}, + ], +}; + +/// Descriptor for `VaultState`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List vaultStateDescriptor = $convert.base64Decode( + 'CgpWYXVsdFN0YXRlEhsKF1ZBVUxUX1NUQVRFX1VOU1BFQ0lGSUVEEAASHgoaVkFVTFRfU1RBVE' + 'VfVU5CT09UU1RSQVBQRUQQARIWChJWQVVMVF9TVEFURV9TRUFMRUQQAhIYChRWQVVMVF9TVEFU' + 'RV9VTlNFQUxFRBADEhUKEVZBVUxUX1NUQVRFX0VSUk9SEAQ='); diff --git a/useragent/lib/proto/user_agent.pb.dart b/useragent/lib/proto/user_agent.pb.dart index fae11ca..ff86736 100644 --- a/useragent/lib/proto/user_agent.pb.dart +++ b/useragent/lib/proto/user_agent.pb.dart @@ -1,303 +1,303 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -import 'user_agent/auth.pb.dart' as $0; -import 'user_agent/evm.pb.dart' as $2; -import 'user_agent/sdk_client.pb.dart' as $3; -import 'user_agent/vault/vault.pb.dart' as $1; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -enum UserAgentRequest_Payload { auth, vault, evm, sdkClient, notSet } - -class UserAgentRequest extends $pb.GeneratedMessage { - factory UserAgentRequest({ - $0.Request? auth, - $1.Request? vault, - $2.Request? evm, - $3.Request? sdkClient, - $core.int? id, - }) { - final result = create(); - if (auth != null) result.auth = auth; - if (vault != null) result.vault = vault; - if (evm != null) result.evm = evm; - if (sdkClient != null) result.sdkClient = sdkClient; - if (id != null) result.id = id; - return result; - } - - UserAgentRequest._(); - - factory UserAgentRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory UserAgentRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, UserAgentRequest_Payload> - _UserAgentRequest_PayloadByTag = { - 1: UserAgentRequest_Payload.auth, - 2: UserAgentRequest_Payload.vault, - 3: UserAgentRequest_Payload.evm, - 4: UserAgentRequest_Payload.sdkClient, - 0: UserAgentRequest_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'UserAgentRequest', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.user_agent'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4]) - ..aOM<$0.Request>(1, _omitFieldNames ? '' : 'auth', - subBuilder: $0.Request.create) - ..aOM<$1.Request>(2, _omitFieldNames ? '' : 'vault', - subBuilder: $1.Request.create) - ..aOM<$2.Request>(3, _omitFieldNames ? '' : 'evm', - subBuilder: $2.Request.create) - ..aOM<$3.Request>(4, _omitFieldNames ? '' : 'sdkClient', - subBuilder: $3.Request.create) - ..aI(16, _omitFieldNames ? '' : 'id') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - UserAgentRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - UserAgentRequest copyWith(void Function(UserAgentRequest) updates) => - super.copyWith((message) => updates(message as UserAgentRequest)) - as UserAgentRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static UserAgentRequest create() => UserAgentRequest._(); - @$core.override - UserAgentRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static UserAgentRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static UserAgentRequest? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - UserAgentRequest_Payload whichPayload() => - _UserAgentRequest_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $0.Request get auth => $_getN(0); - @$pb.TagNumber(1) - set auth($0.Request value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasAuth() => $_has(0); - @$pb.TagNumber(1) - void clearAuth() => $_clearField(1); - @$pb.TagNumber(1) - $0.Request ensureAuth() => $_ensure(0); - - @$pb.TagNumber(2) - $1.Request get vault => $_getN(1); - @$pb.TagNumber(2) - set vault($1.Request value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasVault() => $_has(1); - @$pb.TagNumber(2) - void clearVault() => $_clearField(2); - @$pb.TagNumber(2) - $1.Request ensureVault() => $_ensure(1); - - @$pb.TagNumber(3) - $2.Request get evm => $_getN(2); - @$pb.TagNumber(3) - set evm($2.Request value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasEvm() => $_has(2); - @$pb.TagNumber(3) - void clearEvm() => $_clearField(3); - @$pb.TagNumber(3) - $2.Request ensureEvm() => $_ensure(2); - - @$pb.TagNumber(4) - $3.Request get sdkClient => $_getN(3); - @$pb.TagNumber(4) - set sdkClient($3.Request value) => $_setField(4, value); - @$pb.TagNumber(4) - $core.bool hasSdkClient() => $_has(3); - @$pb.TagNumber(4) - void clearSdkClient() => $_clearField(4); - @$pb.TagNumber(4) - $3.Request ensureSdkClient() => $_ensure(3); - - @$pb.TagNumber(16) - $core.int get id => $_getIZ(4); - @$pb.TagNumber(16) - set id($core.int value) => $_setSignedInt32(4, value); - @$pb.TagNumber(16) - $core.bool hasId() => $_has(4); - @$pb.TagNumber(16) - void clearId() => $_clearField(16); -} - -enum UserAgentResponse_Payload { auth, vault, evm, sdkClient, notSet } - -class UserAgentResponse extends $pb.GeneratedMessage { - factory UserAgentResponse({ - $0.Response? auth, - $1.Response? vault, - $2.Response? evm, - $3.Response? sdkClient, - $core.int? id, - }) { - final result = create(); - if (auth != null) result.auth = auth; - if (vault != null) result.vault = vault; - if (evm != null) result.evm = evm; - if (sdkClient != null) result.sdkClient = sdkClient; - if (id != null) result.id = id; - return result; - } - - UserAgentResponse._(); - - factory UserAgentResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory UserAgentResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, UserAgentResponse_Payload> - _UserAgentResponse_PayloadByTag = { - 1: UserAgentResponse_Payload.auth, - 2: UserAgentResponse_Payload.vault, - 3: UserAgentResponse_Payload.evm, - 4: UserAgentResponse_Payload.sdkClient, - 0: UserAgentResponse_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'UserAgentResponse', - package: - const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.user_agent'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4]) - ..aOM<$0.Response>(1, _omitFieldNames ? '' : 'auth', - subBuilder: $0.Response.create) - ..aOM<$1.Response>(2, _omitFieldNames ? '' : 'vault', - subBuilder: $1.Response.create) - ..aOM<$2.Response>(3, _omitFieldNames ? '' : 'evm', - subBuilder: $2.Response.create) - ..aOM<$3.Response>(4, _omitFieldNames ? '' : 'sdkClient', - subBuilder: $3.Response.create) - ..aI(16, _omitFieldNames ? '' : 'id') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - UserAgentResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - UserAgentResponse copyWith(void Function(UserAgentResponse) updates) => - super.copyWith((message) => updates(message as UserAgentResponse)) - as UserAgentResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static UserAgentResponse create() => UserAgentResponse._(); - @$core.override - UserAgentResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static UserAgentResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static UserAgentResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - UserAgentResponse_Payload whichPayload() => - _UserAgentResponse_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $0.Response get auth => $_getN(0); - @$pb.TagNumber(1) - set auth($0.Response value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasAuth() => $_has(0); - @$pb.TagNumber(1) - void clearAuth() => $_clearField(1); - @$pb.TagNumber(1) - $0.Response ensureAuth() => $_ensure(0); - - @$pb.TagNumber(2) - $1.Response get vault => $_getN(1); - @$pb.TagNumber(2) - set vault($1.Response value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasVault() => $_has(1); - @$pb.TagNumber(2) - void clearVault() => $_clearField(2); - @$pb.TagNumber(2) - $1.Response ensureVault() => $_ensure(1); - - @$pb.TagNumber(3) - $2.Response get evm => $_getN(2); - @$pb.TagNumber(3) - set evm($2.Response value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasEvm() => $_has(2); - @$pb.TagNumber(3) - void clearEvm() => $_clearField(3); - @$pb.TagNumber(3) - $2.Response ensureEvm() => $_ensure(2); - - @$pb.TagNumber(4) - $3.Response get sdkClient => $_getN(3); - @$pb.TagNumber(4) - set sdkClient($3.Response value) => $_setField(4, value); - @$pb.TagNumber(4) - $core.bool hasSdkClient() => $_has(3); - @$pb.TagNumber(4) - void clearSdkClient() => $_clearField(4); - @$pb.TagNumber(4) - $3.Response ensureSdkClient() => $_ensure(3); - - @$pb.TagNumber(16) - $core.int get id => $_getIZ(4); - @$pb.TagNumber(16) - set id($core.int value) => $_setSignedInt32(4, value); - @$pb.TagNumber(16) - $core.bool hasId() => $_has(4); - @$pb.TagNumber(16) - void clearId() => $_clearField(16); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'user_agent/auth.pb.dart' as $0; +import 'user_agent/evm.pb.dart' as $2; +import 'user_agent/sdk_client.pb.dart' as $3; +import 'user_agent/vault/vault.pb.dart' as $1; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +enum UserAgentRequest_Payload { auth, vault, evm, sdkClient, notSet } + +class UserAgentRequest extends $pb.GeneratedMessage { + factory UserAgentRequest({ + $0.Request? auth, + $1.Request? vault, + $2.Request? evm, + $3.Request? sdkClient, + $core.int? id, + }) { + final result = create(); + if (auth != null) result.auth = auth; + if (vault != null) result.vault = vault; + if (evm != null) result.evm = evm; + if (sdkClient != null) result.sdkClient = sdkClient; + if (id != null) result.id = id; + return result; + } + + UserAgentRequest._(); + + factory UserAgentRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory UserAgentRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, UserAgentRequest_Payload> + _UserAgentRequest_PayloadByTag = { + 1: UserAgentRequest_Payload.auth, + 2: UserAgentRequest_Payload.vault, + 3: UserAgentRequest_Payload.evm, + 4: UserAgentRequest_Payload.sdkClient, + 0: UserAgentRequest_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'UserAgentRequest', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.user_agent'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3, 4]) + ..aOM<$0.Request>(1, _omitFieldNames ? '' : 'auth', + subBuilder: $0.Request.create) + ..aOM<$1.Request>(2, _omitFieldNames ? '' : 'vault', + subBuilder: $1.Request.create) + ..aOM<$2.Request>(3, _omitFieldNames ? '' : 'evm', + subBuilder: $2.Request.create) + ..aOM<$3.Request>(4, _omitFieldNames ? '' : 'sdkClient', + subBuilder: $3.Request.create) + ..aI(16, _omitFieldNames ? '' : 'id') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UserAgentRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UserAgentRequest copyWith(void Function(UserAgentRequest) updates) => + super.copyWith((message) => updates(message as UserAgentRequest)) + as UserAgentRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static UserAgentRequest create() => UserAgentRequest._(); + @$core.override + UserAgentRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static UserAgentRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static UserAgentRequest? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + UserAgentRequest_Payload whichPayload() => + _UserAgentRequest_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $0.Request get auth => $_getN(0); + @$pb.TagNumber(1) + set auth($0.Request value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasAuth() => $_has(0); + @$pb.TagNumber(1) + void clearAuth() => $_clearField(1); + @$pb.TagNumber(1) + $0.Request ensureAuth() => $_ensure(0); + + @$pb.TagNumber(2) + $1.Request get vault => $_getN(1); + @$pb.TagNumber(2) + set vault($1.Request value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasVault() => $_has(1); + @$pb.TagNumber(2) + void clearVault() => $_clearField(2); + @$pb.TagNumber(2) + $1.Request ensureVault() => $_ensure(1); + + @$pb.TagNumber(3) + $2.Request get evm => $_getN(2); + @$pb.TagNumber(3) + set evm($2.Request value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasEvm() => $_has(2); + @$pb.TagNumber(3) + void clearEvm() => $_clearField(3); + @$pb.TagNumber(3) + $2.Request ensureEvm() => $_ensure(2); + + @$pb.TagNumber(4) + $3.Request get sdkClient => $_getN(3); + @$pb.TagNumber(4) + set sdkClient($3.Request value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasSdkClient() => $_has(3); + @$pb.TagNumber(4) + void clearSdkClient() => $_clearField(4); + @$pb.TagNumber(4) + $3.Request ensureSdkClient() => $_ensure(3); + + @$pb.TagNumber(16) + $core.int get id => $_getIZ(4); + @$pb.TagNumber(16) + set id($core.int value) => $_setSignedInt32(4, value); + @$pb.TagNumber(16) + $core.bool hasId() => $_has(4); + @$pb.TagNumber(16) + void clearId() => $_clearField(16); +} + +enum UserAgentResponse_Payload { auth, vault, evm, sdkClient, notSet } + +class UserAgentResponse extends $pb.GeneratedMessage { + factory UserAgentResponse({ + $0.Response? auth, + $1.Response? vault, + $2.Response? evm, + $3.Response? sdkClient, + $core.int? id, + }) { + final result = create(); + if (auth != null) result.auth = auth; + if (vault != null) result.vault = vault; + if (evm != null) result.evm = evm; + if (sdkClient != null) result.sdkClient = sdkClient; + if (id != null) result.id = id; + return result; + } + + UserAgentResponse._(); + + factory UserAgentResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory UserAgentResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, UserAgentResponse_Payload> + _UserAgentResponse_PayloadByTag = { + 1: UserAgentResponse_Payload.auth, + 2: UserAgentResponse_Payload.vault, + 3: UserAgentResponse_Payload.evm, + 4: UserAgentResponse_Payload.sdkClient, + 0: UserAgentResponse_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'UserAgentResponse', + package: + const $pb.PackageName(_omitMessageNames ? '' : 'arbiter.user_agent'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3, 4]) + ..aOM<$0.Response>(1, _omitFieldNames ? '' : 'auth', + subBuilder: $0.Response.create) + ..aOM<$1.Response>(2, _omitFieldNames ? '' : 'vault', + subBuilder: $1.Response.create) + ..aOM<$2.Response>(3, _omitFieldNames ? '' : 'evm', + subBuilder: $2.Response.create) + ..aOM<$3.Response>(4, _omitFieldNames ? '' : 'sdkClient', + subBuilder: $3.Response.create) + ..aI(16, _omitFieldNames ? '' : 'id') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UserAgentResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UserAgentResponse copyWith(void Function(UserAgentResponse) updates) => + super.copyWith((message) => updates(message as UserAgentResponse)) + as UserAgentResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static UserAgentResponse create() => UserAgentResponse._(); + @$core.override + UserAgentResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static UserAgentResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static UserAgentResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + UserAgentResponse_Payload whichPayload() => + _UserAgentResponse_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $0.Response get auth => $_getN(0); + @$pb.TagNumber(1) + set auth($0.Response value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasAuth() => $_has(0); + @$pb.TagNumber(1) + void clearAuth() => $_clearField(1); + @$pb.TagNumber(1) + $0.Response ensureAuth() => $_ensure(0); + + @$pb.TagNumber(2) + $1.Response get vault => $_getN(1); + @$pb.TagNumber(2) + set vault($1.Response value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasVault() => $_has(1); + @$pb.TagNumber(2) + void clearVault() => $_clearField(2); + @$pb.TagNumber(2) + $1.Response ensureVault() => $_ensure(1); + + @$pb.TagNumber(3) + $2.Response get evm => $_getN(2); + @$pb.TagNumber(3) + set evm($2.Response value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasEvm() => $_has(2); + @$pb.TagNumber(3) + void clearEvm() => $_clearField(3); + @$pb.TagNumber(3) + $2.Response ensureEvm() => $_ensure(2); + + @$pb.TagNumber(4) + $3.Response get sdkClient => $_getN(3); + @$pb.TagNumber(4) + set sdkClient($3.Response value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasSdkClient() => $_has(3); + @$pb.TagNumber(4) + void clearSdkClient() => $_clearField(4); + @$pb.TagNumber(4) + $3.Response ensureSdkClient() => $_ensure(3); + + @$pb.TagNumber(16) + $core.int get id => $_getIZ(4); + @$pb.TagNumber(16) + set id($core.int value) => $_setSignedInt32(4, value); + @$pb.TagNumber(16) + $core.bool hasId() => $_has(4); + @$pb.TagNumber(16) + void clearId() => $_clearField(16); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/user_agent.pbenum.dart b/useragent/lib/proto/user_agent.pbenum.dart index ef6073b..9edab79 100644 --- a/useragent/lib/proto/user_agent.pbenum.dart +++ b/useragent/lib/proto/user_agent.pbenum.dart @@ -1,11 +1,11 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// This is a generated file - do not edit. +// +// Generated from user_agent.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports diff --git a/useragent/lib/proto/user_agent.pbjson.dart b/useragent/lib/proto/user_agent.pbjson.dart index 347a28a..f94cdb4 100644 --- a/useragent/lib/proto/user_agent.pbjson.dart +++ b/useragent/lib/proto/user_agent.pbjson.dart @@ -1,129 +1,129 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use userAgentRequestDescriptor instead') -const UserAgentRequest$json = { - '1': 'UserAgentRequest', - '2': [ - {'1': 'id', '3': 16, '4': 1, '5': 5, '10': 'id'}, - { - '1': 'auth', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.auth.Request', - '9': 0, - '10': 'auth' - }, - { - '1': 'vault', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.vault.Request', - '9': 0, - '10': 'vault' - }, - { - '1': 'evm', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.evm.Request', - '9': 0, - '10': 'evm' - }, - { - '1': 'sdk_client', - '3': 4, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.Request', - '9': 0, - '10': 'sdkClient' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `UserAgentRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List userAgentRequestDescriptor = $convert.base64Decode( - 'ChBVc2VyQWdlbnRSZXF1ZXN0Eg4KAmlkGBAgASgFUgJpZBI2CgRhdXRoGAEgASgLMiAuYXJiaX' - 'Rlci51c2VyX2FnZW50LmF1dGguUmVxdWVzdEgAUgRhdXRoEjkKBXZhdWx0GAIgASgLMiEuYXJi' - 'aXRlci51c2VyX2FnZW50LnZhdWx0LlJlcXVlc3RIAFIFdmF1bHQSMwoDZXZtGAMgASgLMh8uYX' - 'JiaXRlci51c2VyX2FnZW50LmV2bS5SZXF1ZXN0SABSA2V2bRJHCgpzZGtfY2xpZW50GAQgASgL' - 'MiYuYXJiaXRlci51c2VyX2FnZW50LnNka19jbGllbnQuUmVxdWVzdEgAUglzZGtDbGllbnRCCQ' - 'oHcGF5bG9hZA=='); - -@$core.Deprecated('Use userAgentResponseDescriptor instead') -const UserAgentResponse$json = { - '1': 'UserAgentResponse', - '2': [ - {'1': 'id', '3': 16, '4': 1, '5': 5, '9': 1, '10': 'id', '17': true}, - { - '1': 'auth', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.auth.Response', - '9': 0, - '10': 'auth' - }, - { - '1': 'vault', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.vault.Response', - '9': 0, - '10': 'vault' - }, - { - '1': 'evm', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.evm.Response', - '9': 0, - '10': 'evm' - }, - { - '1': 'sdk_client', - '3': 4, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.Response', - '9': 0, - '10': 'sdkClient' - }, - ], - '8': [ - {'1': 'payload'}, - {'1': '_id'}, - ], -}; - -/// Descriptor for `UserAgentResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List userAgentResponseDescriptor = $convert.base64Decode( - 'ChFVc2VyQWdlbnRSZXNwb25zZRITCgJpZBgQIAEoBUgBUgJpZIgBARI3CgRhdXRoGAEgASgLMi' - 'EuYXJiaXRlci51c2VyX2FnZW50LmF1dGguUmVzcG9uc2VIAFIEYXV0aBI6CgV2YXVsdBgCIAEo' - 'CzIiLmFyYml0ZXIudXNlcl9hZ2VudC52YXVsdC5SZXNwb25zZUgAUgV2YXVsdBI0CgNldm0YAy' - 'ABKAsyIC5hcmJpdGVyLnVzZXJfYWdlbnQuZXZtLlJlc3BvbnNlSABSA2V2bRJICgpzZGtfY2xp' - 'ZW50GAQgASgLMicuYXJiaXRlci51c2VyX2FnZW50LnNka19jbGllbnQuUmVzcG9uc2VIAFIJc2' - 'RrQ2xpZW50QgkKB3BheWxvYWRCBQoDX2lk'); +// This is a generated file - do not edit. +// +// Generated from user_agent.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use userAgentRequestDescriptor instead') +const UserAgentRequest$json = { + '1': 'UserAgentRequest', + '2': [ + {'1': 'id', '3': 16, '4': 1, '5': 5, '10': 'id'}, + { + '1': 'auth', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.auth.Request', + '9': 0, + '10': 'auth' + }, + { + '1': 'vault', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.vault.Request', + '9': 0, + '10': 'vault' + }, + { + '1': 'evm', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.evm.Request', + '9': 0, + '10': 'evm' + }, + { + '1': 'sdk_client', + '3': 4, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.Request', + '9': 0, + '10': 'sdkClient' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `UserAgentRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List userAgentRequestDescriptor = $convert.base64Decode( + 'ChBVc2VyQWdlbnRSZXF1ZXN0Eg4KAmlkGBAgASgFUgJpZBI2CgRhdXRoGAEgASgLMiAuYXJiaX' + 'Rlci51c2VyX2FnZW50LmF1dGguUmVxdWVzdEgAUgRhdXRoEjkKBXZhdWx0GAIgASgLMiEuYXJi' + 'aXRlci51c2VyX2FnZW50LnZhdWx0LlJlcXVlc3RIAFIFdmF1bHQSMwoDZXZtGAMgASgLMh8uYX' + 'JiaXRlci51c2VyX2FnZW50LmV2bS5SZXF1ZXN0SABSA2V2bRJHCgpzZGtfY2xpZW50GAQgASgL' + 'MiYuYXJiaXRlci51c2VyX2FnZW50LnNka19jbGllbnQuUmVxdWVzdEgAUglzZGtDbGllbnRCCQ' + 'oHcGF5bG9hZA=='); + +@$core.Deprecated('Use userAgentResponseDescriptor instead') +const UserAgentResponse$json = { + '1': 'UserAgentResponse', + '2': [ + {'1': 'id', '3': 16, '4': 1, '5': 5, '9': 1, '10': 'id', '17': true}, + { + '1': 'auth', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.auth.Response', + '9': 0, + '10': 'auth' + }, + { + '1': 'vault', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.vault.Response', + '9': 0, + '10': 'vault' + }, + { + '1': 'evm', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.evm.Response', + '9': 0, + '10': 'evm' + }, + { + '1': 'sdk_client', + '3': 4, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.Response', + '9': 0, + '10': 'sdkClient' + }, + ], + '8': [ + {'1': 'payload'}, + {'1': '_id'}, + ], +}; + +/// Descriptor for `UserAgentResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List userAgentResponseDescriptor = $convert.base64Decode( + 'ChFVc2VyQWdlbnRSZXNwb25zZRITCgJpZBgQIAEoBUgBUgJpZIgBARI3CgRhdXRoGAEgASgLMi' + 'EuYXJiaXRlci51c2VyX2FnZW50LmF1dGguUmVzcG9uc2VIAFIEYXV0aBI6CgV2YXVsdBgCIAEo' + 'CzIiLmFyYml0ZXIudXNlcl9hZ2VudC52YXVsdC5SZXNwb25zZUgAUgV2YXVsdBI0CgNldm0YAy' + 'ABKAsyIC5hcmJpdGVyLnVzZXJfYWdlbnQuZXZtLlJlc3BvbnNlSABSA2V2bRJICgpzZGtfY2xp' + 'ZW50GAQgASgLMicuYXJiaXRlci51c2VyX2FnZW50LnNka19jbGllbnQuUmVzcG9uc2VIAFIJc2' + 'RrQ2xpZW50QgkKB3BheWxvYWRCBQoDX2lk'); diff --git a/useragent/lib/proto/user_agent/auth.pb.dart b/useragent/lib/proto/user_agent/auth.pb.dart index c89b8c5..a6a2243 100644 --- a/useragent/lib/proto/user_agent/auth.pb.dart +++ b/useragent/lib/proto/user_agent/auth.pb.dart @@ -1,394 +1,394 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/auth.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:fixnum/fixnum.dart' as $fixnum; -import 'package:protobuf/protobuf.dart' as $pb; - -import 'auth.pbenum.dart'; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -export 'auth.pbenum.dart'; - -class AuthChallengeRequest extends $pb.GeneratedMessage { - factory AuthChallengeRequest({ - $core.List<$core.int>? pubkey, - $core.String? bootstrapToken, - }) { - final result = create(); - if (pubkey != null) result.pubkey = pubkey; - if (bootstrapToken != null) result.bootstrapToken = bootstrapToken; - return result; - } - - AuthChallengeRequest._(); - - factory AuthChallengeRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory AuthChallengeRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'AuthChallengeRequest', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.auth'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) - ..aOS(2, _omitFieldNames ? '' : 'bootstrapToken') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallengeRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallengeRequest copyWith(void Function(AuthChallengeRequest) updates) => - super.copyWith((message) => updates(message as AuthChallengeRequest)) - as AuthChallengeRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static AuthChallengeRequest create() => AuthChallengeRequest._(); - @$core.override - AuthChallengeRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static AuthChallengeRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static AuthChallengeRequest? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get pubkey => $_getN(0); - @$pb.TagNumber(1) - set pubkey($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasPubkey() => $_has(0); - @$pb.TagNumber(1) - void clearPubkey() => $_clearField(1); - - @$pb.TagNumber(2) - $core.String get bootstrapToken => $_getSZ(1); - @$pb.TagNumber(2) - set bootstrapToken($core.String value) => $_setString(1, value); - @$pb.TagNumber(2) - $core.bool hasBootstrapToken() => $_has(1); - @$pb.TagNumber(2) - void clearBootstrapToken() => $_clearField(2); -} - -class AuthChallenge extends $pb.GeneratedMessage { - factory AuthChallenge({ - $fixnum.Int64? timestampNanos, - $core.List<$core.int>? random, - }) { - final result = create(); - if (timestampNanos != null) result.timestampNanos = timestampNanos; - if (random != null) result.random = random; - return result; - } - - AuthChallenge._(); - - factory AuthChallenge.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory AuthChallenge.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'AuthChallenge', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.auth'), - createEmptyInstance: create) - ..a<$fixnum.Int64>( - 1, _omitFieldNames ? '' : 'timestampNanos', $pb.PbFieldType.OU6, - defaultOrMaker: $fixnum.Int64.ZERO) - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'random', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallenge clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallenge copyWith(void Function(AuthChallenge) updates) => - super.copyWith((message) => updates(message as AuthChallenge)) - as AuthChallenge; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static AuthChallenge create() => AuthChallenge._(); - @$core.override - AuthChallenge createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static AuthChallenge getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static AuthChallenge? _defaultInstance; - - @$pb.TagNumber(1) - $fixnum.Int64 get timestampNanos => $_getI64(0); - @$pb.TagNumber(1) - set timestampNanos($fixnum.Int64 value) => $_setInt64(0, value); - @$pb.TagNumber(1) - $core.bool hasTimestampNanos() => $_has(0); - @$pb.TagNumber(1) - void clearTimestampNanos() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get random => $_getN(1); - @$pb.TagNumber(2) - set random($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasRandom() => $_has(1); - @$pb.TagNumber(2) - void clearRandom() => $_clearField(2); -} - -class AuthChallengeSolution extends $pb.GeneratedMessage { - factory AuthChallengeSolution({ - $core.List<$core.int>? signature, - }) { - final result = create(); - if (signature != null) result.signature = signature; - return result; - } - - AuthChallengeSolution._(); - - factory AuthChallengeSolution.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory AuthChallengeSolution.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'AuthChallengeSolution', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.auth'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallengeSolution clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - AuthChallengeSolution copyWith( - void Function(AuthChallengeSolution) updates) => - super.copyWith((message) => updates(message as AuthChallengeSolution)) - as AuthChallengeSolution; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static AuthChallengeSolution create() => AuthChallengeSolution._(); - @$core.override - AuthChallengeSolution createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static AuthChallengeSolution getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static AuthChallengeSolution? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get signature => $_getN(0); - @$pb.TagNumber(1) - set signature($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasSignature() => $_has(0); - @$pb.TagNumber(1) - void clearSignature() => $_clearField(1); -} - -enum Request_Payload { challengeRequest, challengeSolution, notSet } - -class Request extends $pb.GeneratedMessage { - factory Request({ - AuthChallengeRequest? challengeRequest, - AuthChallengeSolution? challengeSolution, - }) { - final result = create(); - if (challengeRequest != null) result.challengeRequest = challengeRequest; - if (challengeSolution != null) result.challengeSolution = challengeSolution; - return result; - } - - Request._(); - - factory Request.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Request.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { - 1: Request_Payload.challengeRequest, - 2: Request_Payload.challengeSolution, - 0: Request_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Request', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.auth'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'challengeRequest', - subBuilder: AuthChallengeRequest.create) - ..aOM(2, _omitFieldNames ? '' : 'challengeSolution', - subBuilder: AuthChallengeSolution.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request copyWith(void Function(Request) updates) => - super.copyWith((message) => updates(message as Request)) as Request; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Request create() => Request._(); - @$core.override - Request createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Request getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Request? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - AuthChallengeRequest get challengeRequest => $_getN(0); - @$pb.TagNumber(1) - set challengeRequest(AuthChallengeRequest value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasChallengeRequest() => $_has(0); - @$pb.TagNumber(1) - void clearChallengeRequest() => $_clearField(1); - @$pb.TagNumber(1) - AuthChallengeRequest ensureChallengeRequest() => $_ensure(0); - - @$pb.TagNumber(2) - AuthChallengeSolution get challengeSolution => $_getN(1); - @$pb.TagNumber(2) - set challengeSolution(AuthChallengeSolution value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasChallengeSolution() => $_has(1); - @$pb.TagNumber(2) - void clearChallengeSolution() => $_clearField(2); - @$pb.TagNumber(2) - AuthChallengeSolution ensureChallengeSolution() => $_ensure(1); -} - -enum Response_Payload { challenge, result, notSet } - -class Response extends $pb.GeneratedMessage { - factory Response({ - AuthChallenge? challenge, - AuthResult? result, - }) { - final result$ = create(); - if (challenge != null) result$.challenge = challenge; - if (result != null) result$.result = result; - return result$; - } - - Response._(); - - factory Response.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Response.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { - 1: Response_Payload.challenge, - 2: Response_Payload.result, - 0: Response_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Response', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.auth'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'challenge', - subBuilder: AuthChallenge.create) - ..aE(2, _omitFieldNames ? '' : 'result', - enumValues: AuthResult.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response copyWith(void Function(Response) updates) => - super.copyWith((message) => updates(message as Response)) as Response; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Response create() => Response._(); - @$core.override - Response createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Response getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Response? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - AuthChallenge get challenge => $_getN(0); - @$pb.TagNumber(1) - set challenge(AuthChallenge value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasChallenge() => $_has(0); - @$pb.TagNumber(1) - void clearChallenge() => $_clearField(1); - @$pb.TagNumber(1) - AuthChallenge ensureChallenge() => $_ensure(0); - - @$pb.TagNumber(2) - AuthResult get result => $_getN(1); - @$pb.TagNumber(2) - set result(AuthResult value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasResult() => $_has(1); - @$pb.TagNumber(2) - void clearResult() => $_clearField(2); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent/auth.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; + +import 'auth.pbenum.dart'; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +export 'auth.pbenum.dart'; + +class AuthChallengeRequest extends $pb.GeneratedMessage { + factory AuthChallengeRequest({ + $core.List<$core.int>? pubkey, + $core.String? bootstrapToken, + }) { + final result = create(); + if (pubkey != null) result.pubkey = pubkey; + if (bootstrapToken != null) result.bootstrapToken = bootstrapToken; + return result; + } + + AuthChallengeRequest._(); + + factory AuthChallengeRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory AuthChallengeRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'AuthChallengeRequest', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.auth'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) + ..aOS(2, _omitFieldNames ? '' : 'bootstrapToken') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallengeRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallengeRequest copyWith(void Function(AuthChallengeRequest) updates) => + super.copyWith((message) => updates(message as AuthChallengeRequest)) + as AuthChallengeRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static AuthChallengeRequest create() => AuthChallengeRequest._(); + @$core.override + AuthChallengeRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static AuthChallengeRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static AuthChallengeRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get pubkey => $_getN(0); + @$pb.TagNumber(1) + set pubkey($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasPubkey() => $_has(0); + @$pb.TagNumber(1) + void clearPubkey() => $_clearField(1); + + @$pb.TagNumber(2) + $core.String get bootstrapToken => $_getSZ(1); + @$pb.TagNumber(2) + set bootstrapToken($core.String value) => $_setString(1, value); + @$pb.TagNumber(2) + $core.bool hasBootstrapToken() => $_has(1); + @$pb.TagNumber(2) + void clearBootstrapToken() => $_clearField(2); +} + +class AuthChallenge extends $pb.GeneratedMessage { + factory AuthChallenge({ + $fixnum.Int64? timestampNanos, + $core.List<$core.int>? random, + }) { + final result = create(); + if (timestampNanos != null) result.timestampNanos = timestampNanos; + if (random != null) result.random = random; + return result; + } + + AuthChallenge._(); + + factory AuthChallenge.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory AuthChallenge.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'AuthChallenge', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.auth'), + createEmptyInstance: create) + ..a<$fixnum.Int64>( + 1, _omitFieldNames ? '' : 'timestampNanos', $pb.PbFieldType.OU6, + defaultOrMaker: $fixnum.Int64.ZERO) + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'random', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallenge clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallenge copyWith(void Function(AuthChallenge) updates) => + super.copyWith((message) => updates(message as AuthChallenge)) + as AuthChallenge; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static AuthChallenge create() => AuthChallenge._(); + @$core.override + AuthChallenge createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static AuthChallenge getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static AuthChallenge? _defaultInstance; + + @$pb.TagNumber(1) + $fixnum.Int64 get timestampNanos => $_getI64(0); + @$pb.TagNumber(1) + set timestampNanos($fixnum.Int64 value) => $_setInt64(0, value); + @$pb.TagNumber(1) + $core.bool hasTimestampNanos() => $_has(0); + @$pb.TagNumber(1) + void clearTimestampNanos() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get random => $_getN(1); + @$pb.TagNumber(2) + set random($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasRandom() => $_has(1); + @$pb.TagNumber(2) + void clearRandom() => $_clearField(2); +} + +class AuthChallengeSolution extends $pb.GeneratedMessage { + factory AuthChallengeSolution({ + $core.List<$core.int>? signature, + }) { + final result = create(); + if (signature != null) result.signature = signature; + return result; + } + + AuthChallengeSolution._(); + + factory AuthChallengeSolution.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory AuthChallengeSolution.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'AuthChallengeSolution', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.auth'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'signature', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallengeSolution clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + AuthChallengeSolution copyWith( + void Function(AuthChallengeSolution) updates) => + super.copyWith((message) => updates(message as AuthChallengeSolution)) + as AuthChallengeSolution; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static AuthChallengeSolution create() => AuthChallengeSolution._(); + @$core.override + AuthChallengeSolution createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static AuthChallengeSolution getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static AuthChallengeSolution? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get signature => $_getN(0); + @$pb.TagNumber(1) + set signature($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasSignature() => $_has(0); + @$pb.TagNumber(1) + void clearSignature() => $_clearField(1); +} + +enum Request_Payload { challengeRequest, challengeSolution, notSet } + +class Request extends $pb.GeneratedMessage { + factory Request({ + AuthChallengeRequest? challengeRequest, + AuthChallengeSolution? challengeSolution, + }) { + final result = create(); + if (challengeRequest != null) result.challengeRequest = challengeRequest; + if (challengeSolution != null) result.challengeSolution = challengeSolution; + return result; + } + + Request._(); + + factory Request.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Request.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { + 1: Request_Payload.challengeRequest, + 2: Request_Payload.challengeSolution, + 0: Request_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Request', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.auth'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'challengeRequest', + subBuilder: AuthChallengeRequest.create) + ..aOM(2, _omitFieldNames ? '' : 'challengeSolution', + subBuilder: AuthChallengeSolution.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request copyWith(void Function(Request) updates) => + super.copyWith((message) => updates(message as Request)) as Request; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Request create() => Request._(); + @$core.override + Request createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Request getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Request? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + AuthChallengeRequest get challengeRequest => $_getN(0); + @$pb.TagNumber(1) + set challengeRequest(AuthChallengeRequest value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasChallengeRequest() => $_has(0); + @$pb.TagNumber(1) + void clearChallengeRequest() => $_clearField(1); + @$pb.TagNumber(1) + AuthChallengeRequest ensureChallengeRequest() => $_ensure(0); + + @$pb.TagNumber(2) + AuthChallengeSolution get challengeSolution => $_getN(1); + @$pb.TagNumber(2) + set challengeSolution(AuthChallengeSolution value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasChallengeSolution() => $_has(1); + @$pb.TagNumber(2) + void clearChallengeSolution() => $_clearField(2); + @$pb.TagNumber(2) + AuthChallengeSolution ensureChallengeSolution() => $_ensure(1); +} + +enum Response_Payload { challenge, result, notSet } + +class Response extends $pb.GeneratedMessage { + factory Response({ + AuthChallenge? challenge, + AuthResult? result, + }) { + final result$ = create(); + if (challenge != null) result$.challenge = challenge; + if (result != null) result$.result = result; + return result$; + } + + Response._(); + + factory Response.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Response.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { + 1: Response_Payload.challenge, + 2: Response_Payload.result, + 0: Response_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Response', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.auth'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'challenge', + subBuilder: AuthChallenge.create) + ..aE(2, _omitFieldNames ? '' : 'result', + enumValues: AuthResult.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response copyWith(void Function(Response) updates) => + super.copyWith((message) => updates(message as Response)) as Response; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Response create() => Response._(); + @$core.override + Response createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Response getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Response? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + AuthChallenge get challenge => $_getN(0); + @$pb.TagNumber(1) + set challenge(AuthChallenge value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasChallenge() => $_has(0); + @$pb.TagNumber(1) + void clearChallenge() => $_clearField(1); + @$pb.TagNumber(1) + AuthChallenge ensureChallenge() => $_ensure(0); + + @$pb.TagNumber(2) + AuthResult get result => $_getN(1); + @$pb.TagNumber(2) + set result(AuthResult value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasResult() => $_has(1); + @$pb.TagNumber(2) + void clearResult() => $_clearField(2); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/user_agent/auth.pbenum.dart b/useragent/lib/proto/user_agent/auth.pbenum.dart index 835ae9c..d667fbd 100644 --- a/useragent/lib/proto/user_agent/auth.pbenum.dart +++ b/useragent/lib/proto/user_agent/auth.pbenum.dart @@ -1,52 +1,52 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/auth.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -class AuthResult extends $pb.ProtobufEnum { - static const AuthResult AUTH_RESULT_UNSPECIFIED = - AuthResult._(0, _omitEnumNames ? '' : 'AUTH_RESULT_UNSPECIFIED'); - static const AuthResult AUTH_RESULT_SUCCESS = - AuthResult._(1, _omitEnumNames ? '' : 'AUTH_RESULT_SUCCESS'); - static const AuthResult AUTH_RESULT_INVALID_KEY = - AuthResult._(2, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_KEY'); - static const AuthResult AUTH_RESULT_INVALID_SIGNATURE = - AuthResult._(3, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_SIGNATURE'); - static const AuthResult AUTH_RESULT_BOOTSTRAP_REQUIRED = - AuthResult._(4, _omitEnumNames ? '' : 'AUTH_RESULT_BOOTSTRAP_REQUIRED'); - static const AuthResult AUTH_RESULT_TOKEN_INVALID = - AuthResult._(5, _omitEnumNames ? '' : 'AUTH_RESULT_TOKEN_INVALID'); - static const AuthResult AUTH_RESULT_INTERNAL = - AuthResult._(6, _omitEnumNames ? '' : 'AUTH_RESULT_INTERNAL'); - - static const $core.List values = [ - AUTH_RESULT_UNSPECIFIED, - AUTH_RESULT_SUCCESS, - AUTH_RESULT_INVALID_KEY, - AUTH_RESULT_INVALID_SIGNATURE, - AUTH_RESULT_BOOTSTRAP_REQUIRED, - AUTH_RESULT_TOKEN_INVALID, - AUTH_RESULT_INTERNAL, - ]; - - static final $core.List _byValue = - $pb.ProtobufEnum.$_initByValueList(values, 6); - static AuthResult? valueOf($core.int value) => - value < 0 || value >= _byValue.length ? null : _byValue[value]; - - const AuthResult._(super.value, super.name); -} - -const $core.bool _omitEnumNames = - $core.bool.fromEnvironment('protobuf.omit_enum_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent/auth.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class AuthResult extends $pb.ProtobufEnum { + static const AuthResult AUTH_RESULT_UNSPECIFIED = + AuthResult._(0, _omitEnumNames ? '' : 'AUTH_RESULT_UNSPECIFIED'); + static const AuthResult AUTH_RESULT_SUCCESS = + AuthResult._(1, _omitEnumNames ? '' : 'AUTH_RESULT_SUCCESS'); + static const AuthResult AUTH_RESULT_INVALID_KEY = + AuthResult._(2, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_KEY'); + static const AuthResult AUTH_RESULT_INVALID_SIGNATURE = + AuthResult._(3, _omitEnumNames ? '' : 'AUTH_RESULT_INVALID_SIGNATURE'); + static const AuthResult AUTH_RESULT_BOOTSTRAP_REQUIRED = + AuthResult._(4, _omitEnumNames ? '' : 'AUTH_RESULT_BOOTSTRAP_REQUIRED'); + static const AuthResult AUTH_RESULT_TOKEN_INVALID = + AuthResult._(5, _omitEnumNames ? '' : 'AUTH_RESULT_TOKEN_INVALID'); + static const AuthResult AUTH_RESULT_INTERNAL = + AuthResult._(6, _omitEnumNames ? '' : 'AUTH_RESULT_INTERNAL'); + + static const $core.List values = [ + AUTH_RESULT_UNSPECIFIED, + AUTH_RESULT_SUCCESS, + AUTH_RESULT_INVALID_KEY, + AUTH_RESULT_INVALID_SIGNATURE, + AUTH_RESULT_BOOTSTRAP_REQUIRED, + AUTH_RESULT_TOKEN_INVALID, + AUTH_RESULT_INTERNAL, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 6); + static AuthResult? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const AuthResult._(super.value, super.name); +} + +const $core.bool _omitEnumNames = + $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/useragent/lib/proto/user_agent/auth.pbjson.dart b/useragent/lib/proto/user_agent/auth.pbjson.dart index 87d0979..2118b49 100644 --- a/useragent/lib/proto/user_agent/auth.pbjson.dart +++ b/useragent/lib/proto/user_agent/auth.pbjson.dart @@ -1,159 +1,159 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/auth.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use authResultDescriptor instead') -const AuthResult$json = { - '1': 'AuthResult', - '2': [ - {'1': 'AUTH_RESULT_UNSPECIFIED', '2': 0}, - {'1': 'AUTH_RESULT_SUCCESS', '2': 1}, - {'1': 'AUTH_RESULT_INVALID_KEY', '2': 2}, - {'1': 'AUTH_RESULT_INVALID_SIGNATURE', '2': 3}, - {'1': 'AUTH_RESULT_BOOTSTRAP_REQUIRED', '2': 4}, - {'1': 'AUTH_RESULT_TOKEN_INVALID', '2': 5}, - {'1': 'AUTH_RESULT_INTERNAL', '2': 6}, - ], -}; - -/// Descriptor for `AuthResult`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List authResultDescriptor = $convert.base64Decode( - 'CgpBdXRoUmVzdWx0EhsKF0FVVEhfUkVTVUxUX1VOU1BFQ0lGSUVEEAASFwoTQVVUSF9SRVNVTF' - 'RfU1VDQ0VTUxABEhsKF0FVVEhfUkVTVUxUX0lOVkFMSURfS0VZEAISIQodQVVUSF9SRVNVTFRf' - 'SU5WQUxJRF9TSUdOQVRVUkUQAxIiCh5BVVRIX1JFU1VMVF9CT09UU1RSQVBfUkVRVUlSRUQQBB' - 'IdChlBVVRIX1JFU1VMVF9UT0tFTl9JTlZBTElEEAUSGAoUQVVUSF9SRVNVTFRfSU5URVJOQUwQ' - 'Bg=='); - -@$core.Deprecated('Use authChallengeRequestDescriptor instead') -const AuthChallengeRequest$json = { - '1': 'AuthChallengeRequest', - '2': [ - {'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'}, - { - '1': 'bootstrap_token', - '3': 2, - '4': 1, - '5': 9, - '9': 0, - '10': 'bootstrapToken', - '17': true - }, - ], - '8': [ - {'1': '_bootstrap_token'}, - ], -}; - -/// Descriptor for `AuthChallengeRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List authChallengeRequestDescriptor = $convert.base64Decode( - 'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRIsCg9ib290c3' - 'RyYXBfdG9rZW4YAiABKAlIAFIOYm9vdHN0cmFwVG9rZW6IAQFCEgoQX2Jvb3RzdHJhcF90b2tl' - 'bg=='); - -@$core.Deprecated('Use authChallengeDescriptor instead') -const AuthChallenge$json = { - '1': 'AuthChallenge', - '2': [ - {'1': 'timestamp_nanos', '3': 1, '4': 1, '5': 4, '10': 'timestampNanos'}, - {'1': 'random', '3': 2, '4': 1, '5': 12, '10': 'random'}, - ], -}; - -/// Descriptor for `AuthChallenge`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List authChallengeDescriptor = $convert.base64Decode( - 'Cg1BdXRoQ2hhbGxlbmdlEicKD3RpbWVzdGFtcF9uYW5vcxgBIAEoBFIOdGltZXN0YW1wTmFub3' - 'MSFgoGcmFuZG9tGAIgASgMUgZyYW5kb20='); - -@$core.Deprecated('Use authChallengeSolutionDescriptor instead') -const AuthChallengeSolution$json = { - '1': 'AuthChallengeSolution', - '2': [ - {'1': 'signature', '3': 1, '4': 1, '5': 12, '10': 'signature'}, - ], -}; - -/// Descriptor for `AuthChallengeSolution`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List authChallengeSolutionDescriptor = $convert.base64Decode( - 'ChVBdXRoQ2hhbGxlbmdlU29sdXRpb24SHAoJc2lnbmF0dXJlGAEgASgMUglzaWduYXR1cmU='); - -@$core.Deprecated('Use requestDescriptor instead') -const Request$json = { - '1': 'Request', - '2': [ - { - '1': 'challenge_request', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.auth.AuthChallengeRequest', - '9': 0, - '10': 'challengeRequest' - }, - { - '1': 'challenge_solution', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.auth.AuthChallengeSolution', - '9': 0, - '10': 'challengeSolution' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( - 'CgdSZXF1ZXN0ElwKEWNoYWxsZW5nZV9yZXF1ZXN0GAEgASgLMi0uYXJiaXRlci51c2VyX2FnZW' - '50LmF1dGguQXV0aENoYWxsZW5nZVJlcXVlc3RIAFIQY2hhbGxlbmdlUmVxdWVzdBJfChJjaGFs' - 'bGVuZ2Vfc29sdXRpb24YAiABKAsyLi5hcmJpdGVyLnVzZXJfYWdlbnQuYXV0aC5BdXRoQ2hhbG' - 'xlbmdlU29sdXRpb25IAFIRY2hhbGxlbmdlU29sdXRpb25CCQoHcGF5bG9hZA=='); - -@$core.Deprecated('Use responseDescriptor instead') -const Response$json = { - '1': 'Response', - '2': [ - { - '1': 'challenge', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.auth.AuthChallenge', - '9': 0, - '10': 'challenge' - }, - { - '1': 'result', - '3': 2, - '4': 1, - '5': 14, - '6': '.arbiter.user_agent.auth.AuthResult', - '9': 0, - '10': 'result' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( - 'CghSZXNwb25zZRJGCgljaGFsbGVuZ2UYASABKAsyJi5hcmJpdGVyLnVzZXJfYWdlbnQuYXV0aC' - '5BdXRoQ2hhbGxlbmdlSABSCWNoYWxsZW5nZRI9CgZyZXN1bHQYAiABKA4yIy5hcmJpdGVyLnVz' - 'ZXJfYWdlbnQuYXV0aC5BdXRoUmVzdWx0SABSBnJlc3VsdEIJCgdwYXlsb2Fk'); +// This is a generated file - do not edit. +// +// Generated from user_agent/auth.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use authResultDescriptor instead') +const AuthResult$json = { + '1': 'AuthResult', + '2': [ + {'1': 'AUTH_RESULT_UNSPECIFIED', '2': 0}, + {'1': 'AUTH_RESULT_SUCCESS', '2': 1}, + {'1': 'AUTH_RESULT_INVALID_KEY', '2': 2}, + {'1': 'AUTH_RESULT_INVALID_SIGNATURE', '2': 3}, + {'1': 'AUTH_RESULT_BOOTSTRAP_REQUIRED', '2': 4}, + {'1': 'AUTH_RESULT_TOKEN_INVALID', '2': 5}, + {'1': 'AUTH_RESULT_INTERNAL', '2': 6}, + ], +}; + +/// Descriptor for `AuthResult`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List authResultDescriptor = $convert.base64Decode( + 'CgpBdXRoUmVzdWx0EhsKF0FVVEhfUkVTVUxUX1VOU1BFQ0lGSUVEEAASFwoTQVVUSF9SRVNVTF' + 'RfU1VDQ0VTUxABEhsKF0FVVEhfUkVTVUxUX0lOVkFMSURfS0VZEAISIQodQVVUSF9SRVNVTFRf' + 'SU5WQUxJRF9TSUdOQVRVUkUQAxIiCh5BVVRIX1JFU1VMVF9CT09UU1RSQVBfUkVRVUlSRUQQBB' + 'IdChlBVVRIX1JFU1VMVF9UT0tFTl9JTlZBTElEEAUSGAoUQVVUSF9SRVNVTFRfSU5URVJOQUwQ' + 'Bg=='); + +@$core.Deprecated('Use authChallengeRequestDescriptor instead') +const AuthChallengeRequest$json = { + '1': 'AuthChallengeRequest', + '2': [ + {'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'}, + { + '1': 'bootstrap_token', + '3': 2, + '4': 1, + '5': 9, + '9': 0, + '10': 'bootstrapToken', + '17': true + }, + ], + '8': [ + {'1': '_bootstrap_token'}, + ], +}; + +/// Descriptor for `AuthChallengeRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List authChallengeRequestDescriptor = $convert.base64Decode( + 'ChRBdXRoQ2hhbGxlbmdlUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRIsCg9ib290c3' + 'RyYXBfdG9rZW4YAiABKAlIAFIOYm9vdHN0cmFwVG9rZW6IAQFCEgoQX2Jvb3RzdHJhcF90b2tl' + 'bg=='); + +@$core.Deprecated('Use authChallengeDescriptor instead') +const AuthChallenge$json = { + '1': 'AuthChallenge', + '2': [ + {'1': 'timestamp_nanos', '3': 1, '4': 1, '5': 4, '10': 'timestampNanos'}, + {'1': 'random', '3': 2, '4': 1, '5': 12, '10': 'random'}, + ], +}; + +/// Descriptor for `AuthChallenge`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List authChallengeDescriptor = $convert.base64Decode( + 'Cg1BdXRoQ2hhbGxlbmdlEicKD3RpbWVzdGFtcF9uYW5vcxgBIAEoBFIOdGltZXN0YW1wTmFub3' + 'MSFgoGcmFuZG9tGAIgASgMUgZyYW5kb20='); + +@$core.Deprecated('Use authChallengeSolutionDescriptor instead') +const AuthChallengeSolution$json = { + '1': 'AuthChallengeSolution', + '2': [ + {'1': 'signature', '3': 1, '4': 1, '5': 12, '10': 'signature'}, + ], +}; + +/// Descriptor for `AuthChallengeSolution`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List authChallengeSolutionDescriptor = $convert.base64Decode( + 'ChVBdXRoQ2hhbGxlbmdlU29sdXRpb24SHAoJc2lnbmF0dXJlGAEgASgMUglzaWduYXR1cmU='); + +@$core.Deprecated('Use requestDescriptor instead') +const Request$json = { + '1': 'Request', + '2': [ + { + '1': 'challenge_request', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.auth.AuthChallengeRequest', + '9': 0, + '10': 'challengeRequest' + }, + { + '1': 'challenge_solution', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.auth.AuthChallengeSolution', + '9': 0, + '10': 'challengeSolution' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( + 'CgdSZXF1ZXN0ElwKEWNoYWxsZW5nZV9yZXF1ZXN0GAEgASgLMi0uYXJiaXRlci51c2VyX2FnZW' + '50LmF1dGguQXV0aENoYWxsZW5nZVJlcXVlc3RIAFIQY2hhbGxlbmdlUmVxdWVzdBJfChJjaGFs' + 'bGVuZ2Vfc29sdXRpb24YAiABKAsyLi5hcmJpdGVyLnVzZXJfYWdlbnQuYXV0aC5BdXRoQ2hhbG' + 'xlbmdlU29sdXRpb25IAFIRY2hhbGxlbmdlU29sdXRpb25CCQoHcGF5bG9hZA=='); + +@$core.Deprecated('Use responseDescriptor instead') +const Response$json = { + '1': 'Response', + '2': [ + { + '1': 'challenge', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.auth.AuthChallenge', + '9': 0, + '10': 'challenge' + }, + { + '1': 'result', + '3': 2, + '4': 1, + '5': 14, + '6': '.arbiter.user_agent.auth.AuthResult', + '9': 0, + '10': 'result' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( + 'CghSZXNwb25zZRJGCgljaGFsbGVuZ2UYASABKAsyJi5hcmJpdGVyLnVzZXJfYWdlbnQuYXV0aC' + '5BdXRoQ2hhbGxlbmdlSABSCWNoYWxsZW5nZRI9CgZyZXN1bHQYAiABKA4yIy5hcmJpdGVyLnVz' + 'ZXJfYWdlbnQuYXV0aC5BdXRoUmVzdWx0SABSBnJlc3VsdEIJCgdwYXlsb2Fk'); diff --git a/useragent/lib/proto/user_agent/evm.pb.dart b/useragent/lib/proto/user_agent/evm.pb.dart index 1819ca7..28c8439 100644 --- a/useragent/lib/proto/user_agent/evm.pb.dart +++ b/useragent/lib/proto/user_agent/evm.pb.dart @@ -1,432 +1,432 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; -import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $1; - -import '../evm.pb.dart' as $0; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -class SignTransactionRequest extends $pb.GeneratedMessage { - factory SignTransactionRequest({ - $core.int? clientId, - $0.EvmSignTransactionRequest? request, - }) { - final result = create(); - if (clientId != null) result.clientId = clientId; - if (request != null) result.request = request; - return result; - } - - SignTransactionRequest._(); - - factory SignTransactionRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory SignTransactionRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'SignTransactionRequest', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.evm'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'clientId') - ..aOM<$0.EvmSignTransactionRequest>(2, _omitFieldNames ? '' : 'request', - subBuilder: $0.EvmSignTransactionRequest.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - SignTransactionRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - SignTransactionRequest copyWith( - void Function(SignTransactionRequest) updates) => - super.copyWith((message) => updates(message as SignTransactionRequest)) - as SignTransactionRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static SignTransactionRequest create() => SignTransactionRequest._(); - @$core.override - SignTransactionRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static SignTransactionRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static SignTransactionRequest? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get clientId => $_getIZ(0); - @$pb.TagNumber(1) - set clientId($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasClientId() => $_has(0); - @$pb.TagNumber(1) - void clearClientId() => $_clearField(1); - - @$pb.TagNumber(2) - $0.EvmSignTransactionRequest get request => $_getN(1); - @$pb.TagNumber(2) - set request($0.EvmSignTransactionRequest value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasRequest() => $_has(1); - @$pb.TagNumber(2) - void clearRequest() => $_clearField(2); - @$pb.TagNumber(2) - $0.EvmSignTransactionRequest ensureRequest() => $_ensure(1); -} - -enum Request_Payload { - walletCreate, - walletList, - grantCreate, - grantDelete, - grantList, - signTransaction, - notSet -} - -class Request extends $pb.GeneratedMessage { - factory Request({ - $1.Empty? walletCreate, - $1.Empty? walletList, - $0.EvmGrantCreateRequest? grantCreate, - $0.EvmGrantDeleteRequest? grantDelete, - $0.EvmGrantListRequest? grantList, - SignTransactionRequest? signTransaction, - }) { - final result = create(); - if (walletCreate != null) result.walletCreate = walletCreate; - if (walletList != null) result.walletList = walletList; - if (grantCreate != null) result.grantCreate = grantCreate; - if (grantDelete != null) result.grantDelete = grantDelete; - if (grantList != null) result.grantList = grantList; - if (signTransaction != null) result.signTransaction = signTransaction; - return result; - } - - Request._(); - - factory Request.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Request.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { - 1: Request_Payload.walletCreate, - 2: Request_Payload.walletList, - 3: Request_Payload.grantCreate, - 4: Request_Payload.grantDelete, - 5: Request_Payload.grantList, - 6: Request_Payload.signTransaction, - 0: Request_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Request', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4, 5, 6]) - ..aOM<$1.Empty>(1, _omitFieldNames ? '' : 'walletCreate', - subBuilder: $1.Empty.create) - ..aOM<$1.Empty>(2, _omitFieldNames ? '' : 'walletList', - subBuilder: $1.Empty.create) - ..aOM<$0.EvmGrantCreateRequest>(3, _omitFieldNames ? '' : 'grantCreate', - subBuilder: $0.EvmGrantCreateRequest.create) - ..aOM<$0.EvmGrantDeleteRequest>(4, _omitFieldNames ? '' : 'grantDelete', - subBuilder: $0.EvmGrantDeleteRequest.create) - ..aOM<$0.EvmGrantListRequest>(5, _omitFieldNames ? '' : 'grantList', - subBuilder: $0.EvmGrantListRequest.create) - ..aOM(6, _omitFieldNames ? '' : 'signTransaction', - subBuilder: SignTransactionRequest.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request copyWith(void Function(Request) updates) => - super.copyWith((message) => updates(message as Request)) as Request; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Request create() => Request._(); - @$core.override - Request createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Request getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Request? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - @$pb.TagNumber(5) - @$pb.TagNumber(6) - Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - @$pb.TagNumber(5) - @$pb.TagNumber(6) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $1.Empty get walletCreate => $_getN(0); - @$pb.TagNumber(1) - set walletCreate($1.Empty value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasWalletCreate() => $_has(0); - @$pb.TagNumber(1) - void clearWalletCreate() => $_clearField(1); - @$pb.TagNumber(1) - $1.Empty ensureWalletCreate() => $_ensure(0); - - @$pb.TagNumber(2) - $1.Empty get walletList => $_getN(1); - @$pb.TagNumber(2) - set walletList($1.Empty value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasWalletList() => $_has(1); - @$pb.TagNumber(2) - void clearWalletList() => $_clearField(2); - @$pb.TagNumber(2) - $1.Empty ensureWalletList() => $_ensure(1); - - @$pb.TagNumber(3) - $0.EvmGrantCreateRequest get grantCreate => $_getN(2); - @$pb.TagNumber(3) - set grantCreate($0.EvmGrantCreateRequest value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasGrantCreate() => $_has(2); - @$pb.TagNumber(3) - void clearGrantCreate() => $_clearField(3); - @$pb.TagNumber(3) - $0.EvmGrantCreateRequest ensureGrantCreate() => $_ensure(2); - - @$pb.TagNumber(4) - $0.EvmGrantDeleteRequest get grantDelete => $_getN(3); - @$pb.TagNumber(4) - set grantDelete($0.EvmGrantDeleteRequest value) => $_setField(4, value); - @$pb.TagNumber(4) - $core.bool hasGrantDelete() => $_has(3); - @$pb.TagNumber(4) - void clearGrantDelete() => $_clearField(4); - @$pb.TagNumber(4) - $0.EvmGrantDeleteRequest ensureGrantDelete() => $_ensure(3); - - @$pb.TagNumber(5) - $0.EvmGrantListRequest get grantList => $_getN(4); - @$pb.TagNumber(5) - set grantList($0.EvmGrantListRequest value) => $_setField(5, value); - @$pb.TagNumber(5) - $core.bool hasGrantList() => $_has(4); - @$pb.TagNumber(5) - void clearGrantList() => $_clearField(5); - @$pb.TagNumber(5) - $0.EvmGrantListRequest ensureGrantList() => $_ensure(4); - - @$pb.TagNumber(6) - SignTransactionRequest get signTransaction => $_getN(5); - @$pb.TagNumber(6) - set signTransaction(SignTransactionRequest value) => $_setField(6, value); - @$pb.TagNumber(6) - $core.bool hasSignTransaction() => $_has(5); - @$pb.TagNumber(6) - void clearSignTransaction() => $_clearField(6); - @$pb.TagNumber(6) - SignTransactionRequest ensureSignTransaction() => $_ensure(5); -} - -enum Response_Payload { - walletCreate, - walletList, - grantCreate, - grantDelete, - grantList, - signTransaction, - notSet -} - -class Response extends $pb.GeneratedMessage { - factory Response({ - $0.WalletCreateResponse? walletCreate, - $0.WalletListResponse? walletList, - $0.EvmGrantCreateResponse? grantCreate, - $0.EvmGrantDeleteResponse? grantDelete, - $0.EvmGrantListResponse? grantList, - $0.EvmSignTransactionResponse? signTransaction, - }) { - final result = create(); - if (walletCreate != null) result.walletCreate = walletCreate; - if (walletList != null) result.walletList = walletList; - if (grantCreate != null) result.grantCreate = grantCreate; - if (grantDelete != null) result.grantDelete = grantDelete; - if (grantList != null) result.grantList = grantList; - if (signTransaction != null) result.signTransaction = signTransaction; - return result; - } - - Response._(); - - factory Response.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Response.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { - 1: Response_Payload.walletCreate, - 2: Response_Payload.walletList, - 3: Response_Payload.grantCreate, - 4: Response_Payload.grantDelete, - 5: Response_Payload.grantList, - 6: Response_Payload.signTransaction, - 0: Response_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Response', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.evm'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4, 5, 6]) - ..aOM<$0.WalletCreateResponse>(1, _omitFieldNames ? '' : 'walletCreate', - subBuilder: $0.WalletCreateResponse.create) - ..aOM<$0.WalletListResponse>(2, _omitFieldNames ? '' : 'walletList', - subBuilder: $0.WalletListResponse.create) - ..aOM<$0.EvmGrantCreateResponse>(3, _omitFieldNames ? '' : 'grantCreate', - subBuilder: $0.EvmGrantCreateResponse.create) - ..aOM<$0.EvmGrantDeleteResponse>(4, _omitFieldNames ? '' : 'grantDelete', - subBuilder: $0.EvmGrantDeleteResponse.create) - ..aOM<$0.EvmGrantListResponse>(5, _omitFieldNames ? '' : 'grantList', - subBuilder: $0.EvmGrantListResponse.create) - ..aOM<$0.EvmSignTransactionResponse>( - 6, _omitFieldNames ? '' : 'signTransaction', - subBuilder: $0.EvmSignTransactionResponse.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response copyWith(void Function(Response) updates) => - super.copyWith((message) => updates(message as Response)) as Response; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Response create() => Response._(); - @$core.override - Response createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Response getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Response? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - @$pb.TagNumber(5) - @$pb.TagNumber(6) - Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - @$pb.TagNumber(5) - @$pb.TagNumber(6) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $0.WalletCreateResponse get walletCreate => $_getN(0); - @$pb.TagNumber(1) - set walletCreate($0.WalletCreateResponse value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasWalletCreate() => $_has(0); - @$pb.TagNumber(1) - void clearWalletCreate() => $_clearField(1); - @$pb.TagNumber(1) - $0.WalletCreateResponse ensureWalletCreate() => $_ensure(0); - - @$pb.TagNumber(2) - $0.WalletListResponse get walletList => $_getN(1); - @$pb.TagNumber(2) - set walletList($0.WalletListResponse value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasWalletList() => $_has(1); - @$pb.TagNumber(2) - void clearWalletList() => $_clearField(2); - @$pb.TagNumber(2) - $0.WalletListResponse ensureWalletList() => $_ensure(1); - - @$pb.TagNumber(3) - $0.EvmGrantCreateResponse get grantCreate => $_getN(2); - @$pb.TagNumber(3) - set grantCreate($0.EvmGrantCreateResponse value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasGrantCreate() => $_has(2); - @$pb.TagNumber(3) - void clearGrantCreate() => $_clearField(3); - @$pb.TagNumber(3) - $0.EvmGrantCreateResponse ensureGrantCreate() => $_ensure(2); - - @$pb.TagNumber(4) - $0.EvmGrantDeleteResponse get grantDelete => $_getN(3); - @$pb.TagNumber(4) - set grantDelete($0.EvmGrantDeleteResponse value) => $_setField(4, value); - @$pb.TagNumber(4) - $core.bool hasGrantDelete() => $_has(3); - @$pb.TagNumber(4) - void clearGrantDelete() => $_clearField(4); - @$pb.TagNumber(4) - $0.EvmGrantDeleteResponse ensureGrantDelete() => $_ensure(3); - - @$pb.TagNumber(5) - $0.EvmGrantListResponse get grantList => $_getN(4); - @$pb.TagNumber(5) - set grantList($0.EvmGrantListResponse value) => $_setField(5, value); - @$pb.TagNumber(5) - $core.bool hasGrantList() => $_has(4); - @$pb.TagNumber(5) - void clearGrantList() => $_clearField(5); - @$pb.TagNumber(5) - $0.EvmGrantListResponse ensureGrantList() => $_ensure(4); - - @$pb.TagNumber(6) - $0.EvmSignTransactionResponse get signTransaction => $_getN(5); - @$pb.TagNumber(6) - set signTransaction($0.EvmSignTransactionResponse value) => - $_setField(6, value); - @$pb.TagNumber(6) - $core.bool hasSignTransaction() => $_has(5); - @$pb.TagNumber(6) - void clearSignTransaction() => $_clearField(6); - @$pb.TagNumber(6) - $0.EvmSignTransactionResponse ensureSignTransaction() => $_ensure(5); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent/evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $1; + +import '../evm.pb.dart' as $0; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +class SignTransactionRequest extends $pb.GeneratedMessage { + factory SignTransactionRequest({ + $core.int? clientId, + $0.EvmSignTransactionRequest? request, + }) { + final result = create(); + if (clientId != null) result.clientId = clientId; + if (request != null) result.request = request; + return result; + } + + SignTransactionRequest._(); + + factory SignTransactionRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory SignTransactionRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'SignTransactionRequest', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.evm'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'clientId') + ..aOM<$0.EvmSignTransactionRequest>(2, _omitFieldNames ? '' : 'request', + subBuilder: $0.EvmSignTransactionRequest.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + SignTransactionRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + SignTransactionRequest copyWith( + void Function(SignTransactionRequest) updates) => + super.copyWith((message) => updates(message as SignTransactionRequest)) + as SignTransactionRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static SignTransactionRequest create() => SignTransactionRequest._(); + @$core.override + SignTransactionRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static SignTransactionRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static SignTransactionRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get clientId => $_getIZ(0); + @$pb.TagNumber(1) + set clientId($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasClientId() => $_has(0); + @$pb.TagNumber(1) + void clearClientId() => $_clearField(1); + + @$pb.TagNumber(2) + $0.EvmSignTransactionRequest get request => $_getN(1); + @$pb.TagNumber(2) + set request($0.EvmSignTransactionRequest value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasRequest() => $_has(1); + @$pb.TagNumber(2) + void clearRequest() => $_clearField(2); + @$pb.TagNumber(2) + $0.EvmSignTransactionRequest ensureRequest() => $_ensure(1); +} + +enum Request_Payload { + walletCreate, + walletList, + grantCreate, + grantDelete, + grantList, + signTransaction, + notSet +} + +class Request extends $pb.GeneratedMessage { + factory Request({ + $1.Empty? walletCreate, + $1.Empty? walletList, + $0.EvmGrantCreateRequest? grantCreate, + $0.EvmGrantDeleteRequest? grantDelete, + $0.EvmGrantListRequest? grantList, + SignTransactionRequest? signTransaction, + }) { + final result = create(); + if (walletCreate != null) result.walletCreate = walletCreate; + if (walletList != null) result.walletList = walletList; + if (grantCreate != null) result.grantCreate = grantCreate; + if (grantDelete != null) result.grantDelete = grantDelete; + if (grantList != null) result.grantList = grantList; + if (signTransaction != null) result.signTransaction = signTransaction; + return result; + } + + Request._(); + + factory Request.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Request.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { + 1: Request_Payload.walletCreate, + 2: Request_Payload.walletList, + 3: Request_Payload.grantCreate, + 4: Request_Payload.grantDelete, + 5: Request_Payload.grantList, + 6: Request_Payload.signTransaction, + 0: Request_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Request', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3, 4, 5, 6]) + ..aOM<$1.Empty>(1, _omitFieldNames ? '' : 'walletCreate', + subBuilder: $1.Empty.create) + ..aOM<$1.Empty>(2, _omitFieldNames ? '' : 'walletList', + subBuilder: $1.Empty.create) + ..aOM<$0.EvmGrantCreateRequest>(3, _omitFieldNames ? '' : 'grantCreate', + subBuilder: $0.EvmGrantCreateRequest.create) + ..aOM<$0.EvmGrantDeleteRequest>(4, _omitFieldNames ? '' : 'grantDelete', + subBuilder: $0.EvmGrantDeleteRequest.create) + ..aOM<$0.EvmGrantListRequest>(5, _omitFieldNames ? '' : 'grantList', + subBuilder: $0.EvmGrantListRequest.create) + ..aOM(6, _omitFieldNames ? '' : 'signTransaction', + subBuilder: SignTransactionRequest.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request copyWith(void Function(Request) updates) => + super.copyWith((message) => updates(message as Request)) as Request; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Request create() => Request._(); + @$core.override + Request createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Request getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Request? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + @$pb.TagNumber(5) + @$pb.TagNumber(6) + Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + @$pb.TagNumber(5) + @$pb.TagNumber(6) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $1.Empty get walletCreate => $_getN(0); + @$pb.TagNumber(1) + set walletCreate($1.Empty value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasWalletCreate() => $_has(0); + @$pb.TagNumber(1) + void clearWalletCreate() => $_clearField(1); + @$pb.TagNumber(1) + $1.Empty ensureWalletCreate() => $_ensure(0); + + @$pb.TagNumber(2) + $1.Empty get walletList => $_getN(1); + @$pb.TagNumber(2) + set walletList($1.Empty value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasWalletList() => $_has(1); + @$pb.TagNumber(2) + void clearWalletList() => $_clearField(2); + @$pb.TagNumber(2) + $1.Empty ensureWalletList() => $_ensure(1); + + @$pb.TagNumber(3) + $0.EvmGrantCreateRequest get grantCreate => $_getN(2); + @$pb.TagNumber(3) + set grantCreate($0.EvmGrantCreateRequest value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasGrantCreate() => $_has(2); + @$pb.TagNumber(3) + void clearGrantCreate() => $_clearField(3); + @$pb.TagNumber(3) + $0.EvmGrantCreateRequest ensureGrantCreate() => $_ensure(2); + + @$pb.TagNumber(4) + $0.EvmGrantDeleteRequest get grantDelete => $_getN(3); + @$pb.TagNumber(4) + set grantDelete($0.EvmGrantDeleteRequest value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasGrantDelete() => $_has(3); + @$pb.TagNumber(4) + void clearGrantDelete() => $_clearField(4); + @$pb.TagNumber(4) + $0.EvmGrantDeleteRequest ensureGrantDelete() => $_ensure(3); + + @$pb.TagNumber(5) + $0.EvmGrantListRequest get grantList => $_getN(4); + @$pb.TagNumber(5) + set grantList($0.EvmGrantListRequest value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasGrantList() => $_has(4); + @$pb.TagNumber(5) + void clearGrantList() => $_clearField(5); + @$pb.TagNumber(5) + $0.EvmGrantListRequest ensureGrantList() => $_ensure(4); + + @$pb.TagNumber(6) + SignTransactionRequest get signTransaction => $_getN(5); + @$pb.TagNumber(6) + set signTransaction(SignTransactionRequest value) => $_setField(6, value); + @$pb.TagNumber(6) + $core.bool hasSignTransaction() => $_has(5); + @$pb.TagNumber(6) + void clearSignTransaction() => $_clearField(6); + @$pb.TagNumber(6) + SignTransactionRequest ensureSignTransaction() => $_ensure(5); +} + +enum Response_Payload { + walletCreate, + walletList, + grantCreate, + grantDelete, + grantList, + signTransaction, + notSet +} + +class Response extends $pb.GeneratedMessage { + factory Response({ + $0.WalletCreateResponse? walletCreate, + $0.WalletListResponse? walletList, + $0.EvmGrantCreateResponse? grantCreate, + $0.EvmGrantDeleteResponse? grantDelete, + $0.EvmGrantListResponse? grantList, + $0.EvmSignTransactionResponse? signTransaction, + }) { + final result = create(); + if (walletCreate != null) result.walletCreate = walletCreate; + if (walletList != null) result.walletList = walletList; + if (grantCreate != null) result.grantCreate = grantCreate; + if (grantDelete != null) result.grantDelete = grantDelete; + if (grantList != null) result.grantList = grantList; + if (signTransaction != null) result.signTransaction = signTransaction; + return result; + } + + Response._(); + + factory Response.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Response.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { + 1: Response_Payload.walletCreate, + 2: Response_Payload.walletList, + 3: Response_Payload.grantCreate, + 4: Response_Payload.grantDelete, + 5: Response_Payload.grantList, + 6: Response_Payload.signTransaction, + 0: Response_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Response', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.evm'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3, 4, 5, 6]) + ..aOM<$0.WalletCreateResponse>(1, _omitFieldNames ? '' : 'walletCreate', + subBuilder: $0.WalletCreateResponse.create) + ..aOM<$0.WalletListResponse>(2, _omitFieldNames ? '' : 'walletList', + subBuilder: $0.WalletListResponse.create) + ..aOM<$0.EvmGrantCreateResponse>(3, _omitFieldNames ? '' : 'grantCreate', + subBuilder: $0.EvmGrantCreateResponse.create) + ..aOM<$0.EvmGrantDeleteResponse>(4, _omitFieldNames ? '' : 'grantDelete', + subBuilder: $0.EvmGrantDeleteResponse.create) + ..aOM<$0.EvmGrantListResponse>(5, _omitFieldNames ? '' : 'grantList', + subBuilder: $0.EvmGrantListResponse.create) + ..aOM<$0.EvmSignTransactionResponse>( + 6, _omitFieldNames ? '' : 'signTransaction', + subBuilder: $0.EvmSignTransactionResponse.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response copyWith(void Function(Response) updates) => + super.copyWith((message) => updates(message as Response)) as Response; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Response create() => Response._(); + @$core.override + Response createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Response getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Response? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + @$pb.TagNumber(5) + @$pb.TagNumber(6) + Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + @$pb.TagNumber(5) + @$pb.TagNumber(6) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $0.WalletCreateResponse get walletCreate => $_getN(0); + @$pb.TagNumber(1) + set walletCreate($0.WalletCreateResponse value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasWalletCreate() => $_has(0); + @$pb.TagNumber(1) + void clearWalletCreate() => $_clearField(1); + @$pb.TagNumber(1) + $0.WalletCreateResponse ensureWalletCreate() => $_ensure(0); + + @$pb.TagNumber(2) + $0.WalletListResponse get walletList => $_getN(1); + @$pb.TagNumber(2) + set walletList($0.WalletListResponse value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasWalletList() => $_has(1); + @$pb.TagNumber(2) + void clearWalletList() => $_clearField(2); + @$pb.TagNumber(2) + $0.WalletListResponse ensureWalletList() => $_ensure(1); + + @$pb.TagNumber(3) + $0.EvmGrantCreateResponse get grantCreate => $_getN(2); + @$pb.TagNumber(3) + set grantCreate($0.EvmGrantCreateResponse value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasGrantCreate() => $_has(2); + @$pb.TagNumber(3) + void clearGrantCreate() => $_clearField(3); + @$pb.TagNumber(3) + $0.EvmGrantCreateResponse ensureGrantCreate() => $_ensure(2); + + @$pb.TagNumber(4) + $0.EvmGrantDeleteResponse get grantDelete => $_getN(3); + @$pb.TagNumber(4) + set grantDelete($0.EvmGrantDeleteResponse value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasGrantDelete() => $_has(3); + @$pb.TagNumber(4) + void clearGrantDelete() => $_clearField(4); + @$pb.TagNumber(4) + $0.EvmGrantDeleteResponse ensureGrantDelete() => $_ensure(3); + + @$pb.TagNumber(5) + $0.EvmGrantListResponse get grantList => $_getN(4); + @$pb.TagNumber(5) + set grantList($0.EvmGrantListResponse value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasGrantList() => $_has(4); + @$pb.TagNumber(5) + void clearGrantList() => $_clearField(5); + @$pb.TagNumber(5) + $0.EvmGrantListResponse ensureGrantList() => $_ensure(4); + + @$pb.TagNumber(6) + $0.EvmSignTransactionResponse get signTransaction => $_getN(5); + @$pb.TagNumber(6) + set signTransaction($0.EvmSignTransactionResponse value) => + $_setField(6, value); + @$pb.TagNumber(6) + $core.bool hasSignTransaction() => $_has(5); + @$pb.TagNumber(6) + void clearSignTransaction() => $_clearField(6); + @$pb.TagNumber(6) + $0.EvmSignTransactionResponse ensureSignTransaction() => $_ensure(5); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/user_agent/evm.pbenum.dart b/useragent/lib/proto/user_agent/evm.pbenum.dart index 9b0fded..5f1ba6d 100644 --- a/useragent/lib/proto/user_agent/evm.pbenum.dart +++ b/useragent/lib/proto/user_agent/evm.pbenum.dart @@ -1,11 +1,11 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// This is a generated file - do not edit. +// +// Generated from user_agent/evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports diff --git a/useragent/lib/proto/user_agent/evm.pbjson.dart b/useragent/lib/proto/user_agent/evm.pbjson.dart index 96739b0..6acc12c 100644 --- a/useragent/lib/proto/user_agent/evm.pbjson.dart +++ b/useragent/lib/proto/user_agent/evm.pbjson.dart @@ -1,190 +1,190 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/evm.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use signTransactionRequestDescriptor instead') -const SignTransactionRequest$json = { - '1': 'SignTransactionRequest', - '2': [ - {'1': 'client_id', '3': 1, '4': 1, '5': 5, '10': 'clientId'}, - { - '1': 'request', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmSignTransactionRequest', - '10': 'request' - }, - ], -}; - -/// Descriptor for `SignTransactionRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List signTransactionRequestDescriptor = $convert.base64Decode( - 'ChZTaWduVHJhbnNhY3Rpb25SZXF1ZXN0EhsKCWNsaWVudF9pZBgBIAEoBVIIY2xpZW50SWQSQA' - 'oHcmVxdWVzdBgCIAEoCzImLmFyYml0ZXIuZXZtLkV2bVNpZ25UcmFuc2FjdGlvblJlcXVlc3RS' - 'B3JlcXVlc3Q='); - -@$core.Deprecated('Use requestDescriptor instead') -const Request$json = { - '1': 'Request', - '2': [ - { - '1': 'wallet_create', - '3': 1, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'walletCreate' - }, - { - '1': 'wallet_list', - '3': 2, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'walletList' - }, - { - '1': 'grant_create', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmGrantCreateRequest', - '9': 0, - '10': 'grantCreate' - }, - { - '1': 'grant_delete', - '3': 4, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmGrantDeleteRequest', - '9': 0, - '10': 'grantDelete' - }, - { - '1': 'grant_list', - '3': 5, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmGrantListRequest', - '9': 0, - '10': 'grantList' - }, - { - '1': 'sign_transaction', - '3': 6, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.evm.SignTransactionRequest', - '9': 0, - '10': 'signTransaction' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( - 'CgdSZXF1ZXN0Ej0KDXdhbGxldF9jcmVhdGUYASABKAsyFi5nb29nbGUucHJvdG9idWYuRW1wdH' - 'lIAFIMd2FsbGV0Q3JlYXRlEjkKC3dhbGxldF9saXN0GAIgASgLMhYuZ29vZ2xlLnByb3RvYnVm' - 'LkVtcHR5SABSCndhbGxldExpc3QSRwoMZ3JhbnRfY3JlYXRlGAMgASgLMiIuYXJiaXRlci5ldm' - '0uRXZtR3JhbnRDcmVhdGVSZXF1ZXN0SABSC2dyYW50Q3JlYXRlEkcKDGdyYW50X2RlbGV0ZRgE' - 'IAEoCzIiLmFyYml0ZXIuZXZtLkV2bUdyYW50RGVsZXRlUmVxdWVzdEgAUgtncmFudERlbGV0ZR' - 'JBCgpncmFudF9saXN0GAUgASgLMiAuYXJiaXRlci5ldm0uRXZtR3JhbnRMaXN0UmVxdWVzdEgA' - 'UglncmFudExpc3QSWwoQc2lnbl90cmFuc2FjdGlvbhgGIAEoCzIuLmFyYml0ZXIudXNlcl9hZ2' - 'VudC5ldm0uU2lnblRyYW5zYWN0aW9uUmVxdWVzdEgAUg9zaWduVHJhbnNhY3Rpb25CCQoHcGF5' - 'bG9hZA=='); - -@$core.Deprecated('Use responseDescriptor instead') -const Response$json = { - '1': 'Response', - '2': [ - { - '1': 'wallet_create', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.evm.WalletCreateResponse', - '9': 0, - '10': 'walletCreate' - }, - { - '1': 'wallet_list', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.evm.WalletListResponse', - '9': 0, - '10': 'walletList' - }, - { - '1': 'grant_create', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmGrantCreateResponse', - '9': 0, - '10': 'grantCreate' - }, - { - '1': 'grant_delete', - '3': 4, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmGrantDeleteResponse', - '9': 0, - '10': 'grantDelete' - }, - { - '1': 'grant_list', - '3': 5, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmGrantListResponse', - '9': 0, - '10': 'grantList' - }, - { - '1': 'sign_transaction', - '3': 6, - '4': 1, - '5': 11, - '6': '.arbiter.evm.EvmSignTransactionResponse', - '9': 0, - '10': 'signTransaction' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( - 'CghSZXNwb25zZRJICg13YWxsZXRfY3JlYXRlGAEgASgLMiEuYXJiaXRlci5ldm0uV2FsbGV0Q3' - 'JlYXRlUmVzcG9uc2VIAFIMd2FsbGV0Q3JlYXRlEkIKC3dhbGxldF9saXN0GAIgASgLMh8uYXJi' - 'aXRlci5ldm0uV2FsbGV0TGlzdFJlc3BvbnNlSABSCndhbGxldExpc3QSSAoMZ3JhbnRfY3JlYX' - 'RlGAMgASgLMiMuYXJiaXRlci5ldm0uRXZtR3JhbnRDcmVhdGVSZXNwb25zZUgAUgtncmFudENy' - 'ZWF0ZRJICgxncmFudF9kZWxldGUYBCABKAsyIy5hcmJpdGVyLmV2bS5Fdm1HcmFudERlbGV0ZV' - 'Jlc3BvbnNlSABSC2dyYW50RGVsZXRlEkIKCmdyYW50X2xpc3QYBSABKAsyIS5hcmJpdGVyLmV2' - 'bS5Fdm1HcmFudExpc3RSZXNwb25zZUgAUglncmFudExpc3QSVAoQc2lnbl90cmFuc2FjdGlvbh' - 'gGIAEoCzInLmFyYml0ZXIuZXZtLkV2bVNpZ25UcmFuc2FjdGlvblJlc3BvbnNlSABSD3NpZ25U' - 'cmFuc2FjdGlvbkIJCgdwYXlsb2Fk'); +// This is a generated file - do not edit. +// +// Generated from user_agent/evm.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use signTransactionRequestDescriptor instead') +const SignTransactionRequest$json = { + '1': 'SignTransactionRequest', + '2': [ + {'1': 'client_id', '3': 1, '4': 1, '5': 5, '10': 'clientId'}, + { + '1': 'request', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmSignTransactionRequest', + '10': 'request' + }, + ], +}; + +/// Descriptor for `SignTransactionRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List signTransactionRequestDescriptor = $convert.base64Decode( + 'ChZTaWduVHJhbnNhY3Rpb25SZXF1ZXN0EhsKCWNsaWVudF9pZBgBIAEoBVIIY2xpZW50SWQSQA' + 'oHcmVxdWVzdBgCIAEoCzImLmFyYml0ZXIuZXZtLkV2bVNpZ25UcmFuc2FjdGlvblJlcXVlc3RS' + 'B3JlcXVlc3Q='); + +@$core.Deprecated('Use requestDescriptor instead') +const Request$json = { + '1': 'Request', + '2': [ + { + '1': 'wallet_create', + '3': 1, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'walletCreate' + }, + { + '1': 'wallet_list', + '3': 2, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'walletList' + }, + { + '1': 'grant_create', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmGrantCreateRequest', + '9': 0, + '10': 'grantCreate' + }, + { + '1': 'grant_delete', + '3': 4, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmGrantDeleteRequest', + '9': 0, + '10': 'grantDelete' + }, + { + '1': 'grant_list', + '3': 5, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmGrantListRequest', + '9': 0, + '10': 'grantList' + }, + { + '1': 'sign_transaction', + '3': 6, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.evm.SignTransactionRequest', + '9': 0, + '10': 'signTransaction' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( + 'CgdSZXF1ZXN0Ej0KDXdhbGxldF9jcmVhdGUYASABKAsyFi5nb29nbGUucHJvdG9idWYuRW1wdH' + 'lIAFIMd2FsbGV0Q3JlYXRlEjkKC3dhbGxldF9saXN0GAIgASgLMhYuZ29vZ2xlLnByb3RvYnVm' + 'LkVtcHR5SABSCndhbGxldExpc3QSRwoMZ3JhbnRfY3JlYXRlGAMgASgLMiIuYXJiaXRlci5ldm' + '0uRXZtR3JhbnRDcmVhdGVSZXF1ZXN0SABSC2dyYW50Q3JlYXRlEkcKDGdyYW50X2RlbGV0ZRgE' + 'IAEoCzIiLmFyYml0ZXIuZXZtLkV2bUdyYW50RGVsZXRlUmVxdWVzdEgAUgtncmFudERlbGV0ZR' + 'JBCgpncmFudF9saXN0GAUgASgLMiAuYXJiaXRlci5ldm0uRXZtR3JhbnRMaXN0UmVxdWVzdEgA' + 'UglncmFudExpc3QSWwoQc2lnbl90cmFuc2FjdGlvbhgGIAEoCzIuLmFyYml0ZXIudXNlcl9hZ2' + 'VudC5ldm0uU2lnblRyYW5zYWN0aW9uUmVxdWVzdEgAUg9zaWduVHJhbnNhY3Rpb25CCQoHcGF5' + 'bG9hZA=='); + +@$core.Deprecated('Use responseDescriptor instead') +const Response$json = { + '1': 'Response', + '2': [ + { + '1': 'wallet_create', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.evm.WalletCreateResponse', + '9': 0, + '10': 'walletCreate' + }, + { + '1': 'wallet_list', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.evm.WalletListResponse', + '9': 0, + '10': 'walletList' + }, + { + '1': 'grant_create', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmGrantCreateResponse', + '9': 0, + '10': 'grantCreate' + }, + { + '1': 'grant_delete', + '3': 4, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmGrantDeleteResponse', + '9': 0, + '10': 'grantDelete' + }, + { + '1': 'grant_list', + '3': 5, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmGrantListResponse', + '9': 0, + '10': 'grantList' + }, + { + '1': 'sign_transaction', + '3': 6, + '4': 1, + '5': 11, + '6': '.arbiter.evm.EvmSignTransactionResponse', + '9': 0, + '10': 'signTransaction' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( + 'CghSZXNwb25zZRJICg13YWxsZXRfY3JlYXRlGAEgASgLMiEuYXJiaXRlci5ldm0uV2FsbGV0Q3' + 'JlYXRlUmVzcG9uc2VIAFIMd2FsbGV0Q3JlYXRlEkIKC3dhbGxldF9saXN0GAIgASgLMh8uYXJi' + 'aXRlci5ldm0uV2FsbGV0TGlzdFJlc3BvbnNlSABSCndhbGxldExpc3QSSAoMZ3JhbnRfY3JlYX' + 'RlGAMgASgLMiMuYXJiaXRlci5ldm0uRXZtR3JhbnRDcmVhdGVSZXNwb25zZUgAUgtncmFudENy' + 'ZWF0ZRJICgxncmFudF9kZWxldGUYBCABKAsyIy5hcmJpdGVyLmV2bS5Fdm1HcmFudERlbGV0ZV' + 'Jlc3BvbnNlSABSC2dyYW50RGVsZXRlEkIKCmdyYW50X2xpc3QYBSABKAsyIS5hcmJpdGVyLmV2' + 'bS5Fdm1HcmFudExpc3RSZXNwb25zZUgAUglncmFudExpc3QSVAoQc2lnbl90cmFuc2FjdGlvbh' + 'gGIAEoCzInLmFyYml0ZXIuZXZtLkV2bVNpZ25UcmFuc2FjdGlvblJlc3BvbnNlSABSD3NpZ25U' + 'cmFuc2FjdGlvbkIJCgdwYXlsb2Fk'); diff --git a/useragent/lib/proto/user_agent/sdk_client.pb.dart b/useragent/lib/proto/user_agent/sdk_client.pb.dart index 1266dbb..40f0d93 100644 --- a/useragent/lib/proto/user_agent/sdk_client.pb.dart +++ b/useragent/lib/proto/user_agent/sdk_client.pb.dart @@ -1,1197 +1,1197 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/sdk_client.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; -import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $1; - -import '../shared/client.pb.dart' as $0; -import 'sdk_client.pbenum.dart'; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -export 'sdk_client.pbenum.dart'; - -class RevokeRequest extends $pb.GeneratedMessage { - factory RevokeRequest({ - $core.int? clientId, - }) { - final result = create(); - if (clientId != null) result.clientId = clientId; - return result; - } - - RevokeRequest._(); - - factory RevokeRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory RevokeRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'RevokeRequest', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'clientId') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - RevokeRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - RevokeRequest copyWith(void Function(RevokeRequest) updates) => - super.copyWith((message) => updates(message as RevokeRequest)) - as RevokeRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static RevokeRequest create() => RevokeRequest._(); - @$core.override - RevokeRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static RevokeRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static RevokeRequest? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get clientId => $_getIZ(0); - @$pb.TagNumber(1) - set clientId($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasClientId() => $_has(0); - @$pb.TagNumber(1) - void clearClientId() => $_clearField(1); -} - -class Entry extends $pb.GeneratedMessage { - factory Entry({ - $core.int? id, - $core.List<$core.int>? pubkey, - $0.ClientInfo? info, - $core.int? createdAt, - }) { - final result = create(); - if (id != null) result.id = id; - if (pubkey != null) result.pubkey = pubkey; - if (info != null) result.info = info; - if (createdAt != null) result.createdAt = createdAt; - return result; - } - - Entry._(); - - factory Entry.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Entry.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Entry', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'id') - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) - ..aOM<$0.ClientInfo>(3, _omitFieldNames ? '' : 'info', - subBuilder: $0.ClientInfo.create) - ..aI(4, _omitFieldNames ? '' : 'createdAt') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Entry clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Entry copyWith(void Function(Entry) updates) => - super.copyWith((message) => updates(message as Entry)) as Entry; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Entry create() => Entry._(); - @$core.override - Entry createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Entry getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Entry? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get id => $_getIZ(0); - @$pb.TagNumber(1) - set id($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasId() => $_has(0); - @$pb.TagNumber(1) - void clearId() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get pubkey => $_getN(1); - @$pb.TagNumber(2) - set pubkey($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasPubkey() => $_has(1); - @$pb.TagNumber(2) - void clearPubkey() => $_clearField(2); - - @$pb.TagNumber(3) - $0.ClientInfo get info => $_getN(2); - @$pb.TagNumber(3) - set info($0.ClientInfo value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasInfo() => $_has(2); - @$pb.TagNumber(3) - void clearInfo() => $_clearField(3); - @$pb.TagNumber(3) - $0.ClientInfo ensureInfo() => $_ensure(2); - - @$pb.TagNumber(4) - $core.int get createdAt => $_getIZ(3); - @$pb.TagNumber(4) - set createdAt($core.int value) => $_setSignedInt32(3, value); - @$pb.TagNumber(4) - $core.bool hasCreatedAt() => $_has(3); - @$pb.TagNumber(4) - void clearCreatedAt() => $_clearField(4); -} - -class List_ extends $pb.GeneratedMessage { - factory List_({ - $core.Iterable? clients, - }) { - final result = create(); - if (clients != null) result.clients.addAll(clients); - return result; - } - - List_._(); - - factory List_.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory List_.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'List', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..pPM(1, _omitFieldNames ? '' : 'clients', subBuilder: Entry.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - List_ clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - List_ copyWith(void Function(List_) updates) => - super.copyWith((message) => updates(message as List_)) as List_; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static List_ create() => List_._(); - @$core.override - List_ createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static List_ getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static List_? _defaultInstance; - - @$pb.TagNumber(1) - $pb.PbList get clients => $_getList(0); -} - -enum RevokeResponse_Result { ok, error, notSet } - -class RevokeResponse extends $pb.GeneratedMessage { - factory RevokeResponse({ - $1.Empty? ok, - Error? error, - }) { - final result = create(); - if (ok != null) result.ok = ok; - if (error != null) result.error = error; - return result; - } - - RevokeResponse._(); - - factory RevokeResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory RevokeResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, RevokeResponse_Result> - _RevokeResponse_ResultByTag = { - 1: RevokeResponse_Result.ok, - 2: RevokeResponse_Result.error, - 0: RevokeResponse_Result.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'RevokeResponse', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM<$1.Empty>(1, _omitFieldNames ? '' : 'ok', subBuilder: $1.Empty.create) - ..aE(2, _omitFieldNames ? '' : 'error', enumValues: Error.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - RevokeResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - RevokeResponse copyWith(void Function(RevokeResponse) updates) => - super.copyWith((message) => updates(message as RevokeResponse)) - as RevokeResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static RevokeResponse create() => RevokeResponse._(); - @$core.override - RevokeResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static RevokeResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static RevokeResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - RevokeResponse_Result whichResult() => - _RevokeResponse_ResultByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearResult() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $1.Empty get ok => $_getN(0); - @$pb.TagNumber(1) - set ok($1.Empty value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasOk() => $_has(0); - @$pb.TagNumber(1) - void clearOk() => $_clearField(1); - @$pb.TagNumber(1) - $1.Empty ensureOk() => $_ensure(0); - - @$pb.TagNumber(2) - Error get error => $_getN(1); - @$pb.TagNumber(2) - set error(Error value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasError() => $_has(1); - @$pb.TagNumber(2) - void clearError() => $_clearField(2); -} - -enum ListResponse_Result { clients, error, notSet } - -class ListResponse extends $pb.GeneratedMessage { - factory ListResponse({ - List_? clients, - Error? error, - }) { - final result = create(); - if (clients != null) result.clients = clients; - if (error != null) result.error = error; - return result; - } - - ListResponse._(); - - factory ListResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory ListResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, ListResponse_Result> - _ListResponse_ResultByTag = { - 1: ListResponse_Result.clients, - 2: ListResponse_Result.error, - 0: ListResponse_Result.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'ListResponse', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'clients', subBuilder: List_.create) - ..aE(2, _omitFieldNames ? '' : 'error', enumValues: Error.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ListResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ListResponse copyWith(void Function(ListResponse) updates) => - super.copyWith((message) => updates(message as ListResponse)) - as ListResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static ListResponse create() => ListResponse._(); - @$core.override - ListResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static ListResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static ListResponse? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - ListResponse_Result whichResult() => - _ListResponse_ResultByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearResult() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - List_ get clients => $_getN(0); - @$pb.TagNumber(1) - set clients(List_ value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasClients() => $_has(0); - @$pb.TagNumber(1) - void clearClients() => $_clearField(1); - @$pb.TagNumber(1) - List_ ensureClients() => $_ensure(0); - - @$pb.TagNumber(2) - Error get error => $_getN(1); - @$pb.TagNumber(2) - set error(Error value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasError() => $_has(1); - @$pb.TagNumber(2) - void clearError() => $_clearField(2); -} - -class ConnectionRequest extends $pb.GeneratedMessage { - factory ConnectionRequest({ - $core.List<$core.int>? pubkey, - $0.ClientInfo? info, - }) { - final result = create(); - if (pubkey != null) result.pubkey = pubkey; - if (info != null) result.info = info; - return result; - } - - ConnectionRequest._(); - - factory ConnectionRequest.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory ConnectionRequest.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'ConnectionRequest', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) - ..aOM<$0.ClientInfo>(2, _omitFieldNames ? '' : 'info', - subBuilder: $0.ClientInfo.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ConnectionRequest clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ConnectionRequest copyWith(void Function(ConnectionRequest) updates) => - super.copyWith((message) => updates(message as ConnectionRequest)) - as ConnectionRequest; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static ConnectionRequest create() => ConnectionRequest._(); - @$core.override - ConnectionRequest createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static ConnectionRequest getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static ConnectionRequest? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get pubkey => $_getN(0); - @$pb.TagNumber(1) - set pubkey($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasPubkey() => $_has(0); - @$pb.TagNumber(1) - void clearPubkey() => $_clearField(1); - - @$pb.TagNumber(2) - $0.ClientInfo get info => $_getN(1); - @$pb.TagNumber(2) - set info($0.ClientInfo value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasInfo() => $_has(1); - @$pb.TagNumber(2) - void clearInfo() => $_clearField(2); - @$pb.TagNumber(2) - $0.ClientInfo ensureInfo() => $_ensure(1); -} - -class ConnectionResponse extends $pb.GeneratedMessage { - factory ConnectionResponse({ - $core.bool? approved, - $core.List<$core.int>? pubkey, - }) { - final result = create(); - if (approved != null) result.approved = approved; - if (pubkey != null) result.pubkey = pubkey; - return result; - } - - ConnectionResponse._(); - - factory ConnectionResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory ConnectionResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'ConnectionResponse', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..aOB(1, _omitFieldNames ? '' : 'approved') - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ConnectionResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ConnectionResponse copyWith(void Function(ConnectionResponse) updates) => - super.copyWith((message) => updates(message as ConnectionResponse)) - as ConnectionResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static ConnectionResponse create() => ConnectionResponse._(); - @$core.override - ConnectionResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static ConnectionResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static ConnectionResponse? _defaultInstance; - - @$pb.TagNumber(1) - $core.bool get approved => $_getBF(0); - @$pb.TagNumber(1) - set approved($core.bool value) => $_setBool(0, value); - @$pb.TagNumber(1) - $core.bool hasApproved() => $_has(0); - @$pb.TagNumber(1) - void clearApproved() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get pubkey => $_getN(1); - @$pb.TagNumber(2) - set pubkey($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasPubkey() => $_has(1); - @$pb.TagNumber(2) - void clearPubkey() => $_clearField(2); -} - -class ConnectionCancel extends $pb.GeneratedMessage { - factory ConnectionCancel({ - $core.List<$core.int>? pubkey, - }) { - final result = create(); - if (pubkey != null) result.pubkey = pubkey; - return result; - } - - ConnectionCancel._(); - - factory ConnectionCancel.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory ConnectionCancel.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'ConnectionCancel', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ConnectionCancel clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ConnectionCancel copyWith(void Function(ConnectionCancel) updates) => - super.copyWith((message) => updates(message as ConnectionCancel)) - as ConnectionCancel; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static ConnectionCancel create() => ConnectionCancel._(); - @$core.override - ConnectionCancel createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static ConnectionCancel getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static ConnectionCancel? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get pubkey => $_getN(0); - @$pb.TagNumber(1) - set pubkey($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasPubkey() => $_has(0); - @$pb.TagNumber(1) - void clearPubkey() => $_clearField(1); -} - -class WalletAccess extends $pb.GeneratedMessage { - factory WalletAccess({ - $core.int? walletId, - $core.int? sdkClientId, - }) { - final result = create(); - if (walletId != null) result.walletId = walletId; - if (sdkClientId != null) result.sdkClientId = sdkClientId; - return result; - } - - WalletAccess._(); - - factory WalletAccess.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory WalletAccess.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'WalletAccess', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'walletId') - ..aI(2, _omitFieldNames ? '' : 'sdkClientId') - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletAccess clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletAccess copyWith(void Function(WalletAccess) updates) => - super.copyWith((message) => updates(message as WalletAccess)) - as WalletAccess; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static WalletAccess create() => WalletAccess._(); - @$core.override - WalletAccess createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static WalletAccess getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static WalletAccess? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get walletId => $_getIZ(0); - @$pb.TagNumber(1) - set walletId($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasWalletId() => $_has(0); - @$pb.TagNumber(1) - void clearWalletId() => $_clearField(1); - - @$pb.TagNumber(2) - $core.int get sdkClientId => $_getIZ(1); - @$pb.TagNumber(2) - set sdkClientId($core.int value) => $_setSignedInt32(1, value); - @$pb.TagNumber(2) - $core.bool hasSdkClientId() => $_has(1); - @$pb.TagNumber(2) - void clearSdkClientId() => $_clearField(2); -} - -class WalletAccessEntry extends $pb.GeneratedMessage { - factory WalletAccessEntry({ - $core.int? id, - WalletAccess? access, - }) { - final result = create(); - if (id != null) result.id = id; - if (access != null) result.access = access; - return result; - } - - WalletAccessEntry._(); - - factory WalletAccessEntry.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory WalletAccessEntry.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'WalletAccessEntry', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..aI(1, _omitFieldNames ? '' : 'id') - ..aOM(2, _omitFieldNames ? '' : 'access', - subBuilder: WalletAccess.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletAccessEntry clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - WalletAccessEntry copyWith(void Function(WalletAccessEntry) updates) => - super.copyWith((message) => updates(message as WalletAccessEntry)) - as WalletAccessEntry; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static WalletAccessEntry create() => WalletAccessEntry._(); - @$core.override - WalletAccessEntry createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static WalletAccessEntry getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static WalletAccessEntry? _defaultInstance; - - @$pb.TagNumber(1) - $core.int get id => $_getIZ(0); - @$pb.TagNumber(1) - set id($core.int value) => $_setSignedInt32(0, value); - @$pb.TagNumber(1) - $core.bool hasId() => $_has(0); - @$pb.TagNumber(1) - void clearId() => $_clearField(1); - - @$pb.TagNumber(2) - WalletAccess get access => $_getN(1); - @$pb.TagNumber(2) - set access(WalletAccess value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasAccess() => $_has(1); - @$pb.TagNumber(2) - void clearAccess() => $_clearField(2); - @$pb.TagNumber(2) - WalletAccess ensureAccess() => $_ensure(1); -} - -class GrantWalletAccess extends $pb.GeneratedMessage { - factory GrantWalletAccess({ - $core.Iterable? accesses, - }) { - final result = create(); - if (accesses != null) result.accesses.addAll(accesses); - return result; - } - - GrantWalletAccess._(); - - factory GrantWalletAccess.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory GrantWalletAccess.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'GrantWalletAccess', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..pPM(1, _omitFieldNames ? '' : 'accesses', - subBuilder: WalletAccess.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - GrantWalletAccess clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - GrantWalletAccess copyWith(void Function(GrantWalletAccess) updates) => - super.copyWith((message) => updates(message as GrantWalletAccess)) - as GrantWalletAccess; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static GrantWalletAccess create() => GrantWalletAccess._(); - @$core.override - GrantWalletAccess createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static GrantWalletAccess getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static GrantWalletAccess? _defaultInstance; - - @$pb.TagNumber(1) - $pb.PbList get accesses => $_getList(0); -} - -class RevokeWalletAccess extends $pb.GeneratedMessage { - factory RevokeWalletAccess({ - $core.Iterable<$core.int>? accesses, - }) { - final result = create(); - if (accesses != null) result.accesses.addAll(accesses); - return result; - } - - RevokeWalletAccess._(); - - factory RevokeWalletAccess.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory RevokeWalletAccess.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'RevokeWalletAccess', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..p<$core.int>(1, _omitFieldNames ? '' : 'accesses', $pb.PbFieldType.K3) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - RevokeWalletAccess clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - RevokeWalletAccess copyWith(void Function(RevokeWalletAccess) updates) => - super.copyWith((message) => updates(message as RevokeWalletAccess)) - as RevokeWalletAccess; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static RevokeWalletAccess create() => RevokeWalletAccess._(); - @$core.override - RevokeWalletAccess createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static RevokeWalletAccess getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static RevokeWalletAccess? _defaultInstance; - - @$pb.TagNumber(1) - $pb.PbList<$core.int> get accesses => $_getList(0); -} - -class ListWalletAccessResponse extends $pb.GeneratedMessage { - factory ListWalletAccessResponse({ - $core.Iterable? accesses, - }) { - final result = create(); - if (accesses != null) result.accesses.addAll(accesses); - return result; - } - - ListWalletAccessResponse._(); - - factory ListWalletAccessResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory ListWalletAccessResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'ListWalletAccessResponse', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..pPM(1, _omitFieldNames ? '' : 'accesses', - subBuilder: WalletAccessEntry.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ListWalletAccessResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - ListWalletAccessResponse copyWith( - void Function(ListWalletAccessResponse) updates) => - super.copyWith((message) => updates(message as ListWalletAccessResponse)) - as ListWalletAccessResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static ListWalletAccessResponse create() => ListWalletAccessResponse._(); - @$core.override - ListWalletAccessResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static ListWalletAccessResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static ListWalletAccessResponse? _defaultInstance; - - @$pb.TagNumber(1) - $pb.PbList get accesses => $_getList(0); -} - -enum Request_Payload { - connectionResponse, - revoke, - list, - grantWalletAccess, - revokeWalletAccess, - listWalletAccess, - notSet -} - -class Request extends $pb.GeneratedMessage { - factory Request({ - ConnectionResponse? connectionResponse, - RevokeRequest? revoke, - $1.Empty? list, - GrantWalletAccess? grantWalletAccess, - RevokeWalletAccess? revokeWalletAccess, - $1.Empty? listWalletAccess, - }) { - final result = create(); - if (connectionResponse != null) - result.connectionResponse = connectionResponse; - if (revoke != null) result.revoke = revoke; - if (list != null) result.list = list; - if (grantWalletAccess != null) result.grantWalletAccess = grantWalletAccess; - if (revokeWalletAccess != null) - result.revokeWalletAccess = revokeWalletAccess; - if (listWalletAccess != null) result.listWalletAccess = listWalletAccess; - return result; - } - - Request._(); - - factory Request.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Request.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { - 1: Request_Payload.connectionResponse, - 2: Request_Payload.revoke, - 3: Request_Payload.list, - 4: Request_Payload.grantWalletAccess, - 5: Request_Payload.revokeWalletAccess, - 6: Request_Payload.listWalletAccess, - 0: Request_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Request', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4, 5, 6]) - ..aOM(1, _omitFieldNames ? '' : 'connectionResponse', - subBuilder: ConnectionResponse.create) - ..aOM(2, _omitFieldNames ? '' : 'revoke', - subBuilder: RevokeRequest.create) - ..aOM<$1.Empty>(3, _omitFieldNames ? '' : 'list', - subBuilder: $1.Empty.create) - ..aOM(4, _omitFieldNames ? '' : 'grantWalletAccess', - subBuilder: GrantWalletAccess.create) - ..aOM(5, _omitFieldNames ? '' : 'revokeWalletAccess', - subBuilder: RevokeWalletAccess.create) - ..aOM<$1.Empty>(6, _omitFieldNames ? '' : 'listWalletAccess', - subBuilder: $1.Empty.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request copyWith(void Function(Request) updates) => - super.copyWith((message) => updates(message as Request)) as Request; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Request create() => Request._(); - @$core.override - Request createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Request getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Request? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - @$pb.TagNumber(5) - @$pb.TagNumber(6) - Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - @$pb.TagNumber(5) - @$pb.TagNumber(6) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - ConnectionResponse get connectionResponse => $_getN(0); - @$pb.TagNumber(1) - set connectionResponse(ConnectionResponse value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasConnectionResponse() => $_has(0); - @$pb.TagNumber(1) - void clearConnectionResponse() => $_clearField(1); - @$pb.TagNumber(1) - ConnectionResponse ensureConnectionResponse() => $_ensure(0); - - @$pb.TagNumber(2) - RevokeRequest get revoke => $_getN(1); - @$pb.TagNumber(2) - set revoke(RevokeRequest value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasRevoke() => $_has(1); - @$pb.TagNumber(2) - void clearRevoke() => $_clearField(2); - @$pb.TagNumber(2) - RevokeRequest ensureRevoke() => $_ensure(1); - - @$pb.TagNumber(3) - $1.Empty get list => $_getN(2); - @$pb.TagNumber(3) - set list($1.Empty value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasList() => $_has(2); - @$pb.TagNumber(3) - void clearList() => $_clearField(3); - @$pb.TagNumber(3) - $1.Empty ensureList() => $_ensure(2); - - @$pb.TagNumber(4) - GrantWalletAccess get grantWalletAccess => $_getN(3); - @$pb.TagNumber(4) - set grantWalletAccess(GrantWalletAccess value) => $_setField(4, value); - @$pb.TagNumber(4) - $core.bool hasGrantWalletAccess() => $_has(3); - @$pb.TagNumber(4) - void clearGrantWalletAccess() => $_clearField(4); - @$pb.TagNumber(4) - GrantWalletAccess ensureGrantWalletAccess() => $_ensure(3); - - @$pb.TagNumber(5) - RevokeWalletAccess get revokeWalletAccess => $_getN(4); - @$pb.TagNumber(5) - set revokeWalletAccess(RevokeWalletAccess value) => $_setField(5, value); - @$pb.TagNumber(5) - $core.bool hasRevokeWalletAccess() => $_has(4); - @$pb.TagNumber(5) - void clearRevokeWalletAccess() => $_clearField(5); - @$pb.TagNumber(5) - RevokeWalletAccess ensureRevokeWalletAccess() => $_ensure(4); - - @$pb.TagNumber(6) - $1.Empty get listWalletAccess => $_getN(5); - @$pb.TagNumber(6) - set listWalletAccess($1.Empty value) => $_setField(6, value); - @$pb.TagNumber(6) - $core.bool hasListWalletAccess() => $_has(5); - @$pb.TagNumber(6) - void clearListWalletAccess() => $_clearField(6); - @$pb.TagNumber(6) - $1.Empty ensureListWalletAccess() => $_ensure(5); -} - -enum Response_Payload { - connectionRequest, - connectionCancel, - revoke, - list, - listWalletAccess, - notSet -} - -class Response extends $pb.GeneratedMessage { - factory Response({ - ConnectionRequest? connectionRequest, - ConnectionCancel? connectionCancel, - RevokeResponse? revoke, - ListResponse? list, - ListWalletAccessResponse? listWalletAccess, - }) { - final result = create(); - if (connectionRequest != null) result.connectionRequest = connectionRequest; - if (connectionCancel != null) result.connectionCancel = connectionCancel; - if (revoke != null) result.revoke = revoke; - if (list != null) result.list = list; - if (listWalletAccess != null) result.listWalletAccess = listWalletAccess; - return result; - } - - Response._(); - - factory Response.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Response.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { - 1: Response_Payload.connectionRequest, - 2: Response_Payload.connectionCancel, - 3: Response_Payload.revoke, - 4: Response_Payload.list, - 5: Response_Payload.listWalletAccess, - 0: Response_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Response', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3, 4, 5]) - ..aOM(1, _omitFieldNames ? '' : 'connectionRequest', - subBuilder: ConnectionRequest.create) - ..aOM(2, _omitFieldNames ? '' : 'connectionCancel', - subBuilder: ConnectionCancel.create) - ..aOM(3, _omitFieldNames ? '' : 'revoke', - subBuilder: RevokeResponse.create) - ..aOM(4, _omitFieldNames ? '' : 'list', - subBuilder: ListResponse.create) - ..aOM( - 5, _omitFieldNames ? '' : 'listWalletAccess', - subBuilder: ListWalletAccessResponse.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response copyWith(void Function(Response) updates) => - super.copyWith((message) => updates(message as Response)) as Response; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Response create() => Response._(); - @$core.override - Response createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Response getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Response? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - @$pb.TagNumber(5) - Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - @$pb.TagNumber(4) - @$pb.TagNumber(5) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - ConnectionRequest get connectionRequest => $_getN(0); - @$pb.TagNumber(1) - set connectionRequest(ConnectionRequest value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasConnectionRequest() => $_has(0); - @$pb.TagNumber(1) - void clearConnectionRequest() => $_clearField(1); - @$pb.TagNumber(1) - ConnectionRequest ensureConnectionRequest() => $_ensure(0); - - @$pb.TagNumber(2) - ConnectionCancel get connectionCancel => $_getN(1); - @$pb.TagNumber(2) - set connectionCancel(ConnectionCancel value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasConnectionCancel() => $_has(1); - @$pb.TagNumber(2) - void clearConnectionCancel() => $_clearField(2); - @$pb.TagNumber(2) - ConnectionCancel ensureConnectionCancel() => $_ensure(1); - - @$pb.TagNumber(3) - RevokeResponse get revoke => $_getN(2); - @$pb.TagNumber(3) - set revoke(RevokeResponse value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasRevoke() => $_has(2); - @$pb.TagNumber(3) - void clearRevoke() => $_clearField(3); - @$pb.TagNumber(3) - RevokeResponse ensureRevoke() => $_ensure(2); - - @$pb.TagNumber(4) - ListResponse get list => $_getN(3); - @$pb.TagNumber(4) - set list(ListResponse value) => $_setField(4, value); - @$pb.TagNumber(4) - $core.bool hasList() => $_has(3); - @$pb.TagNumber(4) - void clearList() => $_clearField(4); - @$pb.TagNumber(4) - ListResponse ensureList() => $_ensure(3); - - @$pb.TagNumber(5) - ListWalletAccessResponse get listWalletAccess => $_getN(4); - @$pb.TagNumber(5) - set listWalletAccess(ListWalletAccessResponse value) => $_setField(5, value); - @$pb.TagNumber(5) - $core.bool hasListWalletAccess() => $_has(4); - @$pb.TagNumber(5) - void clearListWalletAccess() => $_clearField(5); - @$pb.TagNumber(5) - ListWalletAccessResponse ensureListWalletAccess() => $_ensure(4); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent/sdk_client.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $1; + +import '../shared/client.pb.dart' as $0; +import 'sdk_client.pbenum.dart'; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +export 'sdk_client.pbenum.dart'; + +class RevokeRequest extends $pb.GeneratedMessage { + factory RevokeRequest({ + $core.int? clientId, + }) { + final result = create(); + if (clientId != null) result.clientId = clientId; + return result; + } + + RevokeRequest._(); + + factory RevokeRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory RevokeRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'RevokeRequest', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'clientId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + RevokeRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + RevokeRequest copyWith(void Function(RevokeRequest) updates) => + super.copyWith((message) => updates(message as RevokeRequest)) + as RevokeRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static RevokeRequest create() => RevokeRequest._(); + @$core.override + RevokeRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static RevokeRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static RevokeRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get clientId => $_getIZ(0); + @$pb.TagNumber(1) + set clientId($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasClientId() => $_has(0); + @$pb.TagNumber(1) + void clearClientId() => $_clearField(1); +} + +class Entry extends $pb.GeneratedMessage { + factory Entry({ + $core.int? id, + $core.List<$core.int>? pubkey, + $0.ClientInfo? info, + $core.int? createdAt, + }) { + final result = create(); + if (id != null) result.id = id; + if (pubkey != null) result.pubkey = pubkey; + if (info != null) result.info = info; + if (createdAt != null) result.createdAt = createdAt; + return result; + } + + Entry._(); + + factory Entry.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Entry.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Entry', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'id') + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) + ..aOM<$0.ClientInfo>(3, _omitFieldNames ? '' : 'info', + subBuilder: $0.ClientInfo.create) + ..aI(4, _omitFieldNames ? '' : 'createdAt') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Entry clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Entry copyWith(void Function(Entry) updates) => + super.copyWith((message) => updates(message as Entry)) as Entry; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Entry create() => Entry._(); + @$core.override + Entry createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Entry getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Entry? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get id => $_getIZ(0); + @$pb.TagNumber(1) + set id($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get pubkey => $_getN(1); + @$pb.TagNumber(2) + set pubkey($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasPubkey() => $_has(1); + @$pb.TagNumber(2) + void clearPubkey() => $_clearField(2); + + @$pb.TagNumber(3) + $0.ClientInfo get info => $_getN(2); + @$pb.TagNumber(3) + set info($0.ClientInfo value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasInfo() => $_has(2); + @$pb.TagNumber(3) + void clearInfo() => $_clearField(3); + @$pb.TagNumber(3) + $0.ClientInfo ensureInfo() => $_ensure(2); + + @$pb.TagNumber(4) + $core.int get createdAt => $_getIZ(3); + @$pb.TagNumber(4) + set createdAt($core.int value) => $_setSignedInt32(3, value); + @$pb.TagNumber(4) + $core.bool hasCreatedAt() => $_has(3); + @$pb.TagNumber(4) + void clearCreatedAt() => $_clearField(4); +} + +class List_ extends $pb.GeneratedMessage { + factory List_({ + $core.Iterable? clients, + }) { + final result = create(); + if (clients != null) result.clients.addAll(clients); + return result; + } + + List_._(); + + factory List_.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory List_.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'List', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..pPM(1, _omitFieldNames ? '' : 'clients', subBuilder: Entry.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + List_ clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + List_ copyWith(void Function(List_) updates) => + super.copyWith((message) => updates(message as List_)) as List_; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static List_ create() => List_._(); + @$core.override + List_ createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static List_ getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static List_? _defaultInstance; + + @$pb.TagNumber(1) + $pb.PbList get clients => $_getList(0); +} + +enum RevokeResponse_Result { ok, error, notSet } + +class RevokeResponse extends $pb.GeneratedMessage { + factory RevokeResponse({ + $1.Empty? ok, + Error? error, + }) { + final result = create(); + if (ok != null) result.ok = ok; + if (error != null) result.error = error; + return result; + } + + RevokeResponse._(); + + factory RevokeResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory RevokeResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, RevokeResponse_Result> + _RevokeResponse_ResultByTag = { + 1: RevokeResponse_Result.ok, + 2: RevokeResponse_Result.error, + 0: RevokeResponse_Result.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'RevokeResponse', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM<$1.Empty>(1, _omitFieldNames ? '' : 'ok', subBuilder: $1.Empty.create) + ..aE(2, _omitFieldNames ? '' : 'error', enumValues: Error.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + RevokeResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + RevokeResponse copyWith(void Function(RevokeResponse) updates) => + super.copyWith((message) => updates(message as RevokeResponse)) + as RevokeResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static RevokeResponse create() => RevokeResponse._(); + @$core.override + RevokeResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static RevokeResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static RevokeResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + RevokeResponse_Result whichResult() => + _RevokeResponse_ResultByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearResult() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $1.Empty get ok => $_getN(0); + @$pb.TagNumber(1) + set ok($1.Empty value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasOk() => $_has(0); + @$pb.TagNumber(1) + void clearOk() => $_clearField(1); + @$pb.TagNumber(1) + $1.Empty ensureOk() => $_ensure(0); + + @$pb.TagNumber(2) + Error get error => $_getN(1); + @$pb.TagNumber(2) + set error(Error value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasError() => $_has(1); + @$pb.TagNumber(2) + void clearError() => $_clearField(2); +} + +enum ListResponse_Result { clients, error, notSet } + +class ListResponse extends $pb.GeneratedMessage { + factory ListResponse({ + List_? clients, + Error? error, + }) { + final result = create(); + if (clients != null) result.clients = clients; + if (error != null) result.error = error; + return result; + } + + ListResponse._(); + + factory ListResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory ListResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, ListResponse_Result> + _ListResponse_ResultByTag = { + 1: ListResponse_Result.clients, + 2: ListResponse_Result.error, + 0: ListResponse_Result.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ListResponse', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'clients', subBuilder: List_.create) + ..aE(2, _omitFieldNames ? '' : 'error', enumValues: Error.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ListResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ListResponse copyWith(void Function(ListResponse) updates) => + super.copyWith((message) => updates(message as ListResponse)) + as ListResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ListResponse create() => ListResponse._(); + @$core.override + ListResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static ListResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static ListResponse? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + ListResponse_Result whichResult() => + _ListResponse_ResultByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearResult() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + List_ get clients => $_getN(0); + @$pb.TagNumber(1) + set clients(List_ value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasClients() => $_has(0); + @$pb.TagNumber(1) + void clearClients() => $_clearField(1); + @$pb.TagNumber(1) + List_ ensureClients() => $_ensure(0); + + @$pb.TagNumber(2) + Error get error => $_getN(1); + @$pb.TagNumber(2) + set error(Error value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasError() => $_has(1); + @$pb.TagNumber(2) + void clearError() => $_clearField(2); +} + +class ConnectionRequest extends $pb.GeneratedMessage { + factory ConnectionRequest({ + $core.List<$core.int>? pubkey, + $0.ClientInfo? info, + }) { + final result = create(); + if (pubkey != null) result.pubkey = pubkey; + if (info != null) result.info = info; + return result; + } + + ConnectionRequest._(); + + factory ConnectionRequest.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory ConnectionRequest.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ConnectionRequest', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) + ..aOM<$0.ClientInfo>(2, _omitFieldNames ? '' : 'info', + subBuilder: $0.ClientInfo.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ConnectionRequest clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ConnectionRequest copyWith(void Function(ConnectionRequest) updates) => + super.copyWith((message) => updates(message as ConnectionRequest)) + as ConnectionRequest; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ConnectionRequest create() => ConnectionRequest._(); + @$core.override + ConnectionRequest createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static ConnectionRequest getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static ConnectionRequest? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get pubkey => $_getN(0); + @$pb.TagNumber(1) + set pubkey($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasPubkey() => $_has(0); + @$pb.TagNumber(1) + void clearPubkey() => $_clearField(1); + + @$pb.TagNumber(2) + $0.ClientInfo get info => $_getN(1); + @$pb.TagNumber(2) + set info($0.ClientInfo value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasInfo() => $_has(1); + @$pb.TagNumber(2) + void clearInfo() => $_clearField(2); + @$pb.TagNumber(2) + $0.ClientInfo ensureInfo() => $_ensure(1); +} + +class ConnectionResponse extends $pb.GeneratedMessage { + factory ConnectionResponse({ + $core.bool? approved, + $core.List<$core.int>? pubkey, + }) { + final result = create(); + if (approved != null) result.approved = approved; + if (pubkey != null) result.pubkey = pubkey; + return result; + } + + ConnectionResponse._(); + + factory ConnectionResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory ConnectionResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ConnectionResponse', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..aOB(1, _omitFieldNames ? '' : 'approved') + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ConnectionResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ConnectionResponse copyWith(void Function(ConnectionResponse) updates) => + super.copyWith((message) => updates(message as ConnectionResponse)) + as ConnectionResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ConnectionResponse create() => ConnectionResponse._(); + @$core.override + ConnectionResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static ConnectionResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static ConnectionResponse? _defaultInstance; + + @$pb.TagNumber(1) + $core.bool get approved => $_getBF(0); + @$pb.TagNumber(1) + set approved($core.bool value) => $_setBool(0, value); + @$pb.TagNumber(1) + $core.bool hasApproved() => $_has(0); + @$pb.TagNumber(1) + void clearApproved() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get pubkey => $_getN(1); + @$pb.TagNumber(2) + set pubkey($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasPubkey() => $_has(1); + @$pb.TagNumber(2) + void clearPubkey() => $_clearField(2); +} + +class ConnectionCancel extends $pb.GeneratedMessage { + factory ConnectionCancel({ + $core.List<$core.int>? pubkey, + }) { + final result = create(); + if (pubkey != null) result.pubkey = pubkey; + return result; + } + + ConnectionCancel._(); + + factory ConnectionCancel.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory ConnectionCancel.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ConnectionCancel', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'pubkey', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ConnectionCancel clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ConnectionCancel copyWith(void Function(ConnectionCancel) updates) => + super.copyWith((message) => updates(message as ConnectionCancel)) + as ConnectionCancel; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ConnectionCancel create() => ConnectionCancel._(); + @$core.override + ConnectionCancel createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static ConnectionCancel getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static ConnectionCancel? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get pubkey => $_getN(0); + @$pb.TagNumber(1) + set pubkey($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasPubkey() => $_has(0); + @$pb.TagNumber(1) + void clearPubkey() => $_clearField(1); +} + +class WalletAccess extends $pb.GeneratedMessage { + factory WalletAccess({ + $core.int? walletId, + $core.int? sdkClientId, + }) { + final result = create(); + if (walletId != null) result.walletId = walletId; + if (sdkClientId != null) result.sdkClientId = sdkClientId; + return result; + } + + WalletAccess._(); + + factory WalletAccess.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory WalletAccess.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'WalletAccess', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'walletId') + ..aI(2, _omitFieldNames ? '' : 'sdkClientId') + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletAccess clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletAccess copyWith(void Function(WalletAccess) updates) => + super.copyWith((message) => updates(message as WalletAccess)) + as WalletAccess; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static WalletAccess create() => WalletAccess._(); + @$core.override + WalletAccess createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static WalletAccess getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static WalletAccess? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get walletId => $_getIZ(0); + @$pb.TagNumber(1) + set walletId($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasWalletId() => $_has(0); + @$pb.TagNumber(1) + void clearWalletId() => $_clearField(1); + + @$pb.TagNumber(2) + $core.int get sdkClientId => $_getIZ(1); + @$pb.TagNumber(2) + set sdkClientId($core.int value) => $_setSignedInt32(1, value); + @$pb.TagNumber(2) + $core.bool hasSdkClientId() => $_has(1); + @$pb.TagNumber(2) + void clearSdkClientId() => $_clearField(2); +} + +class WalletAccessEntry extends $pb.GeneratedMessage { + factory WalletAccessEntry({ + $core.int? id, + WalletAccess? access, + }) { + final result = create(); + if (id != null) result.id = id; + if (access != null) result.access = access; + return result; + } + + WalletAccessEntry._(); + + factory WalletAccessEntry.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory WalletAccessEntry.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'WalletAccessEntry', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..aI(1, _omitFieldNames ? '' : 'id') + ..aOM(2, _omitFieldNames ? '' : 'access', + subBuilder: WalletAccess.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletAccessEntry clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + WalletAccessEntry copyWith(void Function(WalletAccessEntry) updates) => + super.copyWith((message) => updates(message as WalletAccessEntry)) + as WalletAccessEntry; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static WalletAccessEntry create() => WalletAccessEntry._(); + @$core.override + WalletAccessEntry createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static WalletAccessEntry getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static WalletAccessEntry? _defaultInstance; + + @$pb.TagNumber(1) + $core.int get id => $_getIZ(0); + @$pb.TagNumber(1) + set id($core.int value) => $_setSignedInt32(0, value); + @$pb.TagNumber(1) + $core.bool hasId() => $_has(0); + @$pb.TagNumber(1) + void clearId() => $_clearField(1); + + @$pb.TagNumber(2) + WalletAccess get access => $_getN(1); + @$pb.TagNumber(2) + set access(WalletAccess value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasAccess() => $_has(1); + @$pb.TagNumber(2) + void clearAccess() => $_clearField(2); + @$pb.TagNumber(2) + WalletAccess ensureAccess() => $_ensure(1); +} + +class GrantWalletAccess extends $pb.GeneratedMessage { + factory GrantWalletAccess({ + $core.Iterable? accesses, + }) { + final result = create(); + if (accesses != null) result.accesses.addAll(accesses); + return result; + } + + GrantWalletAccess._(); + + factory GrantWalletAccess.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory GrantWalletAccess.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'GrantWalletAccess', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..pPM(1, _omitFieldNames ? '' : 'accesses', + subBuilder: WalletAccess.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + GrantWalletAccess clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + GrantWalletAccess copyWith(void Function(GrantWalletAccess) updates) => + super.copyWith((message) => updates(message as GrantWalletAccess)) + as GrantWalletAccess; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static GrantWalletAccess create() => GrantWalletAccess._(); + @$core.override + GrantWalletAccess createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static GrantWalletAccess getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static GrantWalletAccess? _defaultInstance; + + @$pb.TagNumber(1) + $pb.PbList get accesses => $_getList(0); +} + +class RevokeWalletAccess extends $pb.GeneratedMessage { + factory RevokeWalletAccess({ + $core.Iterable<$core.int>? accesses, + }) { + final result = create(); + if (accesses != null) result.accesses.addAll(accesses); + return result; + } + + RevokeWalletAccess._(); + + factory RevokeWalletAccess.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory RevokeWalletAccess.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'RevokeWalletAccess', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..p<$core.int>(1, _omitFieldNames ? '' : 'accesses', $pb.PbFieldType.K3) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + RevokeWalletAccess clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + RevokeWalletAccess copyWith(void Function(RevokeWalletAccess) updates) => + super.copyWith((message) => updates(message as RevokeWalletAccess)) + as RevokeWalletAccess; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static RevokeWalletAccess create() => RevokeWalletAccess._(); + @$core.override + RevokeWalletAccess createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static RevokeWalletAccess getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static RevokeWalletAccess? _defaultInstance; + + @$pb.TagNumber(1) + $pb.PbList<$core.int> get accesses => $_getList(0); +} + +class ListWalletAccessResponse extends $pb.GeneratedMessage { + factory ListWalletAccessResponse({ + $core.Iterable? accesses, + }) { + final result = create(); + if (accesses != null) result.accesses.addAll(accesses); + return result; + } + + ListWalletAccessResponse._(); + + factory ListWalletAccessResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory ListWalletAccessResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'ListWalletAccessResponse', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..pPM(1, _omitFieldNames ? '' : 'accesses', + subBuilder: WalletAccessEntry.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ListWalletAccessResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + ListWalletAccessResponse copyWith( + void Function(ListWalletAccessResponse) updates) => + super.copyWith((message) => updates(message as ListWalletAccessResponse)) + as ListWalletAccessResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ListWalletAccessResponse create() => ListWalletAccessResponse._(); + @$core.override + ListWalletAccessResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static ListWalletAccessResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static ListWalletAccessResponse? _defaultInstance; + + @$pb.TagNumber(1) + $pb.PbList get accesses => $_getList(0); +} + +enum Request_Payload { + connectionResponse, + revoke, + list, + grantWalletAccess, + revokeWalletAccess, + listWalletAccess, + notSet +} + +class Request extends $pb.GeneratedMessage { + factory Request({ + ConnectionResponse? connectionResponse, + RevokeRequest? revoke, + $1.Empty? list, + GrantWalletAccess? grantWalletAccess, + RevokeWalletAccess? revokeWalletAccess, + $1.Empty? listWalletAccess, + }) { + final result = create(); + if (connectionResponse != null) + result.connectionResponse = connectionResponse; + if (revoke != null) result.revoke = revoke; + if (list != null) result.list = list; + if (grantWalletAccess != null) result.grantWalletAccess = grantWalletAccess; + if (revokeWalletAccess != null) + result.revokeWalletAccess = revokeWalletAccess; + if (listWalletAccess != null) result.listWalletAccess = listWalletAccess; + return result; + } + + Request._(); + + factory Request.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Request.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { + 1: Request_Payload.connectionResponse, + 2: Request_Payload.revoke, + 3: Request_Payload.list, + 4: Request_Payload.grantWalletAccess, + 5: Request_Payload.revokeWalletAccess, + 6: Request_Payload.listWalletAccess, + 0: Request_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Request', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3, 4, 5, 6]) + ..aOM(1, _omitFieldNames ? '' : 'connectionResponse', + subBuilder: ConnectionResponse.create) + ..aOM(2, _omitFieldNames ? '' : 'revoke', + subBuilder: RevokeRequest.create) + ..aOM<$1.Empty>(3, _omitFieldNames ? '' : 'list', + subBuilder: $1.Empty.create) + ..aOM(4, _omitFieldNames ? '' : 'grantWalletAccess', + subBuilder: GrantWalletAccess.create) + ..aOM(5, _omitFieldNames ? '' : 'revokeWalletAccess', + subBuilder: RevokeWalletAccess.create) + ..aOM<$1.Empty>(6, _omitFieldNames ? '' : 'listWalletAccess', + subBuilder: $1.Empty.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request copyWith(void Function(Request) updates) => + super.copyWith((message) => updates(message as Request)) as Request; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Request create() => Request._(); + @$core.override + Request createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Request getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Request? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + @$pb.TagNumber(5) + @$pb.TagNumber(6) + Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + @$pb.TagNumber(5) + @$pb.TagNumber(6) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + ConnectionResponse get connectionResponse => $_getN(0); + @$pb.TagNumber(1) + set connectionResponse(ConnectionResponse value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasConnectionResponse() => $_has(0); + @$pb.TagNumber(1) + void clearConnectionResponse() => $_clearField(1); + @$pb.TagNumber(1) + ConnectionResponse ensureConnectionResponse() => $_ensure(0); + + @$pb.TagNumber(2) + RevokeRequest get revoke => $_getN(1); + @$pb.TagNumber(2) + set revoke(RevokeRequest value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasRevoke() => $_has(1); + @$pb.TagNumber(2) + void clearRevoke() => $_clearField(2); + @$pb.TagNumber(2) + RevokeRequest ensureRevoke() => $_ensure(1); + + @$pb.TagNumber(3) + $1.Empty get list => $_getN(2); + @$pb.TagNumber(3) + set list($1.Empty value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasList() => $_has(2); + @$pb.TagNumber(3) + void clearList() => $_clearField(3); + @$pb.TagNumber(3) + $1.Empty ensureList() => $_ensure(2); + + @$pb.TagNumber(4) + GrantWalletAccess get grantWalletAccess => $_getN(3); + @$pb.TagNumber(4) + set grantWalletAccess(GrantWalletAccess value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasGrantWalletAccess() => $_has(3); + @$pb.TagNumber(4) + void clearGrantWalletAccess() => $_clearField(4); + @$pb.TagNumber(4) + GrantWalletAccess ensureGrantWalletAccess() => $_ensure(3); + + @$pb.TagNumber(5) + RevokeWalletAccess get revokeWalletAccess => $_getN(4); + @$pb.TagNumber(5) + set revokeWalletAccess(RevokeWalletAccess value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasRevokeWalletAccess() => $_has(4); + @$pb.TagNumber(5) + void clearRevokeWalletAccess() => $_clearField(5); + @$pb.TagNumber(5) + RevokeWalletAccess ensureRevokeWalletAccess() => $_ensure(4); + + @$pb.TagNumber(6) + $1.Empty get listWalletAccess => $_getN(5); + @$pb.TagNumber(6) + set listWalletAccess($1.Empty value) => $_setField(6, value); + @$pb.TagNumber(6) + $core.bool hasListWalletAccess() => $_has(5); + @$pb.TagNumber(6) + void clearListWalletAccess() => $_clearField(6); + @$pb.TagNumber(6) + $1.Empty ensureListWalletAccess() => $_ensure(5); +} + +enum Response_Payload { + connectionRequest, + connectionCancel, + revoke, + list, + listWalletAccess, + notSet +} + +class Response extends $pb.GeneratedMessage { + factory Response({ + ConnectionRequest? connectionRequest, + ConnectionCancel? connectionCancel, + RevokeResponse? revoke, + ListResponse? list, + ListWalletAccessResponse? listWalletAccess, + }) { + final result = create(); + if (connectionRequest != null) result.connectionRequest = connectionRequest; + if (connectionCancel != null) result.connectionCancel = connectionCancel; + if (revoke != null) result.revoke = revoke; + if (list != null) result.list = list; + if (listWalletAccess != null) result.listWalletAccess = listWalletAccess; + return result; + } + + Response._(); + + factory Response.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Response.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { + 1: Response_Payload.connectionRequest, + 2: Response_Payload.connectionCancel, + 3: Response_Payload.revoke, + 4: Response_Payload.list, + 5: Response_Payload.listWalletAccess, + 0: Response_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Response', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.sdk_client'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3, 4, 5]) + ..aOM(1, _omitFieldNames ? '' : 'connectionRequest', + subBuilder: ConnectionRequest.create) + ..aOM(2, _omitFieldNames ? '' : 'connectionCancel', + subBuilder: ConnectionCancel.create) + ..aOM(3, _omitFieldNames ? '' : 'revoke', + subBuilder: RevokeResponse.create) + ..aOM(4, _omitFieldNames ? '' : 'list', + subBuilder: ListResponse.create) + ..aOM( + 5, _omitFieldNames ? '' : 'listWalletAccess', + subBuilder: ListWalletAccessResponse.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response copyWith(void Function(Response) updates) => + super.copyWith((message) => updates(message as Response)) as Response; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Response create() => Response._(); + @$core.override + Response createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Response getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Response? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + @$pb.TagNumber(5) + Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + @$pb.TagNumber(4) + @$pb.TagNumber(5) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + ConnectionRequest get connectionRequest => $_getN(0); + @$pb.TagNumber(1) + set connectionRequest(ConnectionRequest value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasConnectionRequest() => $_has(0); + @$pb.TagNumber(1) + void clearConnectionRequest() => $_clearField(1); + @$pb.TagNumber(1) + ConnectionRequest ensureConnectionRequest() => $_ensure(0); + + @$pb.TagNumber(2) + ConnectionCancel get connectionCancel => $_getN(1); + @$pb.TagNumber(2) + set connectionCancel(ConnectionCancel value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasConnectionCancel() => $_has(1); + @$pb.TagNumber(2) + void clearConnectionCancel() => $_clearField(2); + @$pb.TagNumber(2) + ConnectionCancel ensureConnectionCancel() => $_ensure(1); + + @$pb.TagNumber(3) + RevokeResponse get revoke => $_getN(2); + @$pb.TagNumber(3) + set revoke(RevokeResponse value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasRevoke() => $_has(2); + @$pb.TagNumber(3) + void clearRevoke() => $_clearField(3); + @$pb.TagNumber(3) + RevokeResponse ensureRevoke() => $_ensure(2); + + @$pb.TagNumber(4) + ListResponse get list => $_getN(3); + @$pb.TagNumber(4) + set list(ListResponse value) => $_setField(4, value); + @$pb.TagNumber(4) + $core.bool hasList() => $_has(3); + @$pb.TagNumber(4) + void clearList() => $_clearField(4); + @$pb.TagNumber(4) + ListResponse ensureList() => $_ensure(3); + + @$pb.TagNumber(5) + ListWalletAccessResponse get listWalletAccess => $_getN(4); + @$pb.TagNumber(5) + set listWalletAccess(ListWalletAccessResponse value) => $_setField(5, value); + @$pb.TagNumber(5) + $core.bool hasListWalletAccess() => $_has(4); + @$pb.TagNumber(5) + void clearListWalletAccess() => $_clearField(5); + @$pb.TagNumber(5) + ListWalletAccessResponse ensureListWalletAccess() => $_ensure(4); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/user_agent/sdk_client.pbenum.dart b/useragent/lib/proto/user_agent/sdk_client.pbenum.dart index d8bf9bd..a081fd9 100644 --- a/useragent/lib/proto/user_agent/sdk_client.pbenum.dart +++ b/useragent/lib/proto/user_agent/sdk_client.pbenum.dart @@ -1,46 +1,46 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/sdk_client.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -class Error extends $pb.ProtobufEnum { - static const Error ERROR_UNSPECIFIED = - Error._(0, _omitEnumNames ? '' : 'ERROR_UNSPECIFIED'); - static const Error ERROR_ALREADY_EXISTS = - Error._(1, _omitEnumNames ? '' : 'ERROR_ALREADY_EXISTS'); - static const Error ERROR_NOT_FOUND = - Error._(2, _omitEnumNames ? '' : 'ERROR_NOT_FOUND'); - static const Error ERROR_HAS_RELATED_DATA = - Error._(3, _omitEnumNames ? '' : 'ERROR_HAS_RELATED_DATA'); - static const Error ERROR_INTERNAL = - Error._(4, _omitEnumNames ? '' : 'ERROR_INTERNAL'); - - static const $core.List values = [ - ERROR_UNSPECIFIED, - ERROR_ALREADY_EXISTS, - ERROR_NOT_FOUND, - ERROR_HAS_RELATED_DATA, - ERROR_INTERNAL, - ]; - - static final $core.List _byValue = - $pb.ProtobufEnum.$_initByValueList(values, 4); - static Error? valueOf($core.int value) => - value < 0 || value >= _byValue.length ? null : _byValue[value]; - - const Error._(super.value, super.name); -} - -const $core.bool _omitEnumNames = - $core.bool.fromEnvironment('protobuf.omit_enum_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent/sdk_client.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class Error extends $pb.ProtobufEnum { + static const Error ERROR_UNSPECIFIED = + Error._(0, _omitEnumNames ? '' : 'ERROR_UNSPECIFIED'); + static const Error ERROR_ALREADY_EXISTS = + Error._(1, _omitEnumNames ? '' : 'ERROR_ALREADY_EXISTS'); + static const Error ERROR_NOT_FOUND = + Error._(2, _omitEnumNames ? '' : 'ERROR_NOT_FOUND'); + static const Error ERROR_HAS_RELATED_DATA = + Error._(3, _omitEnumNames ? '' : 'ERROR_HAS_RELATED_DATA'); + static const Error ERROR_INTERNAL = + Error._(4, _omitEnumNames ? '' : 'ERROR_INTERNAL'); + + static const $core.List values = [ + ERROR_UNSPECIFIED, + ERROR_ALREADY_EXISTS, + ERROR_NOT_FOUND, + ERROR_HAS_RELATED_DATA, + ERROR_INTERNAL, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 4); + static Error? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const Error._(super.value, super.name); +} + +const $core.bool _omitEnumNames = + $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/useragent/lib/proto/user_agent/sdk_client.pbjson.dart b/useragent/lib/proto/user_agent/sdk_client.pbjson.dart index 6a33194..505e649 100644 --- a/useragent/lib/proto/user_agent/sdk_client.pbjson.dart +++ b/useragent/lib/proto/user_agent/sdk_client.pbjson.dart @@ -1,438 +1,438 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/sdk_client.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use errorDescriptor instead') -const Error$json = { - '1': 'Error', - '2': [ - {'1': 'ERROR_UNSPECIFIED', '2': 0}, - {'1': 'ERROR_ALREADY_EXISTS', '2': 1}, - {'1': 'ERROR_NOT_FOUND', '2': 2}, - {'1': 'ERROR_HAS_RELATED_DATA', '2': 3}, - {'1': 'ERROR_INTERNAL', '2': 4}, - ], -}; - -/// Descriptor for `Error`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List errorDescriptor = $convert.base64Decode( - 'CgVFcnJvchIVChFFUlJPUl9VTlNQRUNJRklFRBAAEhgKFEVSUk9SX0FMUkVBRFlfRVhJU1RTEA' - 'ESEwoPRVJST1JfTk9UX0ZPVU5EEAISGgoWRVJST1JfSEFTX1JFTEFURURfREFUQRADEhIKDkVS' - 'Uk9SX0lOVEVSTkFMEAQ='); - -@$core.Deprecated('Use revokeRequestDescriptor instead') -const RevokeRequest$json = { - '1': 'RevokeRequest', - '2': [ - {'1': 'client_id', '3': 1, '4': 1, '5': 5, '10': 'clientId'}, - ], -}; - -/// Descriptor for `RevokeRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List revokeRequestDescriptor = $convert.base64Decode( - 'Cg1SZXZva2VSZXF1ZXN0EhsKCWNsaWVudF9pZBgBIAEoBVIIY2xpZW50SWQ='); - -@$core.Deprecated('Use entryDescriptor instead') -const Entry$json = { - '1': 'Entry', - '2': [ - {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, - {'1': 'pubkey', '3': 2, '4': 1, '5': 12, '10': 'pubkey'}, - { - '1': 'info', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.shared.ClientInfo', - '10': 'info' - }, - {'1': 'created_at', '3': 4, '4': 1, '5': 5, '10': 'createdAt'}, - ], -}; - -/// Descriptor for `Entry`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List entryDescriptor = $convert.base64Decode( - 'CgVFbnRyeRIOCgJpZBgBIAEoBVICaWQSFgoGcHVia2V5GAIgASgMUgZwdWJrZXkSLgoEaW5mbx' - 'gDIAEoCzIaLmFyYml0ZXIuc2hhcmVkLkNsaWVudEluZm9SBGluZm8SHQoKY3JlYXRlZF9hdBgE' - 'IAEoBVIJY3JlYXRlZEF0'); - -@$core.Deprecated('Use list_Descriptor instead') -const List_$json = { - '1': 'List', - '2': [ - { - '1': 'clients', - '3': 1, - '4': 3, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.Entry', - '10': 'clients' - }, - ], -}; - -/// Descriptor for `List`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List list_Descriptor = $convert.base64Decode( - 'CgRMaXN0Ej4KB2NsaWVudHMYASADKAsyJC5hcmJpdGVyLnVzZXJfYWdlbnQuc2RrX2NsaWVudC' - '5FbnRyeVIHY2xpZW50cw=='); - -@$core.Deprecated('Use revokeResponseDescriptor instead') -const RevokeResponse$json = { - '1': 'RevokeResponse', - '2': [ - { - '1': 'ok', - '3': 1, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'ok' - }, - { - '1': 'error', - '3': 2, - '4': 1, - '5': 14, - '6': '.arbiter.user_agent.sdk_client.Error', - '9': 0, - '10': 'error' - }, - ], - '8': [ - {'1': 'result'}, - ], -}; - -/// Descriptor for `RevokeResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List revokeResponseDescriptor = $convert.base64Decode( - 'Cg5SZXZva2VSZXNwb25zZRIoCgJvaxgBIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAUg' - 'JvaxI8CgVlcnJvchgCIAEoDjIkLmFyYml0ZXIudXNlcl9hZ2VudC5zZGtfY2xpZW50LkVycm9y' - 'SABSBWVycm9yQggKBnJlc3VsdA=='); - -@$core.Deprecated('Use listResponseDescriptor instead') -const ListResponse$json = { - '1': 'ListResponse', - '2': [ - { - '1': 'clients', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.List', - '9': 0, - '10': 'clients' - }, - { - '1': 'error', - '3': 2, - '4': 1, - '5': 14, - '6': '.arbiter.user_agent.sdk_client.Error', - '9': 0, - '10': 'error' - }, - ], - '8': [ - {'1': 'result'}, - ], -}; - -/// Descriptor for `ListResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List listResponseDescriptor = $convert.base64Decode( - 'CgxMaXN0UmVzcG9uc2USPwoHY2xpZW50cxgBIAEoCzIjLmFyYml0ZXIudXNlcl9hZ2VudC5zZG' - 'tfY2xpZW50Lkxpc3RIAFIHY2xpZW50cxI8CgVlcnJvchgCIAEoDjIkLmFyYml0ZXIudXNlcl9h' - 'Z2VudC5zZGtfY2xpZW50LkVycm9ySABSBWVycm9yQggKBnJlc3VsdA=='); - -@$core.Deprecated('Use connectionRequestDescriptor instead') -const ConnectionRequest$json = { - '1': 'ConnectionRequest', - '2': [ - {'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'}, - { - '1': 'info', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.shared.ClientInfo', - '10': 'info' - }, - ], -}; - -/// Descriptor for `ConnectionRequest`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List connectionRequestDescriptor = $convert.base64Decode( - 'ChFDb25uZWN0aW9uUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRIuCgRpbmZvGAIgAS' - 'gLMhouYXJiaXRlci5zaGFyZWQuQ2xpZW50SW5mb1IEaW5mbw=='); - -@$core.Deprecated('Use connectionResponseDescriptor instead') -const ConnectionResponse$json = { - '1': 'ConnectionResponse', - '2': [ - {'1': 'approved', '3': 1, '4': 1, '5': 8, '10': 'approved'}, - {'1': 'pubkey', '3': 2, '4': 1, '5': 12, '10': 'pubkey'}, - ], -}; - -/// Descriptor for `ConnectionResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List connectionResponseDescriptor = $convert.base64Decode( - 'ChJDb25uZWN0aW9uUmVzcG9uc2USGgoIYXBwcm92ZWQYASABKAhSCGFwcHJvdmVkEhYKBnB1Ym' - 'tleRgCIAEoDFIGcHVia2V5'); - -@$core.Deprecated('Use connectionCancelDescriptor instead') -const ConnectionCancel$json = { - '1': 'ConnectionCancel', - '2': [ - {'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'}, - ], -}; - -/// Descriptor for `ConnectionCancel`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List connectionCancelDescriptor = $convert - .base64Decode('ChBDb25uZWN0aW9uQ2FuY2VsEhYKBnB1YmtleRgBIAEoDFIGcHVia2V5'); - -@$core.Deprecated('Use walletAccessDescriptor instead') -const WalletAccess$json = { - '1': 'WalletAccess', - '2': [ - {'1': 'wallet_id', '3': 1, '4': 1, '5': 5, '10': 'walletId'}, - {'1': 'sdk_client_id', '3': 2, '4': 1, '5': 5, '10': 'sdkClientId'}, - ], -}; - -/// Descriptor for `WalletAccess`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List walletAccessDescriptor = $convert.base64Decode( - 'CgxXYWxsZXRBY2Nlc3MSGwoJd2FsbGV0X2lkGAEgASgFUgh3YWxsZXRJZBIiCg1zZGtfY2xpZW' - '50X2lkGAIgASgFUgtzZGtDbGllbnRJZA=='); - -@$core.Deprecated('Use walletAccessEntryDescriptor instead') -const WalletAccessEntry$json = { - '1': 'WalletAccessEntry', - '2': [ - {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, - { - '1': 'access', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.WalletAccess', - '10': 'access' - }, - ], -}; - -/// Descriptor for `WalletAccessEntry`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List walletAccessEntryDescriptor = $convert.base64Decode( - 'ChFXYWxsZXRBY2Nlc3NFbnRyeRIOCgJpZBgBIAEoBVICaWQSQwoGYWNjZXNzGAIgASgLMisuYX' - 'JiaXRlci51c2VyX2FnZW50LnNka19jbGllbnQuV2FsbGV0QWNjZXNzUgZhY2Nlc3M='); - -@$core.Deprecated('Use grantWalletAccessDescriptor instead') -const GrantWalletAccess$json = { - '1': 'GrantWalletAccess', - '2': [ - { - '1': 'accesses', - '3': 1, - '4': 3, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.WalletAccess', - '10': 'accesses' - }, - ], -}; - -/// Descriptor for `GrantWalletAccess`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List grantWalletAccessDescriptor = $convert.base64Decode( - 'ChFHcmFudFdhbGxldEFjY2VzcxJHCghhY2Nlc3NlcxgBIAMoCzIrLmFyYml0ZXIudXNlcl9hZ2' - 'VudC5zZGtfY2xpZW50LldhbGxldEFjY2Vzc1IIYWNjZXNzZXM='); - -@$core.Deprecated('Use revokeWalletAccessDescriptor instead') -const RevokeWalletAccess$json = { - '1': 'RevokeWalletAccess', - '2': [ - {'1': 'accesses', '3': 1, '4': 3, '5': 5, '10': 'accesses'}, - ], -}; - -/// Descriptor for `RevokeWalletAccess`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List revokeWalletAccessDescriptor = - $convert.base64Decode( - 'ChJSZXZva2VXYWxsZXRBY2Nlc3MSGgoIYWNjZXNzZXMYASADKAVSCGFjY2Vzc2Vz'); - -@$core.Deprecated('Use listWalletAccessResponseDescriptor instead') -const ListWalletAccessResponse$json = { - '1': 'ListWalletAccessResponse', - '2': [ - { - '1': 'accesses', - '3': 1, - '4': 3, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.WalletAccessEntry', - '10': 'accesses' - }, - ], -}; - -/// Descriptor for `ListWalletAccessResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List listWalletAccessResponseDescriptor = - $convert.base64Decode( - 'ChhMaXN0V2FsbGV0QWNjZXNzUmVzcG9uc2USTAoIYWNjZXNzZXMYASADKAsyMC5hcmJpdGVyLn' - 'VzZXJfYWdlbnQuc2RrX2NsaWVudC5XYWxsZXRBY2Nlc3NFbnRyeVIIYWNjZXNzZXM='); - -@$core.Deprecated('Use requestDescriptor instead') -const Request$json = { - '1': 'Request', - '2': [ - { - '1': 'connection_response', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.ConnectionResponse', - '9': 0, - '10': 'connectionResponse' - }, - { - '1': 'revoke', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.RevokeRequest', - '9': 0, - '10': 'revoke' - }, - { - '1': 'list', - '3': 3, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'list' - }, - { - '1': 'grant_wallet_access', - '3': 4, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.GrantWalletAccess', - '9': 0, - '10': 'grantWalletAccess' - }, - { - '1': 'revoke_wallet_access', - '3': 5, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.RevokeWalletAccess', - '9': 0, - '10': 'revokeWalletAccess' - }, - { - '1': 'list_wallet_access', - '3': 6, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'listWalletAccess' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( - 'CgdSZXF1ZXN0EmQKE2Nvbm5lY3Rpb25fcmVzcG9uc2UYASABKAsyMS5hcmJpdGVyLnVzZXJfYW' - 'dlbnQuc2RrX2NsaWVudC5Db25uZWN0aW9uUmVzcG9uc2VIAFISY29ubmVjdGlvblJlc3BvbnNl' - 'EkYKBnJldm9rZRgCIAEoCzIsLmFyYml0ZXIudXNlcl9hZ2VudC5zZGtfY2xpZW50LlJldm9rZV' - 'JlcXVlc3RIAFIGcmV2b2tlEiwKBGxpc3QYAyABKAsyFi5nb29nbGUucHJvdG9idWYuRW1wdHlI' - 'AFIEbGlzdBJiChNncmFudF93YWxsZXRfYWNjZXNzGAQgASgLMjAuYXJiaXRlci51c2VyX2FnZW' - '50LnNka19jbGllbnQuR3JhbnRXYWxsZXRBY2Nlc3NIAFIRZ3JhbnRXYWxsZXRBY2Nlc3MSZQoU' - 'cmV2b2tlX3dhbGxldF9hY2Nlc3MYBSABKAsyMS5hcmJpdGVyLnVzZXJfYWdlbnQuc2RrX2NsaW' - 'VudC5SZXZva2VXYWxsZXRBY2Nlc3NIAFIScmV2b2tlV2FsbGV0QWNjZXNzEkYKEmxpc3Rfd2Fs' - 'bGV0X2FjY2VzcxgGIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAUhBsaXN0V2FsbGV0QW' - 'NjZXNzQgkKB3BheWxvYWQ='); - -@$core.Deprecated('Use responseDescriptor instead') -const Response$json = { - '1': 'Response', - '2': [ - { - '1': 'connection_request', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.ConnectionRequest', - '9': 0, - '10': 'connectionRequest' - }, - { - '1': 'connection_cancel', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.ConnectionCancel', - '9': 0, - '10': 'connectionCancel' - }, - { - '1': 'revoke', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.RevokeResponse', - '9': 0, - '10': 'revoke' - }, - { - '1': 'list', - '3': 4, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.ListResponse', - '9': 0, - '10': 'list' - }, - { - '1': 'list_wallet_access', - '3': 5, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.sdk_client.ListWalletAccessResponse', - '9': 0, - '10': 'listWalletAccess' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( - 'CghSZXNwb25zZRJhChJjb25uZWN0aW9uX3JlcXVlc3QYASABKAsyMC5hcmJpdGVyLnVzZXJfYW' - 'dlbnQuc2RrX2NsaWVudC5Db25uZWN0aW9uUmVxdWVzdEgAUhFjb25uZWN0aW9uUmVxdWVzdBJe' - 'ChFjb25uZWN0aW9uX2NhbmNlbBgCIAEoCzIvLmFyYml0ZXIudXNlcl9hZ2VudC5zZGtfY2xpZW' - '50LkNvbm5lY3Rpb25DYW5jZWxIAFIQY29ubmVjdGlvbkNhbmNlbBJHCgZyZXZva2UYAyABKAsy' - 'LS5hcmJpdGVyLnVzZXJfYWdlbnQuc2RrX2NsaWVudC5SZXZva2VSZXNwb25zZUgAUgZyZXZva2' - 'USQQoEbGlzdBgEIAEoCzIrLmFyYml0ZXIudXNlcl9hZ2VudC5zZGtfY2xpZW50Lkxpc3RSZXNw' - 'b25zZUgAUgRsaXN0EmcKEmxpc3Rfd2FsbGV0X2FjY2VzcxgFIAEoCzI3LmFyYml0ZXIudXNlcl' - '9hZ2VudC5zZGtfY2xpZW50Lkxpc3RXYWxsZXRBY2Nlc3NSZXNwb25zZUgAUhBsaXN0V2FsbGV0' - 'QWNjZXNzQgkKB3BheWxvYWQ='); +// This is a generated file - do not edit. +// +// Generated from user_agent/sdk_client.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use errorDescriptor instead') +const Error$json = { + '1': 'Error', + '2': [ + {'1': 'ERROR_UNSPECIFIED', '2': 0}, + {'1': 'ERROR_ALREADY_EXISTS', '2': 1}, + {'1': 'ERROR_NOT_FOUND', '2': 2}, + {'1': 'ERROR_HAS_RELATED_DATA', '2': 3}, + {'1': 'ERROR_INTERNAL', '2': 4}, + ], +}; + +/// Descriptor for `Error`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List errorDescriptor = $convert.base64Decode( + 'CgVFcnJvchIVChFFUlJPUl9VTlNQRUNJRklFRBAAEhgKFEVSUk9SX0FMUkVBRFlfRVhJU1RTEA' + 'ESEwoPRVJST1JfTk9UX0ZPVU5EEAISGgoWRVJST1JfSEFTX1JFTEFURURfREFUQRADEhIKDkVS' + 'Uk9SX0lOVEVSTkFMEAQ='); + +@$core.Deprecated('Use revokeRequestDescriptor instead') +const RevokeRequest$json = { + '1': 'RevokeRequest', + '2': [ + {'1': 'client_id', '3': 1, '4': 1, '5': 5, '10': 'clientId'}, + ], +}; + +/// Descriptor for `RevokeRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List revokeRequestDescriptor = $convert.base64Decode( + 'Cg1SZXZva2VSZXF1ZXN0EhsKCWNsaWVudF9pZBgBIAEoBVIIY2xpZW50SWQ='); + +@$core.Deprecated('Use entryDescriptor instead') +const Entry$json = { + '1': 'Entry', + '2': [ + {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, + {'1': 'pubkey', '3': 2, '4': 1, '5': 12, '10': 'pubkey'}, + { + '1': 'info', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.shared.ClientInfo', + '10': 'info' + }, + {'1': 'created_at', '3': 4, '4': 1, '5': 5, '10': 'createdAt'}, + ], +}; + +/// Descriptor for `Entry`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List entryDescriptor = $convert.base64Decode( + 'CgVFbnRyeRIOCgJpZBgBIAEoBVICaWQSFgoGcHVia2V5GAIgASgMUgZwdWJrZXkSLgoEaW5mbx' + 'gDIAEoCzIaLmFyYml0ZXIuc2hhcmVkLkNsaWVudEluZm9SBGluZm8SHQoKY3JlYXRlZF9hdBgE' + 'IAEoBVIJY3JlYXRlZEF0'); + +@$core.Deprecated('Use list_Descriptor instead') +const List_$json = { + '1': 'List', + '2': [ + { + '1': 'clients', + '3': 1, + '4': 3, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.Entry', + '10': 'clients' + }, + ], +}; + +/// Descriptor for `List`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List list_Descriptor = $convert.base64Decode( + 'CgRMaXN0Ej4KB2NsaWVudHMYASADKAsyJC5hcmJpdGVyLnVzZXJfYWdlbnQuc2RrX2NsaWVudC' + '5FbnRyeVIHY2xpZW50cw=='); + +@$core.Deprecated('Use revokeResponseDescriptor instead') +const RevokeResponse$json = { + '1': 'RevokeResponse', + '2': [ + { + '1': 'ok', + '3': 1, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'ok' + }, + { + '1': 'error', + '3': 2, + '4': 1, + '5': 14, + '6': '.arbiter.user_agent.sdk_client.Error', + '9': 0, + '10': 'error' + }, + ], + '8': [ + {'1': 'result'}, + ], +}; + +/// Descriptor for `RevokeResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List revokeResponseDescriptor = $convert.base64Decode( + 'Cg5SZXZva2VSZXNwb25zZRIoCgJvaxgBIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAUg' + 'JvaxI8CgVlcnJvchgCIAEoDjIkLmFyYml0ZXIudXNlcl9hZ2VudC5zZGtfY2xpZW50LkVycm9y' + 'SABSBWVycm9yQggKBnJlc3VsdA=='); + +@$core.Deprecated('Use listResponseDescriptor instead') +const ListResponse$json = { + '1': 'ListResponse', + '2': [ + { + '1': 'clients', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.List', + '9': 0, + '10': 'clients' + }, + { + '1': 'error', + '3': 2, + '4': 1, + '5': 14, + '6': '.arbiter.user_agent.sdk_client.Error', + '9': 0, + '10': 'error' + }, + ], + '8': [ + {'1': 'result'}, + ], +}; + +/// Descriptor for `ListResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List listResponseDescriptor = $convert.base64Decode( + 'CgxMaXN0UmVzcG9uc2USPwoHY2xpZW50cxgBIAEoCzIjLmFyYml0ZXIudXNlcl9hZ2VudC5zZG' + 'tfY2xpZW50Lkxpc3RIAFIHY2xpZW50cxI8CgVlcnJvchgCIAEoDjIkLmFyYml0ZXIudXNlcl9h' + 'Z2VudC5zZGtfY2xpZW50LkVycm9ySABSBWVycm9yQggKBnJlc3VsdA=='); + +@$core.Deprecated('Use connectionRequestDescriptor instead') +const ConnectionRequest$json = { + '1': 'ConnectionRequest', + '2': [ + {'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'}, + { + '1': 'info', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.shared.ClientInfo', + '10': 'info' + }, + ], +}; + +/// Descriptor for `ConnectionRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List connectionRequestDescriptor = $convert.base64Decode( + 'ChFDb25uZWN0aW9uUmVxdWVzdBIWCgZwdWJrZXkYASABKAxSBnB1YmtleRIuCgRpbmZvGAIgAS' + 'gLMhouYXJiaXRlci5zaGFyZWQuQ2xpZW50SW5mb1IEaW5mbw=='); + +@$core.Deprecated('Use connectionResponseDescriptor instead') +const ConnectionResponse$json = { + '1': 'ConnectionResponse', + '2': [ + {'1': 'approved', '3': 1, '4': 1, '5': 8, '10': 'approved'}, + {'1': 'pubkey', '3': 2, '4': 1, '5': 12, '10': 'pubkey'}, + ], +}; + +/// Descriptor for `ConnectionResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List connectionResponseDescriptor = $convert.base64Decode( + 'ChJDb25uZWN0aW9uUmVzcG9uc2USGgoIYXBwcm92ZWQYASABKAhSCGFwcHJvdmVkEhYKBnB1Ym' + 'tleRgCIAEoDFIGcHVia2V5'); + +@$core.Deprecated('Use connectionCancelDescriptor instead') +const ConnectionCancel$json = { + '1': 'ConnectionCancel', + '2': [ + {'1': 'pubkey', '3': 1, '4': 1, '5': 12, '10': 'pubkey'}, + ], +}; + +/// Descriptor for `ConnectionCancel`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List connectionCancelDescriptor = $convert + .base64Decode('ChBDb25uZWN0aW9uQ2FuY2VsEhYKBnB1YmtleRgBIAEoDFIGcHVia2V5'); + +@$core.Deprecated('Use walletAccessDescriptor instead') +const WalletAccess$json = { + '1': 'WalletAccess', + '2': [ + {'1': 'wallet_id', '3': 1, '4': 1, '5': 5, '10': 'walletId'}, + {'1': 'sdk_client_id', '3': 2, '4': 1, '5': 5, '10': 'sdkClientId'}, + ], +}; + +/// Descriptor for `WalletAccess`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List walletAccessDescriptor = $convert.base64Decode( + 'CgxXYWxsZXRBY2Nlc3MSGwoJd2FsbGV0X2lkGAEgASgFUgh3YWxsZXRJZBIiCg1zZGtfY2xpZW' + '50X2lkGAIgASgFUgtzZGtDbGllbnRJZA=='); + +@$core.Deprecated('Use walletAccessEntryDescriptor instead') +const WalletAccessEntry$json = { + '1': 'WalletAccessEntry', + '2': [ + {'1': 'id', '3': 1, '4': 1, '5': 5, '10': 'id'}, + { + '1': 'access', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.WalletAccess', + '10': 'access' + }, + ], +}; + +/// Descriptor for `WalletAccessEntry`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List walletAccessEntryDescriptor = $convert.base64Decode( + 'ChFXYWxsZXRBY2Nlc3NFbnRyeRIOCgJpZBgBIAEoBVICaWQSQwoGYWNjZXNzGAIgASgLMisuYX' + 'JiaXRlci51c2VyX2FnZW50LnNka19jbGllbnQuV2FsbGV0QWNjZXNzUgZhY2Nlc3M='); + +@$core.Deprecated('Use grantWalletAccessDescriptor instead') +const GrantWalletAccess$json = { + '1': 'GrantWalletAccess', + '2': [ + { + '1': 'accesses', + '3': 1, + '4': 3, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.WalletAccess', + '10': 'accesses' + }, + ], +}; + +/// Descriptor for `GrantWalletAccess`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List grantWalletAccessDescriptor = $convert.base64Decode( + 'ChFHcmFudFdhbGxldEFjY2VzcxJHCghhY2Nlc3NlcxgBIAMoCzIrLmFyYml0ZXIudXNlcl9hZ2' + 'VudC5zZGtfY2xpZW50LldhbGxldEFjY2Vzc1IIYWNjZXNzZXM='); + +@$core.Deprecated('Use revokeWalletAccessDescriptor instead') +const RevokeWalletAccess$json = { + '1': 'RevokeWalletAccess', + '2': [ + {'1': 'accesses', '3': 1, '4': 3, '5': 5, '10': 'accesses'}, + ], +}; + +/// Descriptor for `RevokeWalletAccess`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List revokeWalletAccessDescriptor = + $convert.base64Decode( + 'ChJSZXZva2VXYWxsZXRBY2Nlc3MSGgoIYWNjZXNzZXMYASADKAVSCGFjY2Vzc2Vz'); + +@$core.Deprecated('Use listWalletAccessResponseDescriptor instead') +const ListWalletAccessResponse$json = { + '1': 'ListWalletAccessResponse', + '2': [ + { + '1': 'accesses', + '3': 1, + '4': 3, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.WalletAccessEntry', + '10': 'accesses' + }, + ], +}; + +/// Descriptor for `ListWalletAccessResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List listWalletAccessResponseDescriptor = + $convert.base64Decode( + 'ChhMaXN0V2FsbGV0QWNjZXNzUmVzcG9uc2USTAoIYWNjZXNzZXMYASADKAsyMC5hcmJpdGVyLn' + 'VzZXJfYWdlbnQuc2RrX2NsaWVudC5XYWxsZXRBY2Nlc3NFbnRyeVIIYWNjZXNzZXM='); + +@$core.Deprecated('Use requestDescriptor instead') +const Request$json = { + '1': 'Request', + '2': [ + { + '1': 'connection_response', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.ConnectionResponse', + '9': 0, + '10': 'connectionResponse' + }, + { + '1': 'revoke', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.RevokeRequest', + '9': 0, + '10': 'revoke' + }, + { + '1': 'list', + '3': 3, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'list' + }, + { + '1': 'grant_wallet_access', + '3': 4, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.GrantWalletAccess', + '9': 0, + '10': 'grantWalletAccess' + }, + { + '1': 'revoke_wallet_access', + '3': 5, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.RevokeWalletAccess', + '9': 0, + '10': 'revokeWalletAccess' + }, + { + '1': 'list_wallet_access', + '3': 6, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'listWalletAccess' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( + 'CgdSZXF1ZXN0EmQKE2Nvbm5lY3Rpb25fcmVzcG9uc2UYASABKAsyMS5hcmJpdGVyLnVzZXJfYW' + 'dlbnQuc2RrX2NsaWVudC5Db25uZWN0aW9uUmVzcG9uc2VIAFISY29ubmVjdGlvblJlc3BvbnNl' + 'EkYKBnJldm9rZRgCIAEoCzIsLmFyYml0ZXIudXNlcl9hZ2VudC5zZGtfY2xpZW50LlJldm9rZV' + 'JlcXVlc3RIAFIGcmV2b2tlEiwKBGxpc3QYAyABKAsyFi5nb29nbGUucHJvdG9idWYuRW1wdHlI' + 'AFIEbGlzdBJiChNncmFudF93YWxsZXRfYWNjZXNzGAQgASgLMjAuYXJiaXRlci51c2VyX2FnZW' + '50LnNka19jbGllbnQuR3JhbnRXYWxsZXRBY2Nlc3NIAFIRZ3JhbnRXYWxsZXRBY2Nlc3MSZQoU' + 'cmV2b2tlX3dhbGxldF9hY2Nlc3MYBSABKAsyMS5hcmJpdGVyLnVzZXJfYWdlbnQuc2RrX2NsaW' + 'VudC5SZXZva2VXYWxsZXRBY2Nlc3NIAFIScmV2b2tlV2FsbGV0QWNjZXNzEkYKEmxpc3Rfd2Fs' + 'bGV0X2FjY2VzcxgGIAEoCzIWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eUgAUhBsaXN0V2FsbGV0QW' + 'NjZXNzQgkKB3BheWxvYWQ='); + +@$core.Deprecated('Use responseDescriptor instead') +const Response$json = { + '1': 'Response', + '2': [ + { + '1': 'connection_request', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.ConnectionRequest', + '9': 0, + '10': 'connectionRequest' + }, + { + '1': 'connection_cancel', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.ConnectionCancel', + '9': 0, + '10': 'connectionCancel' + }, + { + '1': 'revoke', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.RevokeResponse', + '9': 0, + '10': 'revoke' + }, + { + '1': 'list', + '3': 4, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.ListResponse', + '9': 0, + '10': 'list' + }, + { + '1': 'list_wallet_access', + '3': 5, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.sdk_client.ListWalletAccessResponse', + '9': 0, + '10': 'listWalletAccess' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( + 'CghSZXNwb25zZRJhChJjb25uZWN0aW9uX3JlcXVlc3QYASABKAsyMC5hcmJpdGVyLnVzZXJfYW' + 'dlbnQuc2RrX2NsaWVudC5Db25uZWN0aW9uUmVxdWVzdEgAUhFjb25uZWN0aW9uUmVxdWVzdBJe' + 'ChFjb25uZWN0aW9uX2NhbmNlbBgCIAEoCzIvLmFyYml0ZXIudXNlcl9hZ2VudC5zZGtfY2xpZW' + '50LkNvbm5lY3Rpb25DYW5jZWxIAFIQY29ubmVjdGlvbkNhbmNlbBJHCgZyZXZva2UYAyABKAsy' + 'LS5hcmJpdGVyLnVzZXJfYWdlbnQuc2RrX2NsaWVudC5SZXZva2VSZXNwb25zZUgAUgZyZXZva2' + 'USQQoEbGlzdBgEIAEoCzIrLmFyYml0ZXIudXNlcl9hZ2VudC5zZGtfY2xpZW50Lkxpc3RSZXNw' + 'b25zZUgAUgRsaXN0EmcKEmxpc3Rfd2FsbGV0X2FjY2VzcxgFIAEoCzI3LmFyYml0ZXIudXNlcl' + '9hZ2VudC5zZGtfY2xpZW50Lkxpc3RXYWxsZXRBY2Nlc3NSZXNwb25zZUgAUhBsaXN0V2FsbGV0' + 'QWNjZXNzQgkKB3BheWxvYWQ='); diff --git a/useragent/lib/proto/user_agent/vault/bootstrap.pb.dart b/useragent/lib/proto/user_agent/vault/bootstrap.pb.dart index bc7f2f9..7889f19 100644 --- a/useragent/lib/proto/user_agent/vault/bootstrap.pb.dart +++ b/useragent/lib/proto/user_agent/vault/bootstrap.pb.dart @@ -1,221 +1,221 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/vault/bootstrap.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -import 'bootstrap.pbenum.dart'; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -export 'bootstrap.pbenum.dart'; - -class BootstrapEncryptedKey extends $pb.GeneratedMessage { - factory BootstrapEncryptedKey({ - $core.List<$core.int>? nonce, - $core.List<$core.int>? ciphertext, - $core.List<$core.int>? associatedData, - }) { - final result = create(); - if (nonce != null) result.nonce = nonce; - if (ciphertext != null) result.ciphertext = ciphertext; - if (associatedData != null) result.associatedData = associatedData; - return result; - } - - BootstrapEncryptedKey._(); - - factory BootstrapEncryptedKey.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory BootstrapEncryptedKey.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'BootstrapEncryptedKey', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.vault.bootstrap'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'ciphertext', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 3, _omitFieldNames ? '' : 'associatedData', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - BootstrapEncryptedKey clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - BootstrapEncryptedKey copyWith( - void Function(BootstrapEncryptedKey) updates) => - super.copyWith((message) => updates(message as BootstrapEncryptedKey)) - as BootstrapEncryptedKey; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static BootstrapEncryptedKey create() => BootstrapEncryptedKey._(); - @$core.override - BootstrapEncryptedKey createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static BootstrapEncryptedKey getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static BootstrapEncryptedKey? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get nonce => $_getN(0); - @$pb.TagNumber(1) - set nonce($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasNonce() => $_has(0); - @$pb.TagNumber(1) - void clearNonce() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get ciphertext => $_getN(1); - @$pb.TagNumber(2) - set ciphertext($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasCiphertext() => $_has(1); - @$pb.TagNumber(2) - void clearCiphertext() => $_clearField(2); - - @$pb.TagNumber(3) - $core.List<$core.int> get associatedData => $_getN(2); - @$pb.TagNumber(3) - set associatedData($core.List<$core.int> value) => $_setBytes(2, value); - @$pb.TagNumber(3) - $core.bool hasAssociatedData() => $_has(2); - @$pb.TagNumber(3) - void clearAssociatedData() => $_clearField(3); -} - -class Request extends $pb.GeneratedMessage { - factory Request({ - BootstrapEncryptedKey? encryptedKey, - }) { - final result = create(); - if (encryptedKey != null) result.encryptedKey = encryptedKey; - return result; - } - - Request._(); - - factory Request.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Request.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Request', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.vault.bootstrap'), - createEmptyInstance: create) - ..aOM(2, _omitFieldNames ? '' : 'encryptedKey', - subBuilder: BootstrapEncryptedKey.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request copyWith(void Function(Request) updates) => - super.copyWith((message) => updates(message as Request)) as Request; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Request create() => Request._(); - @$core.override - Request createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Request getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Request? _defaultInstance; - - @$pb.TagNumber(2) - BootstrapEncryptedKey get encryptedKey => $_getN(0); - @$pb.TagNumber(2) - set encryptedKey(BootstrapEncryptedKey value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasEncryptedKey() => $_has(0); - @$pb.TagNumber(2) - void clearEncryptedKey() => $_clearField(2); - @$pb.TagNumber(2) - BootstrapEncryptedKey ensureEncryptedKey() => $_ensure(0); -} - -class Response extends $pb.GeneratedMessage { - factory Response({ - BootstrapResult? result, - }) { - final result$ = create(); - if (result != null) result$.result = result; - return result$; - } - - Response._(); - - factory Response.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Response.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Response', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.vault.bootstrap'), - createEmptyInstance: create) - ..aE(1, _omitFieldNames ? '' : 'result', - enumValues: BootstrapResult.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response copyWith(void Function(Response) updates) => - super.copyWith((message) => updates(message as Response)) as Response; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Response create() => Response._(); - @$core.override - Response createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Response getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Response? _defaultInstance; - - @$pb.TagNumber(1) - BootstrapResult get result => $_getN(0); - @$pb.TagNumber(1) - set result(BootstrapResult value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasResult() => $_has(0); - @$pb.TagNumber(1) - void clearResult() => $_clearField(1); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent/vault/bootstrap.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'bootstrap.pbenum.dart'; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +export 'bootstrap.pbenum.dart'; + +class BootstrapEncryptedKey extends $pb.GeneratedMessage { + factory BootstrapEncryptedKey({ + $core.List<$core.int>? nonce, + $core.List<$core.int>? ciphertext, + $core.List<$core.int>? associatedData, + }) { + final result = create(); + if (nonce != null) result.nonce = nonce; + if (ciphertext != null) result.ciphertext = ciphertext; + if (associatedData != null) result.associatedData = associatedData; + return result; + } + + BootstrapEncryptedKey._(); + + factory BootstrapEncryptedKey.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory BootstrapEncryptedKey.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'BootstrapEncryptedKey', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.vault.bootstrap'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'ciphertext', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 3, _omitFieldNames ? '' : 'associatedData', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + BootstrapEncryptedKey clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + BootstrapEncryptedKey copyWith( + void Function(BootstrapEncryptedKey) updates) => + super.copyWith((message) => updates(message as BootstrapEncryptedKey)) + as BootstrapEncryptedKey; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static BootstrapEncryptedKey create() => BootstrapEncryptedKey._(); + @$core.override + BootstrapEncryptedKey createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static BootstrapEncryptedKey getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static BootstrapEncryptedKey? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get nonce => $_getN(0); + @$pb.TagNumber(1) + set nonce($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasNonce() => $_has(0); + @$pb.TagNumber(1) + void clearNonce() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get ciphertext => $_getN(1); + @$pb.TagNumber(2) + set ciphertext($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasCiphertext() => $_has(1); + @$pb.TagNumber(2) + void clearCiphertext() => $_clearField(2); + + @$pb.TagNumber(3) + $core.List<$core.int> get associatedData => $_getN(2); + @$pb.TagNumber(3) + set associatedData($core.List<$core.int> value) => $_setBytes(2, value); + @$pb.TagNumber(3) + $core.bool hasAssociatedData() => $_has(2); + @$pb.TagNumber(3) + void clearAssociatedData() => $_clearField(3); +} + +class Request extends $pb.GeneratedMessage { + factory Request({ + BootstrapEncryptedKey? encryptedKey, + }) { + final result = create(); + if (encryptedKey != null) result.encryptedKey = encryptedKey; + return result; + } + + Request._(); + + factory Request.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Request.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Request', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.vault.bootstrap'), + createEmptyInstance: create) + ..aOM(2, _omitFieldNames ? '' : 'encryptedKey', + subBuilder: BootstrapEncryptedKey.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request copyWith(void Function(Request) updates) => + super.copyWith((message) => updates(message as Request)) as Request; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Request create() => Request._(); + @$core.override + Request createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Request getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Request? _defaultInstance; + + @$pb.TagNumber(2) + BootstrapEncryptedKey get encryptedKey => $_getN(0); + @$pb.TagNumber(2) + set encryptedKey(BootstrapEncryptedKey value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasEncryptedKey() => $_has(0); + @$pb.TagNumber(2) + void clearEncryptedKey() => $_clearField(2); + @$pb.TagNumber(2) + BootstrapEncryptedKey ensureEncryptedKey() => $_ensure(0); +} + +class Response extends $pb.GeneratedMessage { + factory Response({ + BootstrapResult? result, + }) { + final result$ = create(); + if (result != null) result$.result = result; + return result$; + } + + Response._(); + + factory Response.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Response.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Response', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.vault.bootstrap'), + createEmptyInstance: create) + ..aE(1, _omitFieldNames ? '' : 'result', + enumValues: BootstrapResult.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response copyWith(void Function(Response) updates) => + super.copyWith((message) => updates(message as Response)) as Response; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Response create() => Response._(); + @$core.override + Response createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Response getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Response? _defaultInstance; + + @$pb.TagNumber(1) + BootstrapResult get result => $_getN(0); + @$pb.TagNumber(1) + set result(BootstrapResult value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasResult() => $_has(0); + @$pb.TagNumber(1) + void clearResult() => $_clearField(1); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/user_agent/vault/bootstrap.pbenum.dart b/useragent/lib/proto/user_agent/vault/bootstrap.pbenum.dart index aeb96d6..40bfc6c 100644 --- a/useragent/lib/proto/user_agent/vault/bootstrap.pbenum.dart +++ b/useragent/lib/proto/user_agent/vault/bootstrap.pbenum.dart @@ -1,44 +1,44 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/vault/bootstrap.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -class BootstrapResult extends $pb.ProtobufEnum { - static const BootstrapResult BOOTSTRAP_RESULT_UNSPECIFIED = BootstrapResult._( - 0, _omitEnumNames ? '' : 'BOOTSTRAP_RESULT_UNSPECIFIED'); - static const BootstrapResult BOOTSTRAP_RESULT_SUCCESS = - BootstrapResult._(1, _omitEnumNames ? '' : 'BOOTSTRAP_RESULT_SUCCESS'); - static const BootstrapResult BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED = - BootstrapResult._( - 2, _omitEnumNames ? '' : 'BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED'); - static const BootstrapResult BOOTSTRAP_RESULT_INVALID_KEY = BootstrapResult._( - 3, _omitEnumNames ? '' : 'BOOTSTRAP_RESULT_INVALID_KEY'); - - static const $core.List values = [ - BOOTSTRAP_RESULT_UNSPECIFIED, - BOOTSTRAP_RESULT_SUCCESS, - BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED, - BOOTSTRAP_RESULT_INVALID_KEY, - ]; - - static final $core.List _byValue = - $pb.ProtobufEnum.$_initByValueList(values, 3); - static BootstrapResult? valueOf($core.int value) => - value < 0 || value >= _byValue.length ? null : _byValue[value]; - - const BootstrapResult._(super.value, super.name); -} - -const $core.bool _omitEnumNames = - $core.bool.fromEnvironment('protobuf.omit_enum_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent/vault/bootstrap.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class BootstrapResult extends $pb.ProtobufEnum { + static const BootstrapResult BOOTSTRAP_RESULT_UNSPECIFIED = BootstrapResult._( + 0, _omitEnumNames ? '' : 'BOOTSTRAP_RESULT_UNSPECIFIED'); + static const BootstrapResult BOOTSTRAP_RESULT_SUCCESS = + BootstrapResult._(1, _omitEnumNames ? '' : 'BOOTSTRAP_RESULT_SUCCESS'); + static const BootstrapResult BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED = + BootstrapResult._( + 2, _omitEnumNames ? '' : 'BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED'); + static const BootstrapResult BOOTSTRAP_RESULT_INVALID_KEY = BootstrapResult._( + 3, _omitEnumNames ? '' : 'BOOTSTRAP_RESULT_INVALID_KEY'); + + static const $core.List values = [ + BOOTSTRAP_RESULT_UNSPECIFIED, + BOOTSTRAP_RESULT_SUCCESS, + BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED, + BOOTSTRAP_RESULT_INVALID_KEY, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 3); + static BootstrapResult? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const BootstrapResult._(super.value, super.name); +} + +const $core.bool _omitEnumNames = + $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/useragent/lib/proto/user_agent/vault/bootstrap.pbjson.dart b/useragent/lib/proto/user_agent/vault/bootstrap.pbjson.dart index 69d5c4a..9c2ab19 100644 --- a/useragent/lib/proto/user_agent/vault/bootstrap.pbjson.dart +++ b/useragent/lib/proto/user_agent/vault/bootstrap.pbjson.dart @@ -1,89 +1,89 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/vault/bootstrap.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use bootstrapResultDescriptor instead') -const BootstrapResult$json = { - '1': 'BootstrapResult', - '2': [ - {'1': 'BOOTSTRAP_RESULT_UNSPECIFIED', '2': 0}, - {'1': 'BOOTSTRAP_RESULT_SUCCESS', '2': 1}, - {'1': 'BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED', '2': 2}, - {'1': 'BOOTSTRAP_RESULT_INVALID_KEY', '2': 3}, - ], -}; - -/// Descriptor for `BootstrapResult`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List bootstrapResultDescriptor = $convert.base64Decode( - 'Cg9Cb290c3RyYXBSZXN1bHQSIAocQk9PVFNUUkFQX1JFU1VMVF9VTlNQRUNJRklFRBAAEhwKGE' - 'JPT1RTVFJBUF9SRVNVTFRfU1VDQ0VTUxABEikKJUJPT1RTVFJBUF9SRVNVTFRfQUxSRUFEWV9C' - 'T09UU1RSQVBQRUQQAhIgChxCT09UU1RSQVBfUkVTVUxUX0lOVkFMSURfS0VZEAM='); - -@$core.Deprecated('Use bootstrapEncryptedKeyDescriptor instead') -const BootstrapEncryptedKey$json = { - '1': 'BootstrapEncryptedKey', - '2': [ - {'1': 'nonce', '3': 1, '4': 1, '5': 12, '10': 'nonce'}, - {'1': 'ciphertext', '3': 2, '4': 1, '5': 12, '10': 'ciphertext'}, - {'1': 'associated_data', '3': 3, '4': 1, '5': 12, '10': 'associatedData'}, - ], -}; - -/// Descriptor for `BootstrapEncryptedKey`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List bootstrapEncryptedKeyDescriptor = $convert.base64Decode( - 'ChVCb290c3RyYXBFbmNyeXB0ZWRLZXkSFAoFbm9uY2UYASABKAxSBW5vbmNlEh4KCmNpcGhlcn' - 'RleHQYAiABKAxSCmNpcGhlcnRleHQSJwoPYXNzb2NpYXRlZF9kYXRhGAMgASgMUg5hc3NvY2lh' - 'dGVkRGF0YQ=='); - -@$core.Deprecated('Use requestDescriptor instead') -const Request$json = { - '1': 'Request', - '2': [ - { - '1': 'encrypted_key', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.vault.bootstrap.BootstrapEncryptedKey', - '10': 'encryptedKey' - }, - ], -}; - -/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( - 'CgdSZXF1ZXN0El4KDWVuY3J5cHRlZF9rZXkYAiABKAsyOS5hcmJpdGVyLnVzZXJfYWdlbnQudm' - 'F1bHQuYm9vdHN0cmFwLkJvb3RzdHJhcEVuY3J5cHRlZEtleVIMZW5jcnlwdGVkS2V5'); - -@$core.Deprecated('Use responseDescriptor instead') -const Response$json = { - '1': 'Response', - '2': [ - { - '1': 'result', - '3': 1, - '4': 1, - '5': 14, - '6': '.arbiter.user_agent.vault.bootstrap.BootstrapResult', - '10': 'result' - }, - ], -}; - -/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( - 'CghSZXNwb25zZRJLCgZyZXN1bHQYASABKA4yMy5hcmJpdGVyLnVzZXJfYWdlbnQudmF1bHQuYm' - '9vdHN0cmFwLkJvb3RzdHJhcFJlc3VsdFIGcmVzdWx0'); +// This is a generated file - do not edit. +// +// Generated from user_agent/vault/bootstrap.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use bootstrapResultDescriptor instead') +const BootstrapResult$json = { + '1': 'BootstrapResult', + '2': [ + {'1': 'BOOTSTRAP_RESULT_UNSPECIFIED', '2': 0}, + {'1': 'BOOTSTRAP_RESULT_SUCCESS', '2': 1}, + {'1': 'BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED', '2': 2}, + {'1': 'BOOTSTRAP_RESULT_INVALID_KEY', '2': 3}, + ], +}; + +/// Descriptor for `BootstrapResult`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List bootstrapResultDescriptor = $convert.base64Decode( + 'Cg9Cb290c3RyYXBSZXN1bHQSIAocQk9PVFNUUkFQX1JFU1VMVF9VTlNQRUNJRklFRBAAEhwKGE' + 'JPT1RTVFJBUF9SRVNVTFRfU1VDQ0VTUxABEikKJUJPT1RTVFJBUF9SRVNVTFRfQUxSRUFEWV9C' + 'T09UU1RSQVBQRUQQAhIgChxCT09UU1RSQVBfUkVTVUxUX0lOVkFMSURfS0VZEAM='); + +@$core.Deprecated('Use bootstrapEncryptedKeyDescriptor instead') +const BootstrapEncryptedKey$json = { + '1': 'BootstrapEncryptedKey', + '2': [ + {'1': 'nonce', '3': 1, '4': 1, '5': 12, '10': 'nonce'}, + {'1': 'ciphertext', '3': 2, '4': 1, '5': 12, '10': 'ciphertext'}, + {'1': 'associated_data', '3': 3, '4': 1, '5': 12, '10': 'associatedData'}, + ], +}; + +/// Descriptor for `BootstrapEncryptedKey`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List bootstrapEncryptedKeyDescriptor = $convert.base64Decode( + 'ChVCb290c3RyYXBFbmNyeXB0ZWRLZXkSFAoFbm9uY2UYASABKAxSBW5vbmNlEh4KCmNpcGhlcn' + 'RleHQYAiABKAxSCmNpcGhlcnRleHQSJwoPYXNzb2NpYXRlZF9kYXRhGAMgASgMUg5hc3NvY2lh' + 'dGVkRGF0YQ=='); + +@$core.Deprecated('Use requestDescriptor instead') +const Request$json = { + '1': 'Request', + '2': [ + { + '1': 'encrypted_key', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.vault.bootstrap.BootstrapEncryptedKey', + '10': 'encryptedKey' + }, + ], +}; + +/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( + 'CgdSZXF1ZXN0El4KDWVuY3J5cHRlZF9rZXkYAiABKAsyOS5hcmJpdGVyLnVzZXJfYWdlbnQudm' + 'F1bHQuYm9vdHN0cmFwLkJvb3RzdHJhcEVuY3J5cHRlZEtleVIMZW5jcnlwdGVkS2V5'); + +@$core.Deprecated('Use responseDescriptor instead') +const Response$json = { + '1': 'Response', + '2': [ + { + '1': 'result', + '3': 1, + '4': 1, + '5': 14, + '6': '.arbiter.user_agent.vault.bootstrap.BootstrapResult', + '10': 'result' + }, + ], +}; + +/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( + 'CghSZXNwb25zZRJLCgZyZXN1bHQYASABKA4yMy5hcmJpdGVyLnVzZXJfYWdlbnQudmF1bHQuYm' + '9vdHN0cmFwLkJvb3RzdHJhcFJlc3VsdFIGcmVzdWx0'); diff --git a/useragent/lib/proto/user_agent/vault/unseal.pb.dart b/useragent/lib/proto/user_agent/vault/unseal.pb.dart index cb25b7f..ce30eb3 100644 --- a/useragent/lib/proto/user_agent/vault/unseal.pb.dart +++ b/useragent/lib/proto/user_agent/vault/unseal.pb.dart @@ -1,392 +1,392 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/vault/unseal.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -import 'unseal.pbenum.dart'; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -export 'unseal.pbenum.dart'; - -class UnsealStart extends $pb.GeneratedMessage { - factory UnsealStart({ - $core.List<$core.int>? clientPubkey, - }) { - final result = create(); - if (clientPubkey != null) result.clientPubkey = clientPubkey; - return result; - } - - UnsealStart._(); - - factory UnsealStart.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory UnsealStart.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'UnsealStart', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.vault.unseal'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'clientPubkey', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - UnsealStart clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - UnsealStart copyWith(void Function(UnsealStart) updates) => - super.copyWith((message) => updates(message as UnsealStart)) - as UnsealStart; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static UnsealStart create() => UnsealStart._(); - @$core.override - UnsealStart createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static UnsealStart getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static UnsealStart? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get clientPubkey => $_getN(0); - @$pb.TagNumber(1) - set clientPubkey($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasClientPubkey() => $_has(0); - @$pb.TagNumber(1) - void clearClientPubkey() => $_clearField(1); -} - -class UnsealStartResponse extends $pb.GeneratedMessage { - factory UnsealStartResponse({ - $core.List<$core.int>? serverPubkey, - }) { - final result = create(); - if (serverPubkey != null) result.serverPubkey = serverPubkey; - return result; - } - - UnsealStartResponse._(); - - factory UnsealStartResponse.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory UnsealStartResponse.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'UnsealStartResponse', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.vault.unseal'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'serverPubkey', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - UnsealStartResponse clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - UnsealStartResponse copyWith(void Function(UnsealStartResponse) updates) => - super.copyWith((message) => updates(message as UnsealStartResponse)) - as UnsealStartResponse; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static UnsealStartResponse create() => UnsealStartResponse._(); - @$core.override - UnsealStartResponse createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static UnsealStartResponse getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static UnsealStartResponse? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get serverPubkey => $_getN(0); - @$pb.TagNumber(1) - set serverPubkey($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasServerPubkey() => $_has(0); - @$pb.TagNumber(1) - void clearServerPubkey() => $_clearField(1); -} - -class UnsealEncryptedKey extends $pb.GeneratedMessage { - factory UnsealEncryptedKey({ - $core.List<$core.int>? nonce, - $core.List<$core.int>? ciphertext, - $core.List<$core.int>? associatedData, - }) { - final result = create(); - if (nonce != null) result.nonce = nonce; - if (ciphertext != null) result.ciphertext = ciphertext; - if (associatedData != null) result.associatedData = associatedData; - return result; - } - - UnsealEncryptedKey._(); - - factory UnsealEncryptedKey.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory UnsealEncryptedKey.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'UnsealEncryptedKey', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.vault.unseal'), - createEmptyInstance: create) - ..a<$core.List<$core.int>>( - 1, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 2, _omitFieldNames ? '' : 'ciphertext', $pb.PbFieldType.OY) - ..a<$core.List<$core.int>>( - 3, _omitFieldNames ? '' : 'associatedData', $pb.PbFieldType.OY) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - UnsealEncryptedKey clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - UnsealEncryptedKey copyWith(void Function(UnsealEncryptedKey) updates) => - super.copyWith((message) => updates(message as UnsealEncryptedKey)) - as UnsealEncryptedKey; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static UnsealEncryptedKey create() => UnsealEncryptedKey._(); - @$core.override - UnsealEncryptedKey createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static UnsealEncryptedKey getDefault() => _defaultInstance ??= - $pb.GeneratedMessage.$_defaultFor(create); - static UnsealEncryptedKey? _defaultInstance; - - @$pb.TagNumber(1) - $core.List<$core.int> get nonce => $_getN(0); - @$pb.TagNumber(1) - set nonce($core.List<$core.int> value) => $_setBytes(0, value); - @$pb.TagNumber(1) - $core.bool hasNonce() => $_has(0); - @$pb.TagNumber(1) - void clearNonce() => $_clearField(1); - - @$pb.TagNumber(2) - $core.List<$core.int> get ciphertext => $_getN(1); - @$pb.TagNumber(2) - set ciphertext($core.List<$core.int> value) => $_setBytes(1, value); - @$pb.TagNumber(2) - $core.bool hasCiphertext() => $_has(1); - @$pb.TagNumber(2) - void clearCiphertext() => $_clearField(2); - - @$pb.TagNumber(3) - $core.List<$core.int> get associatedData => $_getN(2); - @$pb.TagNumber(3) - set associatedData($core.List<$core.int> value) => $_setBytes(2, value); - @$pb.TagNumber(3) - $core.bool hasAssociatedData() => $_has(2); - @$pb.TagNumber(3) - void clearAssociatedData() => $_clearField(3); -} - -enum Request_Payload { start, encryptedKey, notSet } - -class Request extends $pb.GeneratedMessage { - factory Request({ - UnsealStart? start, - UnsealEncryptedKey? encryptedKey, - }) { - final result = create(); - if (start != null) result.start = start; - if (encryptedKey != null) result.encryptedKey = encryptedKey; - return result; - } - - Request._(); - - factory Request.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Request.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { - 1: Request_Payload.start, - 2: Request_Payload.encryptedKey, - 0: Request_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Request', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.vault.unseal'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'start', - subBuilder: UnsealStart.create) - ..aOM(2, _omitFieldNames ? '' : 'encryptedKey', - subBuilder: UnsealEncryptedKey.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request copyWith(void Function(Request) updates) => - super.copyWith((message) => updates(message as Request)) as Request; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Request create() => Request._(); - @$core.override - Request createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Request getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Request? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - UnsealStart get start => $_getN(0); - @$pb.TagNumber(1) - set start(UnsealStart value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasStart() => $_has(0); - @$pb.TagNumber(1) - void clearStart() => $_clearField(1); - @$pb.TagNumber(1) - UnsealStart ensureStart() => $_ensure(0); - - @$pb.TagNumber(2) - UnsealEncryptedKey get encryptedKey => $_getN(1); - @$pb.TagNumber(2) - set encryptedKey(UnsealEncryptedKey value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasEncryptedKey() => $_has(1); - @$pb.TagNumber(2) - void clearEncryptedKey() => $_clearField(2); - @$pb.TagNumber(2) - UnsealEncryptedKey ensureEncryptedKey() => $_ensure(1); -} - -enum Response_Payload { start, result, notSet } - -class Response extends $pb.GeneratedMessage { - factory Response({ - UnsealStartResponse? start, - UnsealResult? result, - }) { - final result$ = create(); - if (start != null) result$.start = start; - if (result != null) result$.result = result; - return result$; - } - - Response._(); - - factory Response.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Response.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { - 1: Response_Payload.start, - 2: Response_Payload.result, - 0: Response_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Response', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.vault.unseal'), - createEmptyInstance: create) - ..oo(0, [1, 2]) - ..aOM(1, _omitFieldNames ? '' : 'start', - subBuilder: UnsealStartResponse.create) - ..aE(2, _omitFieldNames ? '' : 'result', - enumValues: UnsealResult.values) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response copyWith(void Function(Response) updates) => - super.copyWith((message) => updates(message as Response)) as Response; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Response create() => Response._(); - @$core.override - Response createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Response getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Response? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - UnsealStartResponse get start => $_getN(0); - @$pb.TagNumber(1) - set start(UnsealStartResponse value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasStart() => $_has(0); - @$pb.TagNumber(1) - void clearStart() => $_clearField(1); - @$pb.TagNumber(1) - UnsealStartResponse ensureStart() => $_ensure(0); - - @$pb.TagNumber(2) - UnsealResult get result => $_getN(1); - @$pb.TagNumber(2) - set result(UnsealResult value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasResult() => $_has(1); - @$pb.TagNumber(2) - void clearResult() => $_clearField(2); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent/vault/unseal.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'unseal.pbenum.dart'; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +export 'unseal.pbenum.dart'; + +class UnsealStart extends $pb.GeneratedMessage { + factory UnsealStart({ + $core.List<$core.int>? clientPubkey, + }) { + final result = create(); + if (clientPubkey != null) result.clientPubkey = clientPubkey; + return result; + } + + UnsealStart._(); + + factory UnsealStart.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory UnsealStart.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'UnsealStart', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.vault.unseal'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'clientPubkey', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UnsealStart clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UnsealStart copyWith(void Function(UnsealStart) updates) => + super.copyWith((message) => updates(message as UnsealStart)) + as UnsealStart; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static UnsealStart create() => UnsealStart._(); + @$core.override + UnsealStart createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static UnsealStart getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static UnsealStart? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get clientPubkey => $_getN(0); + @$pb.TagNumber(1) + set clientPubkey($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasClientPubkey() => $_has(0); + @$pb.TagNumber(1) + void clearClientPubkey() => $_clearField(1); +} + +class UnsealStartResponse extends $pb.GeneratedMessage { + factory UnsealStartResponse({ + $core.List<$core.int>? serverPubkey, + }) { + final result = create(); + if (serverPubkey != null) result.serverPubkey = serverPubkey; + return result; + } + + UnsealStartResponse._(); + + factory UnsealStartResponse.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory UnsealStartResponse.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'UnsealStartResponse', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.vault.unseal'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'serverPubkey', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UnsealStartResponse clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UnsealStartResponse copyWith(void Function(UnsealStartResponse) updates) => + super.copyWith((message) => updates(message as UnsealStartResponse)) + as UnsealStartResponse; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static UnsealStartResponse create() => UnsealStartResponse._(); + @$core.override + UnsealStartResponse createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static UnsealStartResponse getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static UnsealStartResponse? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get serverPubkey => $_getN(0); + @$pb.TagNumber(1) + set serverPubkey($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasServerPubkey() => $_has(0); + @$pb.TagNumber(1) + void clearServerPubkey() => $_clearField(1); +} + +class UnsealEncryptedKey extends $pb.GeneratedMessage { + factory UnsealEncryptedKey({ + $core.List<$core.int>? nonce, + $core.List<$core.int>? ciphertext, + $core.List<$core.int>? associatedData, + }) { + final result = create(); + if (nonce != null) result.nonce = nonce; + if (ciphertext != null) result.ciphertext = ciphertext; + if (associatedData != null) result.associatedData = associatedData; + return result; + } + + UnsealEncryptedKey._(); + + factory UnsealEncryptedKey.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory UnsealEncryptedKey.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'UnsealEncryptedKey', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.vault.unseal'), + createEmptyInstance: create) + ..a<$core.List<$core.int>>( + 1, _omitFieldNames ? '' : 'nonce', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 2, _omitFieldNames ? '' : 'ciphertext', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>( + 3, _omitFieldNames ? '' : 'associatedData', $pb.PbFieldType.OY) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UnsealEncryptedKey clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + UnsealEncryptedKey copyWith(void Function(UnsealEncryptedKey) updates) => + super.copyWith((message) => updates(message as UnsealEncryptedKey)) + as UnsealEncryptedKey; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static UnsealEncryptedKey create() => UnsealEncryptedKey._(); + @$core.override + UnsealEncryptedKey createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static UnsealEncryptedKey getDefault() => _defaultInstance ??= + $pb.GeneratedMessage.$_defaultFor(create); + static UnsealEncryptedKey? _defaultInstance; + + @$pb.TagNumber(1) + $core.List<$core.int> get nonce => $_getN(0); + @$pb.TagNumber(1) + set nonce($core.List<$core.int> value) => $_setBytes(0, value); + @$pb.TagNumber(1) + $core.bool hasNonce() => $_has(0); + @$pb.TagNumber(1) + void clearNonce() => $_clearField(1); + + @$pb.TagNumber(2) + $core.List<$core.int> get ciphertext => $_getN(1); + @$pb.TagNumber(2) + set ciphertext($core.List<$core.int> value) => $_setBytes(1, value); + @$pb.TagNumber(2) + $core.bool hasCiphertext() => $_has(1); + @$pb.TagNumber(2) + void clearCiphertext() => $_clearField(2); + + @$pb.TagNumber(3) + $core.List<$core.int> get associatedData => $_getN(2); + @$pb.TagNumber(3) + set associatedData($core.List<$core.int> value) => $_setBytes(2, value); + @$pb.TagNumber(3) + $core.bool hasAssociatedData() => $_has(2); + @$pb.TagNumber(3) + void clearAssociatedData() => $_clearField(3); +} + +enum Request_Payload { start, encryptedKey, notSet } + +class Request extends $pb.GeneratedMessage { + factory Request({ + UnsealStart? start, + UnsealEncryptedKey? encryptedKey, + }) { + final result = create(); + if (start != null) result.start = start; + if (encryptedKey != null) result.encryptedKey = encryptedKey; + return result; + } + + Request._(); + + factory Request.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Request.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { + 1: Request_Payload.start, + 2: Request_Payload.encryptedKey, + 0: Request_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Request', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.vault.unseal'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'start', + subBuilder: UnsealStart.create) + ..aOM(2, _omitFieldNames ? '' : 'encryptedKey', + subBuilder: UnsealEncryptedKey.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request copyWith(void Function(Request) updates) => + super.copyWith((message) => updates(message as Request)) as Request; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Request create() => Request._(); + @$core.override + Request createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Request getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Request? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + UnsealStart get start => $_getN(0); + @$pb.TagNumber(1) + set start(UnsealStart value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasStart() => $_has(0); + @$pb.TagNumber(1) + void clearStart() => $_clearField(1); + @$pb.TagNumber(1) + UnsealStart ensureStart() => $_ensure(0); + + @$pb.TagNumber(2) + UnsealEncryptedKey get encryptedKey => $_getN(1); + @$pb.TagNumber(2) + set encryptedKey(UnsealEncryptedKey value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasEncryptedKey() => $_has(1); + @$pb.TagNumber(2) + void clearEncryptedKey() => $_clearField(2); + @$pb.TagNumber(2) + UnsealEncryptedKey ensureEncryptedKey() => $_ensure(1); +} + +enum Response_Payload { start, result, notSet } + +class Response extends $pb.GeneratedMessage { + factory Response({ + UnsealStartResponse? start, + UnsealResult? result, + }) { + final result$ = create(); + if (start != null) result$.start = start; + if (result != null) result$.result = result; + return result$; + } + + Response._(); + + factory Response.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Response.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { + 1: Response_Payload.start, + 2: Response_Payload.result, + 0: Response_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Response', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.vault.unseal'), + createEmptyInstance: create) + ..oo(0, [1, 2]) + ..aOM(1, _omitFieldNames ? '' : 'start', + subBuilder: UnsealStartResponse.create) + ..aE(2, _omitFieldNames ? '' : 'result', + enumValues: UnsealResult.values) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response copyWith(void Function(Response) updates) => + super.copyWith((message) => updates(message as Response)) as Response; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Response create() => Response._(); + @$core.override + Response createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Response getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Response? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + UnsealStartResponse get start => $_getN(0); + @$pb.TagNumber(1) + set start(UnsealStartResponse value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasStart() => $_has(0); + @$pb.TagNumber(1) + void clearStart() => $_clearField(1); + @$pb.TagNumber(1) + UnsealStartResponse ensureStart() => $_ensure(0); + + @$pb.TagNumber(2) + UnsealResult get result => $_getN(1); + @$pb.TagNumber(2) + set result(UnsealResult value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasResult() => $_has(1); + @$pb.TagNumber(2) + void clearResult() => $_clearField(2); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/user_agent/vault/unseal.pbenum.dart b/useragent/lib/proto/user_agent/vault/unseal.pbenum.dart index 41ddd94..f5dc55d 100644 --- a/useragent/lib/proto/user_agent/vault/unseal.pbenum.dart +++ b/useragent/lib/proto/user_agent/vault/unseal.pbenum.dart @@ -1,43 +1,43 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/vault/unseal.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; - -class UnsealResult extends $pb.ProtobufEnum { - static const UnsealResult UNSEAL_RESULT_UNSPECIFIED = - UnsealResult._(0, _omitEnumNames ? '' : 'UNSEAL_RESULT_UNSPECIFIED'); - static const UnsealResult UNSEAL_RESULT_SUCCESS = - UnsealResult._(1, _omitEnumNames ? '' : 'UNSEAL_RESULT_SUCCESS'); - static const UnsealResult UNSEAL_RESULT_INVALID_KEY = - UnsealResult._(2, _omitEnumNames ? '' : 'UNSEAL_RESULT_INVALID_KEY'); - static const UnsealResult UNSEAL_RESULT_UNBOOTSTRAPPED = - UnsealResult._(3, _omitEnumNames ? '' : 'UNSEAL_RESULT_UNBOOTSTRAPPED'); - - static const $core.List values = [ - UNSEAL_RESULT_UNSPECIFIED, - UNSEAL_RESULT_SUCCESS, - UNSEAL_RESULT_INVALID_KEY, - UNSEAL_RESULT_UNBOOTSTRAPPED, - ]; - - static final $core.List _byValue = - $pb.ProtobufEnum.$_initByValueList(values, 3); - static UnsealResult? valueOf($core.int value) => - value < 0 || value >= _byValue.length ? null : _byValue[value]; - - const UnsealResult._(super.value, super.name); -} - -const $core.bool _omitEnumNames = - $core.bool.fromEnvironment('protobuf.omit_enum_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent/vault/unseal.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +class UnsealResult extends $pb.ProtobufEnum { + static const UnsealResult UNSEAL_RESULT_UNSPECIFIED = + UnsealResult._(0, _omitEnumNames ? '' : 'UNSEAL_RESULT_UNSPECIFIED'); + static const UnsealResult UNSEAL_RESULT_SUCCESS = + UnsealResult._(1, _omitEnumNames ? '' : 'UNSEAL_RESULT_SUCCESS'); + static const UnsealResult UNSEAL_RESULT_INVALID_KEY = + UnsealResult._(2, _omitEnumNames ? '' : 'UNSEAL_RESULT_INVALID_KEY'); + static const UnsealResult UNSEAL_RESULT_UNBOOTSTRAPPED = + UnsealResult._(3, _omitEnumNames ? '' : 'UNSEAL_RESULT_UNBOOTSTRAPPED'); + + static const $core.List values = [ + UNSEAL_RESULT_UNSPECIFIED, + UNSEAL_RESULT_SUCCESS, + UNSEAL_RESULT_INVALID_KEY, + UNSEAL_RESULT_UNBOOTSTRAPPED, + ]; + + static final $core.List _byValue = + $pb.ProtobufEnum.$_initByValueList(values, 3); + static UnsealResult? valueOf($core.int value) => + value < 0 || value >= _byValue.length ? null : _byValue[value]; + + const UnsealResult._(super.value, super.name); +} + +const $core.bool _omitEnumNames = + $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/useragent/lib/proto/user_agent/vault/unseal.pbjson.dart b/useragent/lib/proto/user_agent/vault/unseal.pbjson.dart index da92281..f8e08d2 100644 --- a/useragent/lib/proto/user_agent/vault/unseal.pbjson.dart +++ b/useragent/lib/proto/user_agent/vault/unseal.pbjson.dart @@ -1,144 +1,144 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/vault/unseal.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use unsealResultDescriptor instead') -const UnsealResult$json = { - '1': 'UnsealResult', - '2': [ - {'1': 'UNSEAL_RESULT_UNSPECIFIED', '2': 0}, - {'1': 'UNSEAL_RESULT_SUCCESS', '2': 1}, - {'1': 'UNSEAL_RESULT_INVALID_KEY', '2': 2}, - {'1': 'UNSEAL_RESULT_UNBOOTSTRAPPED', '2': 3}, - ], -}; - -/// Descriptor for `UnsealResult`. Decode as a `google.protobuf.EnumDescriptorProto`. -final $typed_data.Uint8List unsealResultDescriptor = $convert.base64Decode( - 'CgxVbnNlYWxSZXN1bHQSHQoZVU5TRUFMX1JFU1VMVF9VTlNQRUNJRklFRBAAEhkKFVVOU0VBTF' - '9SRVNVTFRfU1VDQ0VTUxABEh0KGVVOU0VBTF9SRVNVTFRfSU5WQUxJRF9LRVkQAhIgChxVTlNF' - 'QUxfUkVTVUxUX1VOQk9PVFNUUkFQUEVEEAM='); - -@$core.Deprecated('Use unsealStartDescriptor instead') -const UnsealStart$json = { - '1': 'UnsealStart', - '2': [ - {'1': 'client_pubkey', '3': 1, '4': 1, '5': 12, '10': 'clientPubkey'}, - ], -}; - -/// Descriptor for `UnsealStart`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List unsealStartDescriptor = $convert.base64Decode( - 'CgtVbnNlYWxTdGFydBIjCg1jbGllbnRfcHVia2V5GAEgASgMUgxjbGllbnRQdWJrZXk='); - -@$core.Deprecated('Use unsealStartResponseDescriptor instead') -const UnsealStartResponse$json = { - '1': 'UnsealStartResponse', - '2': [ - {'1': 'server_pubkey', '3': 1, '4': 1, '5': 12, '10': 'serverPubkey'}, - ], -}; - -/// Descriptor for `UnsealStartResponse`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List unsealStartResponseDescriptor = $convert.base64Decode( - 'ChNVbnNlYWxTdGFydFJlc3BvbnNlEiMKDXNlcnZlcl9wdWJrZXkYASABKAxSDHNlcnZlclB1Ym' - 'tleQ=='); - -@$core.Deprecated('Use unsealEncryptedKeyDescriptor instead') -const UnsealEncryptedKey$json = { - '1': 'UnsealEncryptedKey', - '2': [ - {'1': 'nonce', '3': 1, '4': 1, '5': 12, '10': 'nonce'}, - {'1': 'ciphertext', '3': 2, '4': 1, '5': 12, '10': 'ciphertext'}, - {'1': 'associated_data', '3': 3, '4': 1, '5': 12, '10': 'associatedData'}, - ], -}; - -/// Descriptor for `UnsealEncryptedKey`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List unsealEncryptedKeyDescriptor = $convert.base64Decode( - 'ChJVbnNlYWxFbmNyeXB0ZWRLZXkSFAoFbm9uY2UYASABKAxSBW5vbmNlEh4KCmNpcGhlcnRleH' - 'QYAiABKAxSCmNpcGhlcnRleHQSJwoPYXNzb2NpYXRlZF9kYXRhGAMgASgMUg5hc3NvY2lhdGVk' - 'RGF0YQ=='); - -@$core.Deprecated('Use requestDescriptor instead') -const Request$json = { - '1': 'Request', - '2': [ - { - '1': 'start', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.vault.unseal.UnsealStart', - '9': 0, - '10': 'start' - }, - { - '1': 'encrypted_key', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.vault.unseal.UnsealEncryptedKey', - '9': 0, - '10': 'encryptedKey' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( - 'CgdSZXF1ZXN0EkQKBXN0YXJ0GAEgASgLMiwuYXJiaXRlci51c2VyX2FnZW50LnZhdWx0LnVuc2' - 'VhbC5VbnNlYWxTdGFydEgAUgVzdGFydBJaCg1lbmNyeXB0ZWRfa2V5GAIgASgLMjMuYXJiaXRl' - 'ci51c2VyX2FnZW50LnZhdWx0LnVuc2VhbC5VbnNlYWxFbmNyeXB0ZWRLZXlIAFIMZW5jcnlwdG' - 'VkS2V5QgkKB3BheWxvYWQ='); - -@$core.Deprecated('Use responseDescriptor instead') -const Response$json = { - '1': 'Response', - '2': [ - { - '1': 'start', - '3': 1, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.vault.unseal.UnsealStartResponse', - '9': 0, - '10': 'start' - }, - { - '1': 'result', - '3': 2, - '4': 1, - '5': 14, - '6': '.arbiter.user_agent.vault.unseal.UnsealResult', - '9': 0, - '10': 'result' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( - 'CghSZXNwb25zZRJMCgVzdGFydBgBIAEoCzI0LmFyYml0ZXIudXNlcl9hZ2VudC52YXVsdC51bn' - 'NlYWwuVW5zZWFsU3RhcnRSZXNwb25zZUgAUgVzdGFydBJHCgZyZXN1bHQYAiABKA4yLS5hcmJp' - 'dGVyLnVzZXJfYWdlbnQudmF1bHQudW5zZWFsLlVuc2VhbFJlc3VsdEgAUgZyZXN1bHRCCQoHcG' - 'F5bG9hZA=='); +// This is a generated file - do not edit. +// +// Generated from user_agent/vault/unseal.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use unsealResultDescriptor instead') +const UnsealResult$json = { + '1': 'UnsealResult', + '2': [ + {'1': 'UNSEAL_RESULT_UNSPECIFIED', '2': 0}, + {'1': 'UNSEAL_RESULT_SUCCESS', '2': 1}, + {'1': 'UNSEAL_RESULT_INVALID_KEY', '2': 2}, + {'1': 'UNSEAL_RESULT_UNBOOTSTRAPPED', '2': 3}, + ], +}; + +/// Descriptor for `UnsealResult`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List unsealResultDescriptor = $convert.base64Decode( + 'CgxVbnNlYWxSZXN1bHQSHQoZVU5TRUFMX1JFU1VMVF9VTlNQRUNJRklFRBAAEhkKFVVOU0VBTF' + '9SRVNVTFRfU1VDQ0VTUxABEh0KGVVOU0VBTF9SRVNVTFRfSU5WQUxJRF9LRVkQAhIgChxVTlNF' + 'QUxfUkVTVUxUX1VOQk9PVFNUUkFQUEVEEAM='); + +@$core.Deprecated('Use unsealStartDescriptor instead') +const UnsealStart$json = { + '1': 'UnsealStart', + '2': [ + {'1': 'client_pubkey', '3': 1, '4': 1, '5': 12, '10': 'clientPubkey'}, + ], +}; + +/// Descriptor for `UnsealStart`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List unsealStartDescriptor = $convert.base64Decode( + 'CgtVbnNlYWxTdGFydBIjCg1jbGllbnRfcHVia2V5GAEgASgMUgxjbGllbnRQdWJrZXk='); + +@$core.Deprecated('Use unsealStartResponseDescriptor instead') +const UnsealStartResponse$json = { + '1': 'UnsealStartResponse', + '2': [ + {'1': 'server_pubkey', '3': 1, '4': 1, '5': 12, '10': 'serverPubkey'}, + ], +}; + +/// Descriptor for `UnsealStartResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List unsealStartResponseDescriptor = $convert.base64Decode( + 'ChNVbnNlYWxTdGFydFJlc3BvbnNlEiMKDXNlcnZlcl9wdWJrZXkYASABKAxSDHNlcnZlclB1Ym' + 'tleQ=='); + +@$core.Deprecated('Use unsealEncryptedKeyDescriptor instead') +const UnsealEncryptedKey$json = { + '1': 'UnsealEncryptedKey', + '2': [ + {'1': 'nonce', '3': 1, '4': 1, '5': 12, '10': 'nonce'}, + {'1': 'ciphertext', '3': 2, '4': 1, '5': 12, '10': 'ciphertext'}, + {'1': 'associated_data', '3': 3, '4': 1, '5': 12, '10': 'associatedData'}, + ], +}; + +/// Descriptor for `UnsealEncryptedKey`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List unsealEncryptedKeyDescriptor = $convert.base64Decode( + 'ChJVbnNlYWxFbmNyeXB0ZWRLZXkSFAoFbm9uY2UYASABKAxSBW5vbmNlEh4KCmNpcGhlcnRleH' + 'QYAiABKAxSCmNpcGhlcnRleHQSJwoPYXNzb2NpYXRlZF9kYXRhGAMgASgMUg5hc3NvY2lhdGVk' + 'RGF0YQ=='); + +@$core.Deprecated('Use requestDescriptor instead') +const Request$json = { + '1': 'Request', + '2': [ + { + '1': 'start', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.vault.unseal.UnsealStart', + '9': 0, + '10': 'start' + }, + { + '1': 'encrypted_key', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.vault.unseal.UnsealEncryptedKey', + '9': 0, + '10': 'encryptedKey' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( + 'CgdSZXF1ZXN0EkQKBXN0YXJ0GAEgASgLMiwuYXJiaXRlci51c2VyX2FnZW50LnZhdWx0LnVuc2' + 'VhbC5VbnNlYWxTdGFydEgAUgVzdGFydBJaCg1lbmNyeXB0ZWRfa2V5GAIgASgLMjMuYXJiaXRl' + 'ci51c2VyX2FnZW50LnZhdWx0LnVuc2VhbC5VbnNlYWxFbmNyeXB0ZWRLZXlIAFIMZW5jcnlwdG' + 'VkS2V5QgkKB3BheWxvYWQ='); + +@$core.Deprecated('Use responseDescriptor instead') +const Response$json = { + '1': 'Response', + '2': [ + { + '1': 'start', + '3': 1, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.vault.unseal.UnsealStartResponse', + '9': 0, + '10': 'start' + }, + { + '1': 'result', + '3': 2, + '4': 1, + '5': 14, + '6': '.arbiter.user_agent.vault.unseal.UnsealResult', + '9': 0, + '10': 'result' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( + 'CghSZXNwb25zZRJMCgVzdGFydBgBIAEoCzI0LmFyYml0ZXIudXNlcl9hZ2VudC52YXVsdC51bn' + 'NlYWwuVW5zZWFsU3RhcnRSZXNwb25zZUgAUgVzdGFydBJHCgZyZXN1bHQYAiABKA4yLS5hcmJp' + 'dGVyLnVzZXJfYWdlbnQudmF1bHQudW5zZWFsLlVuc2VhbFJlc3VsdEgAUgZyZXN1bHRCCQoHcG' + 'F5bG9hZA=='); diff --git a/useragent/lib/proto/user_agent/vault/vault.pb.dart b/useragent/lib/proto/user_agent/vault/vault.pb.dart index 6a772dd..b03f81c 100644 --- a/useragent/lib/proto/user_agent/vault/vault.pb.dart +++ b/useragent/lib/proto/user_agent/vault/vault.pb.dart @@ -1,235 +1,235 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/vault/vault.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports - -import 'dart:core' as $core; - -import 'package:protobuf/protobuf.dart' as $pb; -import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $0; - -import '../../shared/vault.pbenum.dart' as $3; -import 'bootstrap.pb.dart' as $2; -import 'unseal.pb.dart' as $1; - -export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; - -enum Request_Payload { queryState, unseal, bootstrap, notSet } - -class Request extends $pb.GeneratedMessage { - factory Request({ - $0.Empty? queryState, - $1.Request? unseal, - $2.Request? bootstrap, - }) { - final result = create(); - if (queryState != null) result.queryState = queryState; - if (unseal != null) result.unseal = unseal; - if (bootstrap != null) result.bootstrap = bootstrap; - return result; - } - - Request._(); - - factory Request.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Request.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { - 1: Request_Payload.queryState, - 2: Request_Payload.unseal, - 3: Request_Payload.bootstrap, - 0: Request_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Request', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.vault'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3]) - ..aOM<$0.Empty>(1, _omitFieldNames ? '' : 'queryState', - subBuilder: $0.Empty.create) - ..aOM<$1.Request>(2, _omitFieldNames ? '' : 'unseal', - subBuilder: $1.Request.create) - ..aOM<$2.Request>(3, _omitFieldNames ? '' : 'bootstrap', - subBuilder: $2.Request.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Request copyWith(void Function(Request) updates) => - super.copyWith((message) => updates(message as Request)) as Request; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Request create() => Request._(); - @$core.override - Request createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Request getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Request? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $0.Empty get queryState => $_getN(0); - @$pb.TagNumber(1) - set queryState($0.Empty value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasQueryState() => $_has(0); - @$pb.TagNumber(1) - void clearQueryState() => $_clearField(1); - @$pb.TagNumber(1) - $0.Empty ensureQueryState() => $_ensure(0); - - @$pb.TagNumber(2) - $1.Request get unseal => $_getN(1); - @$pb.TagNumber(2) - set unseal($1.Request value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasUnseal() => $_has(1); - @$pb.TagNumber(2) - void clearUnseal() => $_clearField(2); - @$pb.TagNumber(2) - $1.Request ensureUnseal() => $_ensure(1); - - @$pb.TagNumber(3) - $2.Request get bootstrap => $_getN(2); - @$pb.TagNumber(3) - set bootstrap($2.Request value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasBootstrap() => $_has(2); - @$pb.TagNumber(3) - void clearBootstrap() => $_clearField(3); - @$pb.TagNumber(3) - $2.Request ensureBootstrap() => $_ensure(2); -} - -enum Response_Payload { state, unseal, bootstrap, notSet } - -class Response extends $pb.GeneratedMessage { - factory Response({ - $3.VaultState? state, - $1.Response? unseal, - $2.Response? bootstrap, - }) { - final result = create(); - if (state != null) result.state = state; - if (unseal != null) result.unseal = unseal; - if (bootstrap != null) result.bootstrap = bootstrap; - return result; - } - - Response._(); - - factory Response.fromBuffer($core.List<$core.int> data, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromBuffer(data, registry); - factory Response.fromJson($core.String json, - [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => - create()..mergeFromJson(json, registry); - - static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { - 1: Response_Payload.state, - 2: Response_Payload.unseal, - 3: Response_Payload.bootstrap, - 0: Response_Payload.notSet - }; - static final $pb.BuilderInfo _i = $pb.BuilderInfo( - _omitMessageNames ? '' : 'Response', - package: const $pb.PackageName( - _omitMessageNames ? '' : 'arbiter.user_agent.vault'), - createEmptyInstance: create) - ..oo(0, [1, 2, 3]) - ..aE<$3.VaultState>(1, _omitFieldNames ? '' : 'state', - enumValues: $3.VaultState.values) - ..aOM<$1.Response>(2, _omitFieldNames ? '' : 'unseal', - subBuilder: $1.Response.create) - ..aOM<$2.Response>(3, _omitFieldNames ? '' : 'bootstrap', - subBuilder: $2.Response.create) - ..hasRequiredFields = false; - - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response clone() => deepCopy(); - @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') - Response copyWith(void Function(Response) updates) => - super.copyWith((message) => updates(message as Response)) as Response; - - @$core.override - $pb.BuilderInfo get info_ => _i; - - @$core.pragma('dart2js:noInline') - static Response create() => Response._(); - @$core.override - Response createEmptyInstance() => create(); - @$core.pragma('dart2js:noInline') - static Response getDefault() => - _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); - static Response? _defaultInstance; - - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; - @$pb.TagNumber(1) - @$pb.TagNumber(2) - @$pb.TagNumber(3) - void clearPayload() => $_clearField($_whichOneof(0)); - - @$pb.TagNumber(1) - $3.VaultState get state => $_getN(0); - @$pb.TagNumber(1) - set state($3.VaultState value) => $_setField(1, value); - @$pb.TagNumber(1) - $core.bool hasState() => $_has(0); - @$pb.TagNumber(1) - void clearState() => $_clearField(1); - - @$pb.TagNumber(2) - $1.Response get unseal => $_getN(1); - @$pb.TagNumber(2) - set unseal($1.Response value) => $_setField(2, value); - @$pb.TagNumber(2) - $core.bool hasUnseal() => $_has(1); - @$pb.TagNumber(2) - void clearUnseal() => $_clearField(2); - @$pb.TagNumber(2) - $1.Response ensureUnseal() => $_ensure(1); - - @$pb.TagNumber(3) - $2.Response get bootstrap => $_getN(2); - @$pb.TagNumber(3) - set bootstrap($2.Response value) => $_setField(3, value); - @$pb.TagNumber(3) - $core.bool hasBootstrap() => $_has(2); - @$pb.TagNumber(3) - void clearBootstrap() => $_clearField(3); - @$pb.TagNumber(3) - $2.Response ensureBootstrap() => $_ensure(2); -} - -const $core.bool _omitFieldNames = - $core.bool.fromEnvironment('protobuf.omit_field_names'); -const $core.bool _omitMessageNames = - $core.bool.fromEnvironment('protobuf.omit_message_names'); +// This is a generated file - do not edit. +// +// Generated from user_agent/vault/vault.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; +import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart' as $0; + +import '../../shared/vault.pbenum.dart' as $3; +import 'bootstrap.pb.dart' as $2; +import 'unseal.pb.dart' as $1; + +export 'package:protobuf/protobuf.dart' show GeneratedMessageGenericExtensions; + +enum Request_Payload { queryState, unseal, bootstrap, notSet } + +class Request extends $pb.GeneratedMessage { + factory Request({ + $0.Empty? queryState, + $1.Request? unseal, + $2.Request? bootstrap, + }) { + final result = create(); + if (queryState != null) result.queryState = queryState; + if (unseal != null) result.unseal = unseal; + if (bootstrap != null) result.bootstrap = bootstrap; + return result; + } + + Request._(); + + factory Request.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Request.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Request_Payload> _Request_PayloadByTag = { + 1: Request_Payload.queryState, + 2: Request_Payload.unseal, + 3: Request_Payload.bootstrap, + 0: Request_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Request', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.vault'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3]) + ..aOM<$0.Empty>(1, _omitFieldNames ? '' : 'queryState', + subBuilder: $0.Empty.create) + ..aOM<$1.Request>(2, _omitFieldNames ? '' : 'unseal', + subBuilder: $1.Request.create) + ..aOM<$2.Request>(3, _omitFieldNames ? '' : 'bootstrap', + subBuilder: $2.Request.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Request copyWith(void Function(Request) updates) => + super.copyWith((message) => updates(message as Request)) as Request; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Request create() => Request._(); + @$core.override + Request createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Request getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Request? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + Request_Payload whichPayload() => _Request_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $0.Empty get queryState => $_getN(0); + @$pb.TagNumber(1) + set queryState($0.Empty value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasQueryState() => $_has(0); + @$pb.TagNumber(1) + void clearQueryState() => $_clearField(1); + @$pb.TagNumber(1) + $0.Empty ensureQueryState() => $_ensure(0); + + @$pb.TagNumber(2) + $1.Request get unseal => $_getN(1); + @$pb.TagNumber(2) + set unseal($1.Request value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasUnseal() => $_has(1); + @$pb.TagNumber(2) + void clearUnseal() => $_clearField(2); + @$pb.TagNumber(2) + $1.Request ensureUnseal() => $_ensure(1); + + @$pb.TagNumber(3) + $2.Request get bootstrap => $_getN(2); + @$pb.TagNumber(3) + set bootstrap($2.Request value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasBootstrap() => $_has(2); + @$pb.TagNumber(3) + void clearBootstrap() => $_clearField(3); + @$pb.TagNumber(3) + $2.Request ensureBootstrap() => $_ensure(2); +} + +enum Response_Payload { state, unseal, bootstrap, notSet } + +class Response extends $pb.GeneratedMessage { + factory Response({ + $3.VaultState? state, + $1.Response? unseal, + $2.Response? bootstrap, + }) { + final result = create(); + if (state != null) result.state = state; + if (unseal != null) result.unseal = unseal; + if (bootstrap != null) result.bootstrap = bootstrap; + return result; + } + + Response._(); + + factory Response.fromBuffer($core.List<$core.int> data, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromBuffer(data, registry); + factory Response.fromJson($core.String json, + [$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) => + create()..mergeFromJson(json, registry); + + static const $core.Map<$core.int, Response_Payload> _Response_PayloadByTag = { + 1: Response_Payload.state, + 2: Response_Payload.unseal, + 3: Response_Payload.bootstrap, + 0: Response_Payload.notSet + }; + static final $pb.BuilderInfo _i = $pb.BuilderInfo( + _omitMessageNames ? '' : 'Response', + package: const $pb.PackageName( + _omitMessageNames ? '' : 'arbiter.user_agent.vault'), + createEmptyInstance: create) + ..oo(0, [1, 2, 3]) + ..aE<$3.VaultState>(1, _omitFieldNames ? '' : 'state', + enumValues: $3.VaultState.values) + ..aOM<$1.Response>(2, _omitFieldNames ? '' : 'unseal', + subBuilder: $1.Response.create) + ..aOM<$2.Response>(3, _omitFieldNames ? '' : 'bootstrap', + subBuilder: $2.Response.create) + ..hasRequiredFields = false; + + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response clone() => deepCopy(); + @$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.') + Response copyWith(void Function(Response) updates) => + super.copyWith((message) => updates(message as Response)) as Response; + + @$core.override + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static Response create() => Response._(); + @$core.override + Response createEmptyInstance() => create(); + @$core.pragma('dart2js:noInline') + static Response getDefault() => + _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static Response? _defaultInstance; + + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + Response_Payload whichPayload() => _Response_PayloadByTag[$_whichOneof(0)]!; + @$pb.TagNumber(1) + @$pb.TagNumber(2) + @$pb.TagNumber(3) + void clearPayload() => $_clearField($_whichOneof(0)); + + @$pb.TagNumber(1) + $3.VaultState get state => $_getN(0); + @$pb.TagNumber(1) + set state($3.VaultState value) => $_setField(1, value); + @$pb.TagNumber(1) + $core.bool hasState() => $_has(0); + @$pb.TagNumber(1) + void clearState() => $_clearField(1); + + @$pb.TagNumber(2) + $1.Response get unseal => $_getN(1); + @$pb.TagNumber(2) + set unseal($1.Response value) => $_setField(2, value); + @$pb.TagNumber(2) + $core.bool hasUnseal() => $_has(1); + @$pb.TagNumber(2) + void clearUnseal() => $_clearField(2); + @$pb.TagNumber(2) + $1.Response ensureUnseal() => $_ensure(1); + + @$pb.TagNumber(3) + $2.Response get bootstrap => $_getN(2); + @$pb.TagNumber(3) + set bootstrap($2.Response value) => $_setField(3, value); + @$pb.TagNumber(3) + $core.bool hasBootstrap() => $_has(2); + @$pb.TagNumber(3) + void clearBootstrap() => $_clearField(3); + @$pb.TagNumber(3) + $2.Response ensureBootstrap() => $_ensure(2); +} + +const $core.bool _omitFieldNames = + $core.bool.fromEnvironment('protobuf.omit_field_names'); +const $core.bool _omitMessageNames = + $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/useragent/lib/proto/user_agent/vault/vault.pbenum.dart b/useragent/lib/proto/user_agent/vault/vault.pbenum.dart index 43f87e3..0db8f5c 100644 --- a/useragent/lib/proto/user_agent/vault/vault.pbenum.dart +++ b/useragent/lib/proto/user_agent/vault/vault.pbenum.dart @@ -1,11 +1,11 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/vault/vault.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// This is a generated file - do not edit. +// +// Generated from user_agent/vault/vault.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports diff --git a/useragent/lib/proto/user_agent/vault/vault.pbjson.dart b/useragent/lib/proto/user_agent/vault/vault.pbjson.dart index 88e010f..d1a8461 100644 --- a/useragent/lib/proto/user_agent/vault/vault.pbjson.dart +++ b/useragent/lib/proto/user_agent/vault/vault.pbjson.dart @@ -1,105 +1,105 @@ -// This is a generated file - do not edit. -// -// Generated from user_agent/vault/vault.proto. - -// @dart = 3.3 - -// ignore_for_file: annotate_overrides, camel_case_types, comment_references -// ignore_for_file: constant_identifier_names -// ignore_for_file: curly_braces_in_flow_control_structures -// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes -// ignore_for_file: non_constant_identifier_names, prefer_relative_imports -// ignore_for_file: unused_import - -import 'dart:convert' as $convert; -import 'dart:core' as $core; -import 'dart:typed_data' as $typed_data; - -@$core.Deprecated('Use requestDescriptor instead') -const Request$json = { - '1': 'Request', - '2': [ - { - '1': 'query_state', - '3': 1, - '4': 1, - '5': 11, - '6': '.google.protobuf.Empty', - '9': 0, - '10': 'queryState' - }, - { - '1': 'unseal', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.vault.unseal.Request', - '9': 0, - '10': 'unseal' - }, - { - '1': 'bootstrap', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.vault.bootstrap.Request', - '9': 0, - '10': 'bootstrap' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( - 'CgdSZXF1ZXN0EjkKC3F1ZXJ5X3N0YXRlGAEgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SA' - 'BSCnF1ZXJ5U3RhdGUSQgoGdW5zZWFsGAIgASgLMiguYXJiaXRlci51c2VyX2FnZW50LnZhdWx0' - 'LnVuc2VhbC5SZXF1ZXN0SABSBnVuc2VhbBJLCglib290c3RyYXAYAyABKAsyKy5hcmJpdGVyLn' - 'VzZXJfYWdlbnQudmF1bHQuYm9vdHN0cmFwLlJlcXVlc3RIAFIJYm9vdHN0cmFwQgkKB3BheWxv' - 'YWQ='); - -@$core.Deprecated('Use responseDescriptor instead') -const Response$json = { - '1': 'Response', - '2': [ - { - '1': 'state', - '3': 1, - '4': 1, - '5': 14, - '6': '.arbiter.shared.VaultState', - '9': 0, - '10': 'state' - }, - { - '1': 'unseal', - '3': 2, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.vault.unseal.Response', - '9': 0, - '10': 'unseal' - }, - { - '1': 'bootstrap', - '3': 3, - '4': 1, - '5': 11, - '6': '.arbiter.user_agent.vault.bootstrap.Response', - '9': 0, - '10': 'bootstrap' - }, - ], - '8': [ - {'1': 'payload'}, - ], -}; - -/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( - 'CghSZXNwb25zZRIyCgVzdGF0ZRgBIAEoDjIaLmFyYml0ZXIuc2hhcmVkLlZhdWx0U3RhdGVIAF' - 'IFc3RhdGUSQwoGdW5zZWFsGAIgASgLMikuYXJiaXRlci51c2VyX2FnZW50LnZhdWx0LnVuc2Vh' - 'bC5SZXNwb25zZUgAUgZ1bnNlYWwSTAoJYm9vdHN0cmFwGAMgASgLMiwuYXJiaXRlci51c2VyX2' - 'FnZW50LnZhdWx0LmJvb3RzdHJhcC5SZXNwb25zZUgAUglib290c3RyYXBCCQoHcGF5bG9hZA=='); +// This is a generated file - do not edit. +// +// Generated from user_agent/vault/vault.proto. + +// @dart = 3.3 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: curly_braces_in_flow_control_structures +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_relative_imports +// ignore_for_file: unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use requestDescriptor instead') +const Request$json = { + '1': 'Request', + '2': [ + { + '1': 'query_state', + '3': 1, + '4': 1, + '5': 11, + '6': '.google.protobuf.Empty', + '9': 0, + '10': 'queryState' + }, + { + '1': 'unseal', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.vault.unseal.Request', + '9': 0, + '10': 'unseal' + }, + { + '1': 'bootstrap', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.vault.bootstrap.Request', + '9': 0, + '10': 'bootstrap' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Request`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List requestDescriptor = $convert.base64Decode( + 'CgdSZXF1ZXN0EjkKC3F1ZXJ5X3N0YXRlGAEgASgLMhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5SA' + 'BSCnF1ZXJ5U3RhdGUSQgoGdW5zZWFsGAIgASgLMiguYXJiaXRlci51c2VyX2FnZW50LnZhdWx0' + 'LnVuc2VhbC5SZXF1ZXN0SABSBnVuc2VhbBJLCglib290c3RyYXAYAyABKAsyKy5hcmJpdGVyLn' + 'VzZXJfYWdlbnQudmF1bHQuYm9vdHN0cmFwLlJlcXVlc3RIAFIJYm9vdHN0cmFwQgkKB3BheWxv' + 'YWQ='); + +@$core.Deprecated('Use responseDescriptor instead') +const Response$json = { + '1': 'Response', + '2': [ + { + '1': 'state', + '3': 1, + '4': 1, + '5': 14, + '6': '.arbiter.shared.VaultState', + '9': 0, + '10': 'state' + }, + { + '1': 'unseal', + '3': 2, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.vault.unseal.Response', + '9': 0, + '10': 'unseal' + }, + { + '1': 'bootstrap', + '3': 3, + '4': 1, + '5': 11, + '6': '.arbiter.user_agent.vault.bootstrap.Response', + '9': 0, + '10': 'bootstrap' + }, + ], + '8': [ + {'1': 'payload'}, + ], +}; + +/// Descriptor for `Response`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List responseDescriptor = $convert.base64Decode( + 'CghSZXNwb25zZRIyCgVzdGF0ZRgBIAEoDjIaLmFyYml0ZXIuc2hhcmVkLlZhdWx0U3RhdGVIAF' + 'IFc3RhdGUSQwoGdW5zZWFsGAIgASgLMikuYXJiaXRlci51c2VyX2FnZW50LnZhdWx0LnVuc2Vh' + 'bC5SZXNwb25zZUgAUgZ1bnNlYWwSTAoJYm9vdHN0cmFwGAMgASgLMiwuYXJiaXRlci51c2VyX2' + 'FnZW50LnZhdWx0LmJvb3RzdHJhcC5SZXNwb25zZUgAUglib290c3RyYXBCCQoHcGF5bG9hZA=='); diff --git a/useragent/lib/providers/connection/bootstrap_token.dart b/useragent/lib/providers/connection/bootstrap_token.dart index fef2bc8..7224c3d 100644 --- a/useragent/lib/providers/connection/bootstrap_token.dart +++ b/useragent/lib/providers/connection/bootstrap_token.dart @@ -1,25 +1,25 @@ -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'bootstrap_token.g.dart'; - -@Riverpod(keepAlive: true) -class BootstrapToken extends _$BootstrapToken { - @override - String? build() { - return null; - } - - void set(String token) { - state = token; - } - - void clear() { - state = null; - } - - String? take() { - final token = state; - state = null; - return token; - } -} +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'bootstrap_token.g.dart'; + +@Riverpod(keepAlive: true) +class BootstrapToken extends _$BootstrapToken { + @override + String? build() { + return null; + } + + void set(String token) { + state = token; + } + + void clear() { + state = null; + } + + String? take() { + final token = state; + state = null; + return token; + } +} diff --git a/useragent/lib/providers/connection/bootstrap_token.g.dart b/useragent/lib/providers/connection/bootstrap_token.g.dart index 0c46387..81d96a2 100644 --- a/useragent/lib/providers/connection/bootstrap_token.g.dart +++ b/useragent/lib/providers/connection/bootstrap_token.g.dart @@ -1,62 +1,62 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'bootstrap_token.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(BootstrapToken) -final bootstrapTokenProvider = BootstrapTokenProvider._(); - -final class BootstrapTokenProvider - extends $NotifierProvider { - BootstrapTokenProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'bootstrapTokenProvider', - isAutoDispose: false, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$bootstrapTokenHash(); - - @$internal - @override - BootstrapToken create() => BootstrapToken(); - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(String? value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider(value), - ); - } -} - -String _$bootstrapTokenHash() => r'5c09ea4480fc3a7fd0d0a0bced712912542cca5d'; - -abstract class _$BootstrapToken extends $Notifier { - String? build(); - @$mustCallSuper - @override - void runBuild() { - final ref = this.ref as $Ref; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, - String?, - Object?, - Object? - >; - element.handleCreate(ref, build); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'bootstrap_token.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(BootstrapToken) +final bootstrapTokenProvider = BootstrapTokenProvider._(); + +final class BootstrapTokenProvider + extends $NotifierProvider { + BootstrapTokenProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'bootstrapTokenProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$bootstrapTokenHash(); + + @$internal + @override + BootstrapToken create() => BootstrapToken(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(String? value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } +} + +String _$bootstrapTokenHash() => r'5c09ea4480fc3a7fd0d0a0bced712912542cca5d'; + +abstract class _$BootstrapToken extends $Notifier { + String? build(); + @$mustCallSuper + @override + void runBuild() { + final ref = this.ref as $Ref; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, + String?, + Object?, + Object? + >; + element.handleCreate(ref, build); + } +} diff --git a/useragent/lib/providers/connection/connection_manager.dart b/useragent/lib/providers/connection/connection_manager.dart index 49b673d..0915a16 100644 --- a/useragent/lib/providers/connection/connection_manager.dart +++ b/useragent/lib/providers/connection/connection_manager.dart @@ -1,46 +1,46 @@ -import 'package:arbiter/features/connection/auth.dart'; -import 'package:arbiter/features/connection/connection.dart'; -import 'package:arbiter/providers/connection/bootstrap_token.dart'; -import 'package:arbiter/providers/key.dart'; -import 'package:arbiter/providers/server_info.dart'; -import 'package:mtcore/markettakers.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'connection_manager.g.dart'; - -@Riverpod(keepAlive: true) -class ConnectionManager extends _$ConnectionManager { - @override - Future build() async { - final serverInfo = await ref.watch(serverInfoProvider.future); - final key = await ref.watch(keyProvider.future); - final token = ref.read(bootstrapTokenProvider); - - if (serverInfo == null || key == null) { - return null; - } - final Connection connection; - try { - connection = await connectAndAuthorize( - serverInfo, - key, - bootstrapToken: token, - ); - if (token != null) { - ref.read(bootstrapTokenProvider.notifier).clear(); - } - } catch (e) { - talker.handle(e); - rethrow; - } - - ref.onDispose(() { - final connection = state.asData?.value; - if (connection != null) { - connection.close(); - } - }); - - return connection; - } -} +import 'package:arbiter/features/connection/auth.dart'; +import 'package:arbiter/features/connection/connection.dart'; +import 'package:arbiter/providers/connection/bootstrap_token.dart'; +import 'package:arbiter/providers/key.dart'; +import 'package:arbiter/providers/server_info.dart'; +import 'package:mtcore/markettakers.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'connection_manager.g.dart'; + +@Riverpod(keepAlive: true) +class ConnectionManager extends _$ConnectionManager { + @override + Future build() async { + final serverInfo = await ref.watch(serverInfoProvider.future); + final key = await ref.watch(keyProvider.future); + final token = ref.read(bootstrapTokenProvider); + + if (serverInfo == null || key == null) { + return null; + } + final Connection connection; + try { + connection = await connectAndAuthorize( + serverInfo, + key, + bootstrapToken: token, + ); + if (token != null) { + ref.read(bootstrapTokenProvider.notifier).clear(); + } + } catch (e) { + talker.handle(e); + rethrow; + } + + ref.onDispose(() { + final connection = state.asData?.value; + if (connection != null) { + connection.close(); + } + }); + + return connection; + } +} diff --git a/useragent/lib/providers/connection/connection_manager.g.dart b/useragent/lib/providers/connection/connection_manager.g.dart index ce66127..385c8a5 100644 --- a/useragent/lib/providers/connection/connection_manager.g.dart +++ b/useragent/lib/providers/connection/connection_manager.g.dart @@ -1,54 +1,54 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'connection_manager.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(ConnectionManager) -final connectionManagerProvider = ConnectionManagerProvider._(); - -final class ConnectionManagerProvider - extends $AsyncNotifierProvider { - ConnectionManagerProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'connectionManagerProvider', - isAutoDispose: false, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$connectionManagerHash(); - - @$internal - @override - ConnectionManager create() => ConnectionManager(); -} - -String _$connectionManagerHash() => r'f471afb49bdcde77238424942f5af1716634f084'; - -abstract class _$ConnectionManager extends $AsyncNotifier { - FutureOr build(); - @$mustCallSuper - @override - void runBuild() { - final ref = this.ref as $Ref, Connection?>; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, Connection?>, - AsyncValue, - Object?, - Object? - >; - element.handleCreate(ref, build); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'connection_manager.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(ConnectionManager) +final connectionManagerProvider = ConnectionManagerProvider._(); + +final class ConnectionManagerProvider + extends $AsyncNotifierProvider { + ConnectionManagerProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'connectionManagerProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$connectionManagerHash(); + + @$internal + @override + ConnectionManager create() => ConnectionManager(); +} + +String _$connectionManagerHash() => r'f471afb49bdcde77238424942f5af1716634f084'; + +abstract class _$ConnectionManager extends $AsyncNotifier { + FutureOr build(); + @$mustCallSuper + @override + void runBuild() { + final ref = this.ref as $Ref, Connection?>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, Connection?>, + AsyncValue, + Object?, + Object? + >; + element.handleCreate(ref, build); + } +} diff --git a/useragent/lib/providers/evm/evm.dart b/useragent/lib/providers/evm/evm.dart index 9e73f70..def6b9c 100644 --- a/useragent/lib/providers/evm/evm.dart +++ b/useragent/lib/providers/evm/evm.dart @@ -1,46 +1,46 @@ -import 'package:arbiter/features/connection/evm.dart' as evm; -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'evm.g.dart'; - -@riverpod -class Evm extends _$Evm { - @override - Future?> build() async { - final connection = await ref.watch(connectionManagerProvider.future); - if (connection == null) { - return null; - } - - return evm.listEvmWallets(connection); - } - - Future refreshWallets() async { - final connection = await ref.read(connectionManagerProvider.future); - if (connection == null) { - state = const AsyncData(null); - return; - } - - state = const AsyncLoading(); - state = await AsyncValue.guard(() => evm.listEvmWallets(connection)); - } -} - -final createEvmWallet = Mutation(); - -Future executeCreateEvmWallet(MutationTarget target) async { - return await createEvmWallet.run(target, (tsx) async { - final connection = await tsx.get(connectionManagerProvider.future); - if (connection == null) { - throw Exception('Not connected to the server.'); - } - - await evm.createEvmWallet(connection); - - await tsx.get(evmProvider.notifier).refreshWallets(); - }); -} +import 'package:arbiter/features/connection/evm.dart' as evm; +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'evm.g.dart'; + +@riverpod +class Evm extends _$Evm { + @override + Future?> build() async { + final connection = await ref.watch(connectionManagerProvider.future); + if (connection == null) { + return null; + } + + return evm.listEvmWallets(connection); + } + + Future refreshWallets() async { + final connection = await ref.read(connectionManagerProvider.future); + if (connection == null) { + state = const AsyncData(null); + return; + } + + state = const AsyncLoading(); + state = await AsyncValue.guard(() => evm.listEvmWallets(connection)); + } +} + +final createEvmWallet = Mutation(); + +Future executeCreateEvmWallet(MutationTarget target) async { + return await createEvmWallet.run(target, (tsx) async { + final connection = await tsx.get(connectionManagerProvider.future); + if (connection == null) { + throw Exception('Not connected to the server.'); + } + + await evm.createEvmWallet(connection); + + await tsx.get(evmProvider.notifier).refreshWallets(); + }); +} diff --git a/useragent/lib/providers/evm/evm.g.dart b/useragent/lib/providers/evm/evm.g.dart index ab490d7..da527de 100644 --- a/useragent/lib/providers/evm/evm.g.dart +++ b/useragent/lib/providers/evm/evm.g.dart @@ -1,55 +1,55 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'evm.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(Evm) -final evmProvider = EvmProvider._(); - -final class EvmProvider - extends $AsyncNotifierProvider?> { - EvmProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'evmProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$evmHash(); - - @$internal - @override - Evm create() => Evm(); -} - -String _$evmHash() => r'ca2c9736065c5dc7cc45d8485000dd85dfbfa572'; - -abstract class _$Evm extends $AsyncNotifier?> { - FutureOr?> build(); - @$mustCallSuper - @override - void runBuild() { - final ref = - this.ref as $Ref?>, List?>; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier?>, List?>, - AsyncValue?>, - Object?, - Object? - >; - element.handleCreate(ref, build); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'evm.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(Evm) +final evmProvider = EvmProvider._(); + +final class EvmProvider + extends $AsyncNotifierProvider?> { + EvmProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'evmProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$evmHash(); + + @$internal + @override + Evm create() => Evm(); +} + +String _$evmHash() => r'ca2c9736065c5dc7cc45d8485000dd85dfbfa572'; + +abstract class _$Evm extends $AsyncNotifier?> { + FutureOr?> build(); + @$mustCallSuper + @override + void runBuild() { + final ref = + this.ref as $Ref?>, List?>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier?>, List?>, + AsyncValue?>, + Object?, + Object? + >; + element.handleCreate(ref, build); + } +} diff --git a/useragent/lib/providers/evm/evm_grants.dart b/useragent/lib/providers/evm/evm_grants.dart index fb03342..27a257c 100644 --- a/useragent/lib/providers/evm/evm_grants.dart +++ b/useragent/lib/providers/evm/evm_grants.dart @@ -1,105 +1,105 @@ -import 'package:arbiter/features/connection/evm/grants.dart'; -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; -import 'package:mtcore/markettakers.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'evm_grants.freezed.dart'; -part 'evm_grants.g.dart'; - -final createEvmGrantMutation = Mutation(); -final revokeEvmGrantMutation = Mutation(); - -@freezed -abstract class EvmGrantsState with _$EvmGrantsState { - const EvmGrantsState._(); - - const factory EvmGrantsState({ - required List grants, - @Default(false) bool showRevoked, - }) = _EvmGrantsState; - - bool get revokedFilterBackedByServer => false; -} - -@riverpod -class EvmGrants extends _$EvmGrants { - @override - Future build() async { - final connection = await ref.watch(connectionManagerProvider.future); - if (connection == null) { - return null; - } - - try { - final grants = await listEvmGrants(connection); - return EvmGrantsState(grants: grants); - } catch (e, st) { - talker.handle(e, st); - rethrow; - } - } - - void toggleShowRevoked(bool value) { - final current = state.asData?.value; - if (current == null) { - return; - } - state = AsyncData(current.copyWith(showRevoked: value)); - } - - Future refresh() async { - final connection = await ref.read(connectionManagerProvider.future); - if (connection == null) { - state = const AsyncData(null); - return; - } - - final previous = state.asData?.value; - state = const AsyncLoading(); - - state = await AsyncValue.guard(() async { - final grants = await listEvmGrants(connection); - return EvmGrantsState( - grants: grants, - showRevoked: previous?.showRevoked ?? false, - ); - }); - } -} - -Future executeCreateEvmGrant( - MutationTarget ref, { - required SharedSettings sharedSettings, - required SpecificGrant specific, -}) { - return createEvmGrantMutation.run(ref, (tsx) async { - final connection = await tsx.get(connectionManagerProvider.future); - if (connection == null) { - throw Exception('Not connected to the server.'); - } - - final grantId = await createEvmGrant( - connection, - sharedSettings: sharedSettings, - specific: specific, - ); - - await tsx.get(evmGrantsProvider.notifier).refresh(); - return grantId; - }); -} - -Future executeRevokeEvmGrant(MutationTarget ref, {required int grantId}) { - return revokeEvmGrantMutation.run(ref, (tsx) async { - final connection = await tsx.get(connectionManagerProvider.future); - if (connection == null) { - throw Exception('Not connected to the server.'); - } - - await deleteEvmGrant(connection, grantId); - await tsx.get(evmGrantsProvider.notifier).refresh(); - }); -} +import 'package:arbiter/features/connection/evm/grants.dart'; +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; +import 'package:mtcore/markettakers.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'evm_grants.freezed.dart'; +part 'evm_grants.g.dart'; + +final createEvmGrantMutation = Mutation(); +final revokeEvmGrantMutation = Mutation(); + +@freezed +abstract class EvmGrantsState with _$EvmGrantsState { + const EvmGrantsState._(); + + const factory EvmGrantsState({ + required List grants, + @Default(false) bool showRevoked, + }) = _EvmGrantsState; + + bool get revokedFilterBackedByServer => false; +} + +@riverpod +class EvmGrants extends _$EvmGrants { + @override + Future build() async { + final connection = await ref.watch(connectionManagerProvider.future); + if (connection == null) { + return null; + } + + try { + final grants = await listEvmGrants(connection); + return EvmGrantsState(grants: grants); + } catch (e, st) { + talker.handle(e, st); + rethrow; + } + } + + void toggleShowRevoked(bool value) { + final current = state.asData?.value; + if (current == null) { + return; + } + state = AsyncData(current.copyWith(showRevoked: value)); + } + + Future refresh() async { + final connection = await ref.read(connectionManagerProvider.future); + if (connection == null) { + state = const AsyncData(null); + return; + } + + final previous = state.asData?.value; + state = const AsyncLoading(); + + state = await AsyncValue.guard(() async { + final grants = await listEvmGrants(connection); + return EvmGrantsState( + grants: grants, + showRevoked: previous?.showRevoked ?? false, + ); + }); + } +} + +Future executeCreateEvmGrant( + MutationTarget ref, { + required SharedSettings sharedSettings, + required SpecificGrant specific, +}) { + return createEvmGrantMutation.run(ref, (tsx) async { + final connection = await tsx.get(connectionManagerProvider.future); + if (connection == null) { + throw Exception('Not connected to the server.'); + } + + final grantId = await createEvmGrant( + connection, + sharedSettings: sharedSettings, + specific: specific, + ); + + await tsx.get(evmGrantsProvider.notifier).refresh(); + return grantId; + }); +} + +Future executeRevokeEvmGrant(MutationTarget ref, {required int grantId}) { + return revokeEvmGrantMutation.run(ref, (tsx) async { + final connection = await tsx.get(connectionManagerProvider.future); + if (connection == null) { + throw Exception('Not connected to the server.'); + } + + await deleteEvmGrant(connection, grantId); + await tsx.get(evmGrantsProvider.notifier).refresh(); + }); +} diff --git a/useragent/lib/providers/evm/evm_grants.freezed.dart b/useragent/lib/providers/evm/evm_grants.freezed.dart index 9797bb7..70eeae5 100644 --- a/useragent/lib/providers/evm/evm_grants.freezed.dart +++ b/useragent/lib/providers/evm/evm_grants.freezed.dart @@ -1,280 +1,280 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND -// coverage:ignore-file -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'evm_grants.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -// dart format off -T _$identity(T value) => value; -/// @nodoc -mixin _$EvmGrantsState { - - List get grants; bool get showRevoked; -/// Create a copy of EvmGrantsState -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$EvmGrantsStateCopyWith get copyWith => _$EvmGrantsStateCopyWithImpl(this as EvmGrantsState, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is EvmGrantsState&&const DeepCollectionEquality().equals(other.grants, grants)&&(identical(other.showRevoked, showRevoked) || other.showRevoked == showRevoked)); -} - - -@override -int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(grants),showRevoked); - -@override -String toString() { - return 'EvmGrantsState(grants: $grants, showRevoked: $showRevoked)'; -} - - -} - -/// @nodoc -abstract mixin class $EvmGrantsStateCopyWith<$Res> { - factory $EvmGrantsStateCopyWith(EvmGrantsState value, $Res Function(EvmGrantsState) _then) = _$EvmGrantsStateCopyWithImpl; -@useResult -$Res call({ - List grants, bool showRevoked -}); - - - - -} -/// @nodoc -class _$EvmGrantsStateCopyWithImpl<$Res> - implements $EvmGrantsStateCopyWith<$Res> { - _$EvmGrantsStateCopyWithImpl(this._self, this._then); - - final EvmGrantsState _self; - final $Res Function(EvmGrantsState) _then; - -/// Create a copy of EvmGrantsState -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? grants = null,Object? showRevoked = null,}) { - return _then(_self.copyWith( -grants: null == grants ? _self.grants : grants // ignore: cast_nullable_to_non_nullable -as List,showRevoked: null == showRevoked ? _self.showRevoked : showRevoked // ignore: cast_nullable_to_non_nullable -as bool, - )); -} - -} - - -/// Adds pattern-matching-related methods to [EvmGrantsState]. -extension EvmGrantsStatePatterns on EvmGrantsState { -/// A variant of `map` that fallback to returning `orElse`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeMap(TResult Function( _EvmGrantsState value)? $default,{required TResult orElse(),}){ -final _that = this; -switch (_that) { -case _EvmGrantsState() when $default != null: -return $default(_that);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// Callbacks receives the raw object, upcasted. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case final Subclass2 value: -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult map(TResult Function( _EvmGrantsState value) $default,){ -final _that = this; -switch (_that) { -case _EvmGrantsState(): -return $default(_that);case _: - throw StateError('Unexpected subclass'); - -} -} -/// A variant of `map` that fallback to returning `null`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? mapOrNull(TResult? Function( _EvmGrantsState value)? $default,){ -final _that = this; -switch (_that) { -case _EvmGrantsState() when $default != null: -return $default(_that);case _: - return null; - -} -} -/// A variant of `when` that fallback to an `orElse` callback. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeWhen(TResult Function( List grants, bool showRevoked)? $default,{required TResult orElse(),}) {final _that = this; -switch (_that) { -case _EvmGrantsState() when $default != null: -return $default(_that.grants,_that.showRevoked);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// As opposed to `map`, this offers destructuring. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case Subclass2(:final field2): -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult when(TResult Function( List grants, bool showRevoked) $default,) {final _that = this; -switch (_that) { -case _EvmGrantsState(): -return $default(_that.grants,_that.showRevoked);case _: - throw StateError('Unexpected subclass'); - -} -} -/// A variant of `when` that fallback to returning `null` -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? whenOrNull(TResult? Function( List grants, bool showRevoked)? $default,) {final _that = this; -switch (_that) { -case _EvmGrantsState() when $default != null: -return $default(_that.grants,_that.showRevoked);case _: - return null; - -} -} - -} - -/// @nodoc - - -class _EvmGrantsState extends EvmGrantsState { - const _EvmGrantsState({required final List grants, this.showRevoked = false}): _grants = grants,super._(); - - - final List _grants; -@override List get grants { - if (_grants is EqualUnmodifiableListView) return _grants; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_grants); -} - -@override@JsonKey() final bool showRevoked; - -/// Create a copy of EvmGrantsState -/// with the given fields replaced by the non-null parameter values. -@override @JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -_$EvmGrantsStateCopyWith<_EvmGrantsState> get copyWith => __$EvmGrantsStateCopyWithImpl<_EvmGrantsState>(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _EvmGrantsState&&const DeepCollectionEquality().equals(other._grants, _grants)&&(identical(other.showRevoked, showRevoked) || other.showRevoked == showRevoked)); -} - - -@override -int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_grants),showRevoked); - -@override -String toString() { - return 'EvmGrantsState(grants: $grants, showRevoked: $showRevoked)'; -} - - -} - -/// @nodoc -abstract mixin class _$EvmGrantsStateCopyWith<$Res> implements $EvmGrantsStateCopyWith<$Res> { - factory _$EvmGrantsStateCopyWith(_EvmGrantsState value, $Res Function(_EvmGrantsState) _then) = __$EvmGrantsStateCopyWithImpl; -@override @useResult -$Res call({ - List grants, bool showRevoked -}); - - - - -} -/// @nodoc -class __$EvmGrantsStateCopyWithImpl<$Res> - implements _$EvmGrantsStateCopyWith<$Res> { - __$EvmGrantsStateCopyWithImpl(this._self, this._then); - - final _EvmGrantsState _self; - final $Res Function(_EvmGrantsState) _then; - -/// Create a copy of EvmGrantsState -/// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? grants = null,Object? showRevoked = null,}) { - return _then(_EvmGrantsState( -grants: null == grants ? _self._grants : grants // ignore: cast_nullable_to_non_nullable -as List,showRevoked: null == showRevoked ? _self.showRevoked : showRevoked // ignore: cast_nullable_to_non_nullable -as bool, - )); -} - - -} - -// dart format on +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'evm_grants.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$EvmGrantsState { + + List get grants; bool get showRevoked; +/// Create a copy of EvmGrantsState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$EvmGrantsStateCopyWith get copyWith => _$EvmGrantsStateCopyWithImpl(this as EvmGrantsState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is EvmGrantsState&&const DeepCollectionEquality().equals(other.grants, grants)&&(identical(other.showRevoked, showRevoked) || other.showRevoked == showRevoked)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(grants),showRevoked); + +@override +String toString() { + return 'EvmGrantsState(grants: $grants, showRevoked: $showRevoked)'; +} + + +} + +/// @nodoc +abstract mixin class $EvmGrantsStateCopyWith<$Res> { + factory $EvmGrantsStateCopyWith(EvmGrantsState value, $Res Function(EvmGrantsState) _then) = _$EvmGrantsStateCopyWithImpl; +@useResult +$Res call({ + List grants, bool showRevoked +}); + + + + +} +/// @nodoc +class _$EvmGrantsStateCopyWithImpl<$Res> + implements $EvmGrantsStateCopyWith<$Res> { + _$EvmGrantsStateCopyWithImpl(this._self, this._then); + + final EvmGrantsState _self; + final $Res Function(EvmGrantsState) _then; + +/// Create a copy of EvmGrantsState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? grants = null,Object? showRevoked = null,}) { + return _then(_self.copyWith( +grants: null == grants ? _self.grants : grants // ignore: cast_nullable_to_non_nullable +as List,showRevoked: null == showRevoked ? _self.showRevoked : showRevoked // ignore: cast_nullable_to_non_nullable +as bool, + )); +} + +} + + +/// Adds pattern-matching-related methods to [EvmGrantsState]. +extension EvmGrantsStatePatterns on EvmGrantsState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _EvmGrantsState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _EvmGrantsState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _EvmGrantsState value) $default,){ +final _that = this; +switch (_that) { +case _EvmGrantsState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _EvmGrantsState value)? $default,){ +final _that = this; +switch (_that) { +case _EvmGrantsState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List grants, bool showRevoked)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _EvmGrantsState() when $default != null: +return $default(_that.grants,_that.showRevoked);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List grants, bool showRevoked) $default,) {final _that = this; +switch (_that) { +case _EvmGrantsState(): +return $default(_that.grants,_that.showRevoked);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List grants, bool showRevoked)? $default,) {final _that = this; +switch (_that) { +case _EvmGrantsState() when $default != null: +return $default(_that.grants,_that.showRevoked);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _EvmGrantsState extends EvmGrantsState { + const _EvmGrantsState({required final List grants, this.showRevoked = false}): _grants = grants,super._(); + + + final List _grants; +@override List get grants { + if (_grants is EqualUnmodifiableListView) return _grants; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_grants); +} + +@override@JsonKey() final bool showRevoked; + +/// Create a copy of EvmGrantsState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$EvmGrantsStateCopyWith<_EvmGrantsState> get copyWith => __$EvmGrantsStateCopyWithImpl<_EvmGrantsState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _EvmGrantsState&&const DeepCollectionEquality().equals(other._grants, _grants)&&(identical(other.showRevoked, showRevoked) || other.showRevoked == showRevoked)); +} + + +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_grants),showRevoked); + +@override +String toString() { + return 'EvmGrantsState(grants: $grants, showRevoked: $showRevoked)'; +} + + +} + +/// @nodoc +abstract mixin class _$EvmGrantsStateCopyWith<$Res> implements $EvmGrantsStateCopyWith<$Res> { + factory _$EvmGrantsStateCopyWith(_EvmGrantsState value, $Res Function(_EvmGrantsState) _then) = __$EvmGrantsStateCopyWithImpl; +@override @useResult +$Res call({ + List grants, bool showRevoked +}); + + + + +} +/// @nodoc +class __$EvmGrantsStateCopyWithImpl<$Res> + implements _$EvmGrantsStateCopyWith<$Res> { + __$EvmGrantsStateCopyWithImpl(this._self, this._then); + + final _EvmGrantsState _self; + final $Res Function(_EvmGrantsState) _then; + +/// Create a copy of EvmGrantsState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? grants = null,Object? showRevoked = null,}) { + return _then(_EvmGrantsState( +grants: null == grants ? _self._grants : grants // ignore: cast_nullable_to_non_nullable +as List,showRevoked: null == showRevoked ? _self.showRevoked : showRevoked // ignore: cast_nullable_to_non_nullable +as bool, + )); +} + + +} + +// dart format on diff --git a/useragent/lib/providers/evm/evm_grants.g.dart b/useragent/lib/providers/evm/evm_grants.g.dart index f0e97e8..71b6f7c 100644 --- a/useragent/lib/providers/evm/evm_grants.g.dart +++ b/useragent/lib/providers/evm/evm_grants.g.dart @@ -1,54 +1,54 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'evm_grants.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(EvmGrants) -final evmGrantsProvider = EvmGrantsProvider._(); - -final class EvmGrantsProvider - extends $AsyncNotifierProvider { - EvmGrantsProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'evmGrantsProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$evmGrantsHash(); - - @$internal - @override - EvmGrants create() => EvmGrants(); -} - -String _$evmGrantsHash() => r'd71ec12bbc1b412f11fdbaae27382b289f8a3538'; - -abstract class _$EvmGrants extends $AsyncNotifier { - FutureOr build(); - @$mustCallSuper - @override - void runBuild() { - final ref = this.ref as $Ref, EvmGrantsState?>; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, EvmGrantsState?>, - AsyncValue, - Object?, - Object? - >; - element.handleCreate(ref, build); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'evm_grants.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(EvmGrants) +final evmGrantsProvider = EvmGrantsProvider._(); + +final class EvmGrantsProvider + extends $AsyncNotifierProvider { + EvmGrantsProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'evmGrantsProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$evmGrantsHash(); + + @$internal + @override + EvmGrants create() => EvmGrants(); +} + +String _$evmGrantsHash() => r'd71ec12bbc1b412f11fdbaae27382b289f8a3538'; + +abstract class _$EvmGrants extends $AsyncNotifier { + FutureOr build(); + @$mustCallSuper + @override + void runBuild() { + final ref = this.ref as $Ref, EvmGrantsState?>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, EvmGrantsState?>, + AsyncValue, + Object?, + Object? + >; + element.handleCreate(ref, build); + } +} diff --git a/useragent/lib/providers/key.dart b/useragent/lib/providers/key.dart index 4ad9662..a2f232e 100644 --- a/useragent/lib/providers/key.dart +++ b/useragent/lib/providers/key.dart @@ -1,59 +1,59 @@ -import 'package:mtcore/markettakers.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:arbiter/features/identity/pk_manager.dart'; -import 'package:arbiter/features/identity/hazmat_mldsa.dart'; - -part 'key.g.dart'; - -@riverpod -KeyManager keyManager(Ref ref) { - return HazmatMLDSAManager(); -} - -@Riverpod(keepAlive: true) -class Key extends _$Key { - @override - Future build() async { - final manager = ref.watch(keyManagerProvider); - final keyHandle = await manager.get(); - return keyHandle; - } - - Future create() async { - final manager = ref.watch(keyManagerProvider); - if (state.value != null) { - return; - } - - state = await AsyncValue.guard(() async { - final newKeyHandle = await manager.create(); - return newKeyHandle; - }); - } -} - -class KeyBootstrapper implements StageFactory { - final ProviderContainer ref; - - KeyBootstrapper({required this.ref}); - - @override - String get title => "Setting up your identity"; - - @override - Future get isAlreadyCompleted async { - final key = await ref.read(keyProvider.future); - return key != null; - } - - @override - Future start(StageController controller) async { - controller.setIndefiniteProgress(); - final key = ref.read(keyProvider.notifier); - - await key.create(); - } - - @override - void dispose() {} -} +import 'package:mtcore/markettakers.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:arbiter/features/identity/pk_manager.dart'; +import 'package:arbiter/features/identity/hazmat_mldsa.dart'; + +part 'key.g.dart'; + +@riverpod +KeyManager keyManager(Ref ref) { + return HazmatMLDSAManager(); +} + +@Riverpod(keepAlive: true) +class Key extends _$Key { + @override + Future build() async { + final manager = ref.watch(keyManagerProvider); + final keyHandle = await manager.get(); + return keyHandle; + } + + Future create() async { + final manager = ref.watch(keyManagerProvider); + if (state.value != null) { + return; + } + + state = await AsyncValue.guard(() async { + final newKeyHandle = await manager.create(); + return newKeyHandle; + }); + } +} + +class KeyBootstrapper implements StageFactory { + final ProviderContainer ref; + + KeyBootstrapper({required this.ref}); + + @override + String get title => "Setting up your identity"; + + @override + Future get isAlreadyCompleted async { + final key = await ref.read(keyProvider.future); + return key != null; + } + + @override + Future start(StageController controller) async { + controller.setIndefiniteProgress(); + final key = ref.read(keyProvider.notifier); + + await key.create(); + } + + @override + void dispose() {} +} diff --git a/useragent/lib/providers/key.g.dart b/useragent/lib/providers/key.g.dart index c827cab..001dfb3 100644 --- a/useragent/lib/providers/key.g.dart +++ b/useragent/lib/providers/key.g.dart @@ -1,94 +1,94 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'key.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(keyManager) -final keyManagerProvider = KeyManagerProvider._(); - -final class KeyManagerProvider - extends $FunctionalProvider - with $Provider { - KeyManagerProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'keyManagerProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$keyManagerHash(); - - @$internal - @override - $ProviderElement $createElement($ProviderPointer pointer) => - $ProviderElement(pointer); - - @override - KeyManager create(Ref ref) { - return keyManager(ref); - } - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(KeyManager value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider(value), - ); - } -} - -String _$keyManagerHash() => r'aa37bca34c01a39c11e29d57e320172b37c0b116'; - -@ProviderFor(Key) -final keyProvider = KeyProvider._(); - -final class KeyProvider extends $AsyncNotifierProvider { - KeyProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'keyProvider', - isAutoDispose: false, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$keyHash(); - - @$internal - @override - Key create() => Key(); -} - -String _$keyHash() => r'37b209825067adadbb75fe0b4ce936ea1c201dc8'; - -abstract class _$Key extends $AsyncNotifier { - FutureOr build(); - @$mustCallSuper - @override - void runBuild() { - final ref = this.ref as $Ref, KeyHandle?>; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, KeyHandle?>, - AsyncValue, - Object?, - Object? - >; - element.handleCreate(ref, build); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'key.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(keyManager) +final keyManagerProvider = KeyManagerProvider._(); + +final class KeyManagerProvider + extends $FunctionalProvider + with $Provider { + KeyManagerProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'keyManagerProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$keyManagerHash(); + + @$internal + @override + $ProviderElement $createElement($ProviderPointer pointer) => + $ProviderElement(pointer); + + @override + KeyManager create(Ref ref) { + return keyManager(ref); + } + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(KeyManager value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } +} + +String _$keyManagerHash() => r'aa37bca34c01a39c11e29d57e320172b37c0b116'; + +@ProviderFor(Key) +final keyProvider = KeyProvider._(); + +final class KeyProvider extends $AsyncNotifierProvider { + KeyProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'keyProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$keyHash(); + + @$internal + @override + Key create() => Key(); +} + +String _$keyHash() => r'37b209825067adadbb75fe0b4ce936ea1c201dc8'; + +abstract class _$Key extends $AsyncNotifier { + FutureOr build(); + @$mustCallSuper + @override + void runBuild() { + final ref = this.ref as $Ref, KeyHandle?>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, KeyHandle?>, + AsyncValue, + Object?, + Object? + >; + element.handleCreate(ref, build); + } +} diff --git a/useragent/lib/providers/sdk_clients/details.dart b/useragent/lib/providers/sdk_clients/details.dart index b6939f2..5da660b 100644 --- a/useragent/lib/providers/sdk_clients/details.dart +++ b/useragent/lib/providers/sdk_clients/details.dart @@ -1,19 +1,19 @@ -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/providers/sdk_clients/list.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'details.g.dart'; - -@riverpod -Future clientDetails(Ref ref, int clientId) async { - final clients = await ref.watch(sdkClientsProvider.future); - if (clients == null) { - return null; - } - for (final client in clients) { - if (client.id == clientId) { - return client; - } - } - return null; -} +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/providers/sdk_clients/list.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'details.g.dart'; + +@riverpod +Future clientDetails(Ref ref, int clientId) async { + final clients = await ref.watch(sdkClientsProvider.future); + if (clients == null) { + return null; + } + for (final client in clients) { + if (client.id == clientId) { + return client; + } + } + return null; +} diff --git a/useragent/lib/providers/sdk_clients/details.g.dart b/useragent/lib/providers/sdk_clients/details.g.dart index 5c77abf..3960004 100644 --- a/useragent/lib/providers/sdk_clients/details.g.dart +++ b/useragent/lib/providers/sdk_clients/details.g.dart @@ -1,85 +1,85 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'details.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(clientDetails) -final clientDetailsProvider = ClientDetailsFamily._(); - -final class ClientDetailsProvider - extends - $FunctionalProvider< - AsyncValue, - ua_sdk.Entry?, - FutureOr - > - with $FutureModifier, $FutureProvider { - ClientDetailsProvider._({ - required ClientDetailsFamily super.from, - required int super.argument, - }) : super( - retry: null, - name: r'clientDetailsProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$clientDetailsHash(); - - @override - String toString() { - return r'clientDetailsProvider' - '' - '($argument)'; - } - - @$internal - @override - $FutureProviderElement $createElement( - $ProviderPointer pointer, - ) => $FutureProviderElement(pointer); - - @override - FutureOr create(Ref ref) { - final argument = this.argument as int; - return clientDetails(ref, argument); - } - - @override - bool operator ==(Object other) { - return other is ClientDetailsProvider && other.argument == argument; - } - - @override - int get hashCode { - return argument.hashCode; - } -} - -String _$clientDetailsHash() => r'907fd39230cc630dcaad3bbe924f343a84a2375e'; - -final class ClientDetailsFamily extends $Family - with $FunctionalFamilyOverride, int> { - ClientDetailsFamily._() - : super( - retry: null, - name: r'clientDetailsProvider', - dependencies: null, - $allTransitiveDependencies: null, - isAutoDispose: true, - ); - - ClientDetailsProvider call(int clientId) => - ClientDetailsProvider._(argument: clientId, from: this); - - @override - String toString() => r'clientDetailsProvider'; -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'details.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(clientDetails) +final clientDetailsProvider = ClientDetailsFamily._(); + +final class ClientDetailsProvider + extends + $FunctionalProvider< + AsyncValue, + ua_sdk.Entry?, + FutureOr + > + with $FutureModifier, $FutureProvider { + ClientDetailsProvider._({ + required ClientDetailsFamily super.from, + required int super.argument, + }) : super( + retry: null, + name: r'clientDetailsProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$clientDetailsHash(); + + @override + String toString() { + return r'clientDetailsProvider' + '' + '($argument)'; + } + + @$internal + @override + $FutureProviderElement $createElement( + $ProviderPointer pointer, + ) => $FutureProviderElement(pointer); + + @override + FutureOr create(Ref ref) { + final argument = this.argument as int; + return clientDetails(ref, argument); + } + + @override + bool operator ==(Object other) { + return other is ClientDetailsProvider && other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$clientDetailsHash() => r'907fd39230cc630dcaad3bbe924f343a84a2375e'; + +final class ClientDetailsFamily extends $Family + with $FunctionalFamilyOverride, int> { + ClientDetailsFamily._() + : super( + retry: null, + name: r'clientDetailsProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + ClientDetailsProvider call(int clientId) => + ClientDetailsProvider._(argument: clientId, from: this); + + @override + String toString() => r'clientDetailsProvider'; +} diff --git a/useragent/lib/providers/sdk_clients/list.dart b/useragent/lib/providers/sdk_clients/list.dart index 4a52818..858a693 100644 --- a/useragent/lib/providers/sdk_clients/list.dart +++ b/useragent/lib/providers/sdk_clients/list.dart @@ -1,39 +1,39 @@ -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/proto/user_agent.pb.dart'; -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'list.g.dart'; - -@riverpod -Future?> sdkClients(Ref ref) async { - final connection = await ref.watch(connectionManagerProvider.future); - if (connection == null) { - return null; - } - - final resp = await connection.ask( - UserAgentRequest(sdkClient: ua_sdk.Request(list: Empty())), - ); - - if (!resp.hasSdkClient()) { - throw Exception('Expected SDK client response, got ${resp.whichPayload()}'); - } - final sdkClientResponse = resp.sdkClient; - if (!sdkClientResponse.hasList()) { - throw Exception( - 'Expected SDK client list response, got ${sdkClientResponse.whichPayload()}', - ); - } - final result = sdkClientResponse.list; - - switch (result.whichResult()) { - case ua_sdk.ListResponse_Result.clients: - return result.clients.clients.toList(growable: false); - case ua_sdk.ListResponse_Result.error: - throw Exception('Error listing SDK clients: ${result.error}'); - case ua_sdk.ListResponse_Result.notSet: - throw Exception('SDK client list response was empty.'); - } -} +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/proto/user_agent.pb.dart'; +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'list.g.dart'; + +@riverpod +Future?> sdkClients(Ref ref) async { + final connection = await ref.watch(connectionManagerProvider.future); + if (connection == null) { + return null; + } + + final resp = await connection.ask( + UserAgentRequest(sdkClient: ua_sdk.Request(list: Empty())), + ); + + if (!resp.hasSdkClient()) { + throw Exception('Expected SDK client response, got ${resp.whichPayload()}'); + } + final sdkClientResponse = resp.sdkClient; + if (!sdkClientResponse.hasList()) { + throw Exception( + 'Expected SDK client list response, got ${sdkClientResponse.whichPayload()}', + ); + } + final result = sdkClientResponse.list; + + switch (result.whichResult()) { + case ua_sdk.ListResponse_Result.clients: + return result.clients.clients.toList(growable: false); + case ua_sdk.ListResponse_Result.error: + throw Exception('Error listing SDK clients: ${result.error}'); + case ua_sdk.ListResponse_Result.notSet: + throw Exception('SDK client list response was empty.'); + } +} diff --git a/useragent/lib/providers/sdk_clients/list.g.dart b/useragent/lib/providers/sdk_clients/list.g.dart index e506d5a..fc1e293 100644 --- a/useragent/lib/providers/sdk_clients/list.g.dart +++ b/useragent/lib/providers/sdk_clients/list.g.dart @@ -1,51 +1,51 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'list.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(sdkClients) -final sdkClientsProvider = SdkClientsProvider._(); - -final class SdkClientsProvider - extends - $FunctionalProvider< - AsyncValue?>, - List?, - FutureOr?> - > - with - $FutureModifier?>, - $FutureProvider?> { - SdkClientsProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'sdkClientsProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$sdkClientsHash(); - - @$internal - @override - $FutureProviderElement?> $createElement( - $ProviderPointer pointer, - ) => $FutureProviderElement(pointer); - - @override - FutureOr?> create(Ref ref) { - return sdkClients(ref); - } -} - -String _$sdkClientsHash() => r'9b966083effea11035d6edde379e71cc2a0f85c0'; +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'list.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(sdkClients) +final sdkClientsProvider = SdkClientsProvider._(); + +final class SdkClientsProvider + extends + $FunctionalProvider< + AsyncValue?>, + List?, + FutureOr?> + > + with + $FutureModifier?>, + $FutureProvider?> { + SdkClientsProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'sdkClientsProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$sdkClientsHash(); + + @$internal + @override + $FutureProviderElement?> $createElement( + $ProviderPointer pointer, + ) => $FutureProviderElement(pointer); + + @override + FutureOr?> create(Ref ref) { + return sdkClients(ref); + } +} + +String _$sdkClientsHash() => r'9b966083effea11035d6edde379e71cc2a0f85c0'; diff --git a/useragent/lib/providers/sdk_clients/wallet_access.dart b/useragent/lib/providers/sdk_clients/wallet_access.dart index faf4f95..1c4643e 100644 --- a/useragent/lib/providers/sdk_clients/wallet_access.dart +++ b/useragent/lib/providers/sdk_clients/wallet_access.dart @@ -1,174 +1,174 @@ -import 'package:arbiter/features/connection/evm/wallet_access.dart'; -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:arbiter/providers/evm/evm.dart'; -import 'package:flutter/foundation.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'wallet_access.g.dart'; - -class ClientWalletOption { - const ClientWalletOption({required this.walletId, required this.address}); - - final int walletId; - final String address; -} - -class ClientWalletAccessState { - const ClientWalletAccessState({ - this.searchQuery = '', - this.originalWalletIds = const {}, - this.selectedWalletIds = const {}, - }); - - final String searchQuery; - final Set originalWalletIds; - final Set selectedWalletIds; - - bool get hasChanges => !setEquals(originalWalletIds, selectedWalletIds); - - ClientWalletAccessState copyWith({ - String? searchQuery, - Set? originalWalletIds, - Set? selectedWalletIds, - }) { - return ClientWalletAccessState( - searchQuery: searchQuery ?? this.searchQuery, - originalWalletIds: originalWalletIds ?? this.originalWalletIds, - selectedWalletIds: selectedWalletIds ?? this.selectedWalletIds, - ); - } -} - -final saveClientWalletAccessMutation = Mutation(); - -abstract class ClientWalletAccessRepository { - Future> fetchSelectedWalletIds(int clientId); - Future saveSelectedWalletIds(int clientId, Set walletIds); -} - -class ServerClientWalletAccessRepository - implements ClientWalletAccessRepository { - ServerClientWalletAccessRepository(this.ref); - - final Ref ref; - - @override - Future> fetchSelectedWalletIds(int clientId) async { - final connection = await ref.read(connectionManagerProvider.future); - if (connection == null) { - throw Exception('Not connected to the server.'); - } - return readClientWalletAccess(connection, clientId: clientId); - } - - @override - Future saveSelectedWalletIds(int clientId, Set walletIds) async { - final connection = await ref.read(connectionManagerProvider.future); - if (connection == null) { - throw Exception('Not connected to the server.'); - } - await writeClientWalletAccess( - connection, - clientId: clientId, - walletIds: walletIds, - ); - } -} - -@riverpod -ClientWalletAccessRepository clientWalletAccessRepository(Ref ref) { - return ServerClientWalletAccessRepository(ref); -} - -@riverpod -Future> clientWalletOptions(Ref ref) async { - final wallets = await ref.watch(evmProvider.future) ?? const []; - return [ - for (var index = 0; index < wallets.length; index++) - ClientWalletOption( - walletId: index + 1, - address: formatWalletAddress(wallets[index].address), - ), - ]; -} - -@riverpod -Future> clientWalletAccessSelection(Ref ref, int clientId) async { - final repository = ref.watch(clientWalletAccessRepositoryProvider); - return repository.fetchSelectedWalletIds(clientId); -} - -@riverpod -class ClientWalletAccessController extends _$ClientWalletAccessController { - @override - ClientWalletAccessState build(int clientId) { - final selection = ref.read(clientWalletAccessSelectionProvider(clientId)); - - void sync(AsyncValue> value) { - value.when(data: hydrate, error: (_, _) {}, loading: () {}); - } - - ref.listen>>( - clientWalletAccessSelectionProvider(clientId), - (_, next) => sync(next), - ); - return selection.when( - data: (walletIds) => ClientWalletAccessState( - originalWalletIds: Set.of(walletIds), - selectedWalletIds: Set.of(walletIds), - ), - error: (error, _) => const ClientWalletAccessState(), - loading: () => const ClientWalletAccessState(), - ); - } - - void hydrate(Set selectedWalletIds) { - state = state.copyWith( - originalWalletIds: Set.of(selectedWalletIds), - selectedWalletIds: Set.of(selectedWalletIds), - ); - } - - void setSearchQuery(String value) { - state = state.copyWith(searchQuery: value); - } - - void toggleWallet(int walletId) { - final next = Set.of(state.selectedWalletIds); - if (!next.add(walletId)) { - next.remove(walletId); - } - state = state.copyWith(selectedWalletIds: next); - } - - void discardChanges() { - state = state.copyWith(selectedWalletIds: Set.of(state.originalWalletIds)); - } -} - -Future executeSaveClientWalletAccess( - MutationTarget ref, { - required int clientId, -}) { - final mutation = saveClientWalletAccessMutation(clientId); - return mutation.run(ref, (tsx) async { - final repository = tsx.get(clientWalletAccessRepositoryProvider); - final controller = tsx.get( - clientWalletAccessControllerProvider(clientId).notifier, - ); - final selectedWalletIds = tsx - .get(clientWalletAccessControllerProvider(clientId)) - .selectedWalletIds; - await repository.saveSelectedWalletIds(clientId, selectedWalletIds); - controller.hydrate(selectedWalletIds); - }); -} - -String formatWalletAddress(List bytes) { - final hex = bytes - .map((byte) => byte.toRadixString(16).padLeft(2, '0')) - .join(); - return '0x$hex'; -} +import 'package:arbiter/features/connection/evm/wallet_access.dart'; +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:arbiter/providers/evm/evm.dart'; +import 'package:flutter/foundation.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'wallet_access.g.dart'; + +class ClientWalletOption { + const ClientWalletOption({required this.walletId, required this.address}); + + final int walletId; + final String address; +} + +class ClientWalletAccessState { + const ClientWalletAccessState({ + this.searchQuery = '', + this.originalWalletIds = const {}, + this.selectedWalletIds = const {}, + }); + + final String searchQuery; + final Set originalWalletIds; + final Set selectedWalletIds; + + bool get hasChanges => !setEquals(originalWalletIds, selectedWalletIds); + + ClientWalletAccessState copyWith({ + String? searchQuery, + Set? originalWalletIds, + Set? selectedWalletIds, + }) { + return ClientWalletAccessState( + searchQuery: searchQuery ?? this.searchQuery, + originalWalletIds: originalWalletIds ?? this.originalWalletIds, + selectedWalletIds: selectedWalletIds ?? this.selectedWalletIds, + ); + } +} + +final saveClientWalletAccessMutation = Mutation(); + +abstract class ClientWalletAccessRepository { + Future> fetchSelectedWalletIds(int clientId); + Future saveSelectedWalletIds(int clientId, Set walletIds); +} + +class ServerClientWalletAccessRepository + implements ClientWalletAccessRepository { + ServerClientWalletAccessRepository(this.ref); + + final Ref ref; + + @override + Future> fetchSelectedWalletIds(int clientId) async { + final connection = await ref.read(connectionManagerProvider.future); + if (connection == null) { + throw Exception('Not connected to the server.'); + } + return readClientWalletAccess(connection, clientId: clientId); + } + + @override + Future saveSelectedWalletIds(int clientId, Set walletIds) async { + final connection = await ref.read(connectionManagerProvider.future); + if (connection == null) { + throw Exception('Not connected to the server.'); + } + await writeClientWalletAccess( + connection, + clientId: clientId, + walletIds: walletIds, + ); + } +} + +@riverpod +ClientWalletAccessRepository clientWalletAccessRepository(Ref ref) { + return ServerClientWalletAccessRepository(ref); +} + +@riverpod +Future> clientWalletOptions(Ref ref) async { + final wallets = await ref.watch(evmProvider.future) ?? const []; + return [ + for (var index = 0; index < wallets.length; index++) + ClientWalletOption( + walletId: index + 1, + address: formatWalletAddress(wallets[index].address), + ), + ]; +} + +@riverpod +Future> clientWalletAccessSelection(Ref ref, int clientId) async { + final repository = ref.watch(clientWalletAccessRepositoryProvider); + return repository.fetchSelectedWalletIds(clientId); +} + +@riverpod +class ClientWalletAccessController extends _$ClientWalletAccessController { + @override + ClientWalletAccessState build(int clientId) { + final selection = ref.read(clientWalletAccessSelectionProvider(clientId)); + + void sync(AsyncValue> value) { + value.when(data: hydrate, error: (_, _) {}, loading: () {}); + } + + ref.listen>>( + clientWalletAccessSelectionProvider(clientId), + (_, next) => sync(next), + ); + return selection.when( + data: (walletIds) => ClientWalletAccessState( + originalWalletIds: Set.of(walletIds), + selectedWalletIds: Set.of(walletIds), + ), + error: (error, _) => const ClientWalletAccessState(), + loading: () => const ClientWalletAccessState(), + ); + } + + void hydrate(Set selectedWalletIds) { + state = state.copyWith( + originalWalletIds: Set.of(selectedWalletIds), + selectedWalletIds: Set.of(selectedWalletIds), + ); + } + + void setSearchQuery(String value) { + state = state.copyWith(searchQuery: value); + } + + void toggleWallet(int walletId) { + final next = Set.of(state.selectedWalletIds); + if (!next.add(walletId)) { + next.remove(walletId); + } + state = state.copyWith(selectedWalletIds: next); + } + + void discardChanges() { + state = state.copyWith(selectedWalletIds: Set.of(state.originalWalletIds)); + } +} + +Future executeSaveClientWalletAccess( + MutationTarget ref, { + required int clientId, +}) { + final mutation = saveClientWalletAccessMutation(clientId); + return mutation.run(ref, (tsx) async { + final repository = tsx.get(clientWalletAccessRepositoryProvider); + final controller = tsx.get( + clientWalletAccessControllerProvider(clientId).notifier, + ); + final selectedWalletIds = tsx + .get(clientWalletAccessControllerProvider(clientId)) + .selectedWalletIds; + await repository.saveSelectedWalletIds(clientId, selectedWalletIds); + controller.hydrate(selectedWalletIds); + }); +} + +String formatWalletAddress(List bytes) { + final hex = bytes + .map((byte) => byte.toRadixString(16).padLeft(2, '0')) + .join(); + return '0x$hex'; +} diff --git a/useragent/lib/providers/sdk_clients/wallet_access.g.dart b/useragent/lib/providers/sdk_clients/wallet_access.g.dart index 413ff16..4468242 100644 --- a/useragent/lib/providers/sdk_clients/wallet_access.g.dart +++ b/useragent/lib/providers/sdk_clients/wallet_access.g.dart @@ -1,280 +1,280 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'wallet_access.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(clientWalletAccessRepository) -final clientWalletAccessRepositoryProvider = - ClientWalletAccessRepositoryProvider._(); - -final class ClientWalletAccessRepositoryProvider - extends - $FunctionalProvider< - ClientWalletAccessRepository, - ClientWalletAccessRepository, - ClientWalletAccessRepository - > - with $Provider { - ClientWalletAccessRepositoryProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'clientWalletAccessRepositoryProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$clientWalletAccessRepositoryHash(); - - @$internal - @override - $ProviderElement $createElement( - $ProviderPointer pointer, - ) => $ProviderElement(pointer); - - @override - ClientWalletAccessRepository create(Ref ref) { - return clientWalletAccessRepository(ref); - } - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(ClientWalletAccessRepository value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider(value), - ); - } -} - -String _$clientWalletAccessRepositoryHash() => - r'bbc332284bc36a8b5d807bd5c45362b6b12b19e7'; - -@ProviderFor(clientWalletOptions) -final clientWalletOptionsProvider = ClientWalletOptionsProvider._(); - -final class ClientWalletOptionsProvider - extends - $FunctionalProvider< - AsyncValue>, - List, - FutureOr> - > - with - $FutureModifier>, - $FutureProvider> { - ClientWalletOptionsProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'clientWalletOptionsProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$clientWalletOptionsHash(); - - @$internal - @override - $FutureProviderElement> $createElement( - $ProviderPointer pointer, - ) => $FutureProviderElement(pointer); - - @override - FutureOr> create(Ref ref) { - return clientWalletOptions(ref); - } -} - -String _$clientWalletOptionsHash() => - r'32183c2b281e2a41400de07f2381132a706815ab'; - -@ProviderFor(clientWalletAccessSelection) -final clientWalletAccessSelectionProvider = - ClientWalletAccessSelectionFamily._(); - -final class ClientWalletAccessSelectionProvider - extends - $FunctionalProvider>, Set, FutureOr>> - with $FutureModifier>, $FutureProvider> { - ClientWalletAccessSelectionProvider._({ - required ClientWalletAccessSelectionFamily super.from, - required int super.argument, - }) : super( - retry: null, - name: r'clientWalletAccessSelectionProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$clientWalletAccessSelectionHash(); - - @override - String toString() { - return r'clientWalletAccessSelectionProvider' - '' - '($argument)'; - } - - @$internal - @override - $FutureProviderElement> $createElement($ProviderPointer pointer) => - $FutureProviderElement(pointer); - - @override - FutureOr> create(Ref ref) { - final argument = this.argument as int; - return clientWalletAccessSelection(ref, argument); - } - - @override - bool operator ==(Object other) { - return other is ClientWalletAccessSelectionProvider && - other.argument == argument; - } - - @override - int get hashCode { - return argument.hashCode; - } -} - -String _$clientWalletAccessSelectionHash() => - r'f33705ee7201cd9b899cc058d6642de85a22b03e'; - -final class ClientWalletAccessSelectionFamily extends $Family - with $FunctionalFamilyOverride>, int> { - ClientWalletAccessSelectionFamily._() - : super( - retry: null, - name: r'clientWalletAccessSelectionProvider', - dependencies: null, - $allTransitiveDependencies: null, - isAutoDispose: true, - ); - - ClientWalletAccessSelectionProvider call(int clientId) => - ClientWalletAccessSelectionProvider._(argument: clientId, from: this); - - @override - String toString() => r'clientWalletAccessSelectionProvider'; -} - -@ProviderFor(ClientWalletAccessController) -final clientWalletAccessControllerProvider = - ClientWalletAccessControllerFamily._(); - -final class ClientWalletAccessControllerProvider - extends - $NotifierProvider< - ClientWalletAccessController, - ClientWalletAccessState - > { - ClientWalletAccessControllerProvider._({ - required ClientWalletAccessControllerFamily super.from, - required int super.argument, - }) : super( - retry: null, - name: r'clientWalletAccessControllerProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$clientWalletAccessControllerHash(); - - @override - String toString() { - return r'clientWalletAccessControllerProvider' - '' - '($argument)'; - } - - @$internal - @override - ClientWalletAccessController create() => ClientWalletAccessController(); - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(ClientWalletAccessState value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider(value), - ); - } - - @override - bool operator ==(Object other) { - return other is ClientWalletAccessControllerProvider && - other.argument == argument; - } - - @override - int get hashCode { - return argument.hashCode; - } -} - -String _$clientWalletAccessControllerHash() => - r'45bff81382fec3e8610190167b55667a7dfc1111'; - -final class ClientWalletAccessControllerFamily extends $Family - with - $ClassFamilyOverride< - ClientWalletAccessController, - ClientWalletAccessState, - ClientWalletAccessState, - ClientWalletAccessState, - int - > { - ClientWalletAccessControllerFamily._() - : super( - retry: null, - name: r'clientWalletAccessControllerProvider', - dependencies: null, - $allTransitiveDependencies: null, - isAutoDispose: true, - ); - - ClientWalletAccessControllerProvider call(int clientId) => - ClientWalletAccessControllerProvider._(argument: clientId, from: this); - - @override - String toString() => r'clientWalletAccessControllerProvider'; -} - -abstract class _$ClientWalletAccessController - extends $Notifier { - late final _$args = ref.$arg as int; - int get clientId => _$args; - - ClientWalletAccessState build(int clientId); - @$mustCallSuper - @override - void runBuild() { - final ref = - this.ref as $Ref; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, - ClientWalletAccessState, - Object?, - Object? - >; - element.handleCreate(ref, () => build(_$args)); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'wallet_access.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(clientWalletAccessRepository) +final clientWalletAccessRepositoryProvider = + ClientWalletAccessRepositoryProvider._(); + +final class ClientWalletAccessRepositoryProvider + extends + $FunctionalProvider< + ClientWalletAccessRepository, + ClientWalletAccessRepository, + ClientWalletAccessRepository + > + with $Provider { + ClientWalletAccessRepositoryProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'clientWalletAccessRepositoryProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$clientWalletAccessRepositoryHash(); + + @$internal + @override + $ProviderElement $createElement( + $ProviderPointer pointer, + ) => $ProviderElement(pointer); + + @override + ClientWalletAccessRepository create(Ref ref) { + return clientWalletAccessRepository(ref); + } + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(ClientWalletAccessRepository value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } +} + +String _$clientWalletAccessRepositoryHash() => + r'bbc332284bc36a8b5d807bd5c45362b6b12b19e7'; + +@ProviderFor(clientWalletOptions) +final clientWalletOptionsProvider = ClientWalletOptionsProvider._(); + +final class ClientWalletOptionsProvider + extends + $FunctionalProvider< + AsyncValue>, + List, + FutureOr> + > + with + $FutureModifier>, + $FutureProvider> { + ClientWalletOptionsProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'clientWalletOptionsProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$clientWalletOptionsHash(); + + @$internal + @override + $FutureProviderElement> $createElement( + $ProviderPointer pointer, + ) => $FutureProviderElement(pointer); + + @override + FutureOr> create(Ref ref) { + return clientWalletOptions(ref); + } +} + +String _$clientWalletOptionsHash() => + r'32183c2b281e2a41400de07f2381132a706815ab'; + +@ProviderFor(clientWalletAccessSelection) +final clientWalletAccessSelectionProvider = + ClientWalletAccessSelectionFamily._(); + +final class ClientWalletAccessSelectionProvider + extends + $FunctionalProvider>, Set, FutureOr>> + with $FutureModifier>, $FutureProvider> { + ClientWalletAccessSelectionProvider._({ + required ClientWalletAccessSelectionFamily super.from, + required int super.argument, + }) : super( + retry: null, + name: r'clientWalletAccessSelectionProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$clientWalletAccessSelectionHash(); + + @override + String toString() { + return r'clientWalletAccessSelectionProvider' + '' + '($argument)'; + } + + @$internal + @override + $FutureProviderElement> $createElement($ProviderPointer pointer) => + $FutureProviderElement(pointer); + + @override + FutureOr> create(Ref ref) { + final argument = this.argument as int; + return clientWalletAccessSelection(ref, argument); + } + + @override + bool operator ==(Object other) { + return other is ClientWalletAccessSelectionProvider && + other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$clientWalletAccessSelectionHash() => + r'f33705ee7201cd9b899cc058d6642de85a22b03e'; + +final class ClientWalletAccessSelectionFamily extends $Family + with $FunctionalFamilyOverride>, int> { + ClientWalletAccessSelectionFamily._() + : super( + retry: null, + name: r'clientWalletAccessSelectionProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + ClientWalletAccessSelectionProvider call(int clientId) => + ClientWalletAccessSelectionProvider._(argument: clientId, from: this); + + @override + String toString() => r'clientWalletAccessSelectionProvider'; +} + +@ProviderFor(ClientWalletAccessController) +final clientWalletAccessControllerProvider = + ClientWalletAccessControllerFamily._(); + +final class ClientWalletAccessControllerProvider + extends + $NotifierProvider< + ClientWalletAccessController, + ClientWalletAccessState + > { + ClientWalletAccessControllerProvider._({ + required ClientWalletAccessControllerFamily super.from, + required int super.argument, + }) : super( + retry: null, + name: r'clientWalletAccessControllerProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$clientWalletAccessControllerHash(); + + @override + String toString() { + return r'clientWalletAccessControllerProvider' + '' + '($argument)'; + } + + @$internal + @override + ClientWalletAccessController create() => ClientWalletAccessController(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(ClientWalletAccessState value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } + + @override + bool operator ==(Object other) { + return other is ClientWalletAccessControllerProvider && + other.argument == argument; + } + + @override + int get hashCode { + return argument.hashCode; + } +} + +String _$clientWalletAccessControllerHash() => + r'45bff81382fec3e8610190167b55667a7dfc1111'; + +final class ClientWalletAccessControllerFamily extends $Family + with + $ClassFamilyOverride< + ClientWalletAccessController, + ClientWalletAccessState, + ClientWalletAccessState, + ClientWalletAccessState, + int + > { + ClientWalletAccessControllerFamily._() + : super( + retry: null, + name: r'clientWalletAccessControllerProvider', + dependencies: null, + $allTransitiveDependencies: null, + isAutoDispose: true, + ); + + ClientWalletAccessControllerProvider call(int clientId) => + ClientWalletAccessControllerProvider._(argument: clientId, from: this); + + @override + String toString() => r'clientWalletAccessControllerProvider'; +} + +abstract class _$ClientWalletAccessController + extends $Notifier { + late final _$args = ref.$arg as int; + int get clientId => _$args; + + ClientWalletAccessState build(int clientId); + @$mustCallSuper + @override + void runBuild() { + final ref = + this.ref as $Ref; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, + ClientWalletAccessState, + Object?, + Object? + >; + element.handleCreate(ref, () => build(_$args)); + } +} diff --git a/useragent/lib/providers/sdk_clients/wallet_access_list.dart b/useragent/lib/providers/sdk_clients/wallet_access_list.dart index cb33ef4..05ce13f 100644 --- a/useragent/lib/providers/sdk_clients/wallet_access_list.dart +++ b/useragent/lib/providers/sdk_clients/wallet_access_list.dart @@ -1,22 +1,22 @@ -import 'package:arbiter/features/connection/evm/wallet_access.dart'; -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:mtcore/markettakers.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'wallet_access_list.g.dart'; - -@riverpod -Future?> walletAccessList(Ref ref) async { - final connection = await ref.watch(connectionManagerProvider.future); - if (connection == null) { - return null; - } - - try { - return await listAllWalletAccesses(connection); - } catch (e, st) { - talker.handle(e, st); - rethrow; - } -} +import 'package:arbiter/features/connection/evm/wallet_access.dart'; +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:mtcore/markettakers.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'wallet_access_list.g.dart'; + +@riverpod +Future?> walletAccessList(Ref ref) async { + final connection = await ref.watch(connectionManagerProvider.future); + if (connection == null) { + return null; + } + + try { + return await listAllWalletAccesses(connection); + } catch (e, st) { + talker.handle(e, st); + rethrow; + } +} diff --git a/useragent/lib/providers/sdk_clients/wallet_access_list.g.dart b/useragent/lib/providers/sdk_clients/wallet_access_list.g.dart index 0034b47..5c3abb8 100644 --- a/useragent/lib/providers/sdk_clients/wallet_access_list.g.dart +++ b/useragent/lib/providers/sdk_clients/wallet_access_list.g.dart @@ -1,51 +1,51 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'wallet_access_list.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(walletAccessList) -final walletAccessListProvider = WalletAccessListProvider._(); - -final class WalletAccessListProvider - extends - $FunctionalProvider< - AsyncValue?>, - List?, - FutureOr?> - > - with - $FutureModifier?>, - $FutureProvider?> { - WalletAccessListProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'walletAccessListProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$walletAccessListHash(); - - @$internal - @override - $FutureProviderElement?> $createElement( - $ProviderPointer pointer, - ) => $FutureProviderElement(pointer); - - @override - FutureOr?> create(Ref ref) { - return walletAccessList(ref); - } -} - -String _$walletAccessListHash() => r'143387471489ebc36de76b2a8ddcb6d857cbad17'; +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'wallet_access_list.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(walletAccessList) +final walletAccessListProvider = WalletAccessListProvider._(); + +final class WalletAccessListProvider + extends + $FunctionalProvider< + AsyncValue?>, + List?, + FutureOr?> + > + with + $FutureModifier?>, + $FutureProvider?> { + WalletAccessListProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'walletAccessListProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$walletAccessListHash(); + + @$internal + @override + $FutureProviderElement?> $createElement( + $ProviderPointer pointer, + ) => $FutureProviderElement(pointer); + + @override + FutureOr?> create(Ref ref) { + return walletAccessList(ref); + } +} + +String _$walletAccessListHash() => r'143387471489ebc36de76b2a8ddcb6d857cbad17'; diff --git a/useragent/lib/providers/server_info.dart b/useragent/lib/providers/server_info.dart index 54344c8..ad146eb 100644 --- a/useragent/lib/providers/server_info.dart +++ b/useragent/lib/providers/server_info.dart @@ -1,53 +1,53 @@ -import 'package:arbiter/features/connection/server_info_storage.dart'; -import 'package:cryptography/cryptography.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'server_info.g.dart'; - -@riverpod -ServerInfoStorage serverInfoStorage(Ref ref) { - return const SecureServerInfoStorage(); -} - -@Riverpod(keepAlive: true) -class ServerInfo extends _$ServerInfo { - @override - Future build() { - final storage = ref.watch(serverInfoStorageProvider); - return storage.load(); - } - - Future save({ - required String address, - required int port, - required List caCert, - }) async { - final storage = ref.read(serverInfoStorageProvider); - final fingerprint = await _fingerprint(caCert); - final serverInfo = StoredServerInfo( - address: address, - port: port, - caCertFingerprint: fingerprint, - ); - - state = await AsyncValue.guard(() async { - await storage.save(serverInfo); - return serverInfo; - }); - } - - Future clear() async { - final storage = ref.read(serverInfoStorageProvider); - state = await AsyncValue.guard(() async { - await storage.clear(); - return null; - }); - } - - Future _fingerprint(List caCert) async { - final digest = await Sha256().hash(caCert); - return digest.bytes - .map((byte) => byte.toRadixString(16).padLeft(2, '0')) - .join(); - } -} +import 'package:arbiter/features/connection/server_info_storage.dart'; +import 'package:cryptography/cryptography.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'server_info.g.dart'; + +@riverpod +ServerInfoStorage serverInfoStorage(Ref ref) { + return const SecureServerInfoStorage(); +} + +@Riverpod(keepAlive: true) +class ServerInfo extends _$ServerInfo { + @override + Future build() { + final storage = ref.watch(serverInfoStorageProvider); + return storage.load(); + } + + Future save({ + required String address, + required int port, + required List caCert, + }) async { + final storage = ref.read(serverInfoStorageProvider); + final fingerprint = await _fingerprint(caCert); + final serverInfo = StoredServerInfo( + address: address, + port: port, + caCertFingerprint: fingerprint, + ); + + state = await AsyncValue.guard(() async { + await storage.save(serverInfo); + return serverInfo; + }); + } + + Future clear() async { + final storage = ref.read(serverInfoStorageProvider); + state = await AsyncValue.guard(() async { + await storage.clear(); + return null; + }); + } + + Future _fingerprint(List caCert) async { + final digest = await Sha256().hash(caCert); + return digest.bytes + .map((byte) => byte.toRadixString(16).padLeft(2, '0')) + .join(); + } +} diff --git a/useragent/lib/providers/server_info.g.dart b/useragent/lib/providers/server_info.g.dart index ec0afbc..e33c991 100644 --- a/useragent/lib/providers/server_info.g.dart +++ b/useragent/lib/providers/server_info.g.dart @@ -1,102 +1,102 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'server_info.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(serverInfoStorage) -final serverInfoStorageProvider = ServerInfoStorageProvider._(); - -final class ServerInfoStorageProvider - extends - $FunctionalProvider< - ServerInfoStorage, - ServerInfoStorage, - ServerInfoStorage - > - with $Provider { - ServerInfoStorageProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'serverInfoStorageProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$serverInfoStorageHash(); - - @$internal - @override - $ProviderElement $createElement( - $ProviderPointer pointer, - ) => $ProviderElement(pointer); - - @override - ServerInfoStorage create(Ref ref) { - return serverInfoStorage(ref); - } - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(ServerInfoStorage value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider(value), - ); - } -} - -String _$serverInfoStorageHash() => r'fc06865e7314b1a2493c5de1a9347923a3d21c5c'; - -@ProviderFor(ServerInfo) -final serverInfoProvider = ServerInfoProvider._(); - -final class ServerInfoProvider - extends $AsyncNotifierProvider { - ServerInfoProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'serverInfoProvider', - isAutoDispose: false, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$serverInfoHash(); - - @$internal - @override - ServerInfo create() => ServerInfo(); -} - -String _$serverInfoHash() => r'6e94f52de03259695a2166b766004eec60ff45fa'; - -abstract class _$ServerInfo extends $AsyncNotifier { - FutureOr build(); - @$mustCallSuper - @override - void runBuild() { - final ref = - this.ref as $Ref, StoredServerInfo?>; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, StoredServerInfo?>, - AsyncValue, - Object?, - Object? - >; - element.handleCreate(ref, build); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'server_info.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(serverInfoStorage) +final serverInfoStorageProvider = ServerInfoStorageProvider._(); + +final class ServerInfoStorageProvider + extends + $FunctionalProvider< + ServerInfoStorage, + ServerInfoStorage, + ServerInfoStorage + > + with $Provider { + ServerInfoStorageProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'serverInfoStorageProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$serverInfoStorageHash(); + + @$internal + @override + $ProviderElement $createElement( + $ProviderPointer pointer, + ) => $ProviderElement(pointer); + + @override + ServerInfoStorage create(Ref ref) { + return serverInfoStorage(ref); + } + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(ServerInfoStorage value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } +} + +String _$serverInfoStorageHash() => r'fc06865e7314b1a2493c5de1a9347923a3d21c5c'; + +@ProviderFor(ServerInfo) +final serverInfoProvider = ServerInfoProvider._(); + +final class ServerInfoProvider + extends $AsyncNotifierProvider { + ServerInfoProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'serverInfoProvider', + isAutoDispose: false, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$serverInfoHash(); + + @$internal + @override + ServerInfo create() => ServerInfo(); +} + +String _$serverInfoHash() => r'6e94f52de03259695a2166b766004eec60ff45fa'; + +abstract class _$ServerInfo extends $AsyncNotifier { + FutureOr build(); + @$mustCallSuper + @override + void runBuild() { + final ref = + this.ref as $Ref, StoredServerInfo?>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, StoredServerInfo?>, + AsyncValue, + Object?, + Object? + >; + element.handleCreate(ref, build); + } +} diff --git a/useragent/lib/providers/vault_state.dart b/useragent/lib/providers/vault_state.dart index 874da0f..40fd34e 100644 --- a/useragent/lib/providers/vault_state.dart +++ b/useragent/lib/providers/vault_state.dart @@ -1,37 +1,37 @@ -import 'package:arbiter/proto/shared/vault.pbenum.dart'; -import 'package:arbiter/proto/user_agent/vault/vault.pb.dart' as ua_vault; -import 'package:arbiter/proto/user_agent.pb.dart'; -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:mtcore/markettakers.dart'; -import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'vault_state.g.dart'; - -@riverpod -Future vaultState(Ref ref) async { - final conn = await ref.watch(connectionManagerProvider.future); - if (conn == null) { - return null; - } - - final resp = await conn.ask( - UserAgentRequest(vault: ua_vault.Request(queryState: Empty())), - ); - if (!resp.hasVault()) { - talker.warning('Expected vault state response, got ${resp.whichPayload()}'); - return null; - } - - final vaultResponse = resp.vault; - if (!vaultResponse.hasState()) { - talker.warning( - 'Expected vault state payload, got ${vaultResponse.whichPayload()}', - ); - return null; - } - - final vaultState = vaultResponse.state; - - return vaultState; -} +import 'package:arbiter/proto/shared/vault.pbenum.dart'; +import 'package:arbiter/proto/user_agent/vault/vault.pb.dart' as ua_vault; +import 'package:arbiter/proto/user_agent.pb.dart'; +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:mtcore/markettakers.dart'; +import 'package:protobuf/well_known_types/google/protobuf/empty.pb.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'vault_state.g.dart'; + +@riverpod +Future vaultState(Ref ref) async { + final conn = await ref.watch(connectionManagerProvider.future); + if (conn == null) { + return null; + } + + final resp = await conn.ask( + UserAgentRequest(vault: ua_vault.Request(queryState: Empty())), + ); + if (!resp.hasVault()) { + talker.warning('Expected vault state response, got ${resp.whichPayload()}'); + return null; + } + + final vaultResponse = resp.vault; + if (!vaultResponse.hasState()) { + talker.warning( + 'Expected vault state payload, got ${vaultResponse.whichPayload()}', + ); + return null; + } + + final vaultState = vaultResponse.state; + + return vaultState; +} diff --git a/useragent/lib/providers/vault_state.g.dart b/useragent/lib/providers/vault_state.g.dart index 779ecbb..b61ea19 100644 --- a/useragent/lib/providers/vault_state.g.dart +++ b/useragent/lib/providers/vault_state.g.dart @@ -1,49 +1,49 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'vault_state.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(vaultState) -final vaultStateProvider = VaultStateProvider._(); - -final class VaultStateProvider - extends - $FunctionalProvider< - AsyncValue, - VaultState?, - FutureOr - > - with $FutureModifier, $FutureProvider { - VaultStateProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'vaultStateProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$vaultStateHash(); - - @$internal - @override - $FutureProviderElement $createElement( - $ProviderPointer pointer, - ) => $FutureProviderElement(pointer); - - @override - FutureOr create(Ref ref) { - return vaultState(ref); - } -} - -String _$vaultStateHash() => r'f7247826d92ed583c475dd7f956b1ffea1f9a7da'; +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'vault_state.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(vaultState) +final vaultStateProvider = VaultStateProvider._(); + +final class VaultStateProvider + extends + $FunctionalProvider< + AsyncValue, + VaultState?, + FutureOr + > + with $FutureModifier, $FutureProvider { + VaultStateProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'vaultStateProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$vaultStateHash(); + + @$internal + @override + $FutureProviderElement $createElement( + $ProviderPointer pointer, + ) => $FutureProviderElement(pointer); + + @override + FutureOr create(Ref ref) { + return vaultState(ref); + } +} + +String _$vaultStateHash() => r'f7247826d92ed583c475dd7f956b1ffea1f9a7da'; diff --git a/useragent/lib/router.dart b/useragent/lib/router.dart index ab06b07..05b7b2d 100644 --- a/useragent/lib/router.dart +++ b/useragent/lib/router.dart @@ -1,27 +1,27 @@ -import 'package:auto_route/auto_route.dart'; - -import 'router.gr.dart'; - -@AutoRouterConfig(generateForDir: ['lib/screens']) -class Router extends RootStackRouter { - @override - List get routes => [ - AutoRoute(page: Bootstrap.page, path: '/bootstrap', initial: true), - AutoRoute(page: ServerInfoSetupRoute.page, path: '/server-info'), - AutoRoute(page: ServerConnectionRoute.page, path: '/server-connection'), - AutoRoute(page: VaultSetupRoute.page, path: '/vault'), - AutoRoute(page: ClientDetailsRoute.page, path: '/clients/:clientId'), - AutoRoute(page: CreateEvmGrantRoute.page, path: '/evm-grants/create'), - - AutoRoute( - page: DashboardRouter.page, - path: '/dashboard', - children: [ - AutoRoute(page: EvmRoute.page, path: 'evm'), - AutoRoute(page: ClientsRoute.page, path: 'clients'), - AutoRoute(page: EvmGrantsRoute.page, path: 'grants'), - AutoRoute(page: AboutRoute.page, path: 'about'), - ], - ), - ]; -} +import 'package:auto_route/auto_route.dart'; + +import 'router.gr.dart'; + +@AutoRouterConfig(generateForDir: ['lib/screens']) +class Router extends RootStackRouter { + @override + List get routes => [ + AutoRoute(page: Bootstrap.page, path: '/bootstrap', initial: true), + AutoRoute(page: ServerInfoSetupRoute.page, path: '/server-info'), + AutoRoute(page: ServerConnectionRoute.page, path: '/server-connection'), + AutoRoute(page: VaultSetupRoute.page, path: '/vault'), + AutoRoute(page: ClientDetailsRoute.page, path: '/clients/:clientId'), + AutoRoute(page: CreateEvmGrantRoute.page, path: '/evm-grants/create'), + + AutoRoute( + page: DashboardRouter.page, + path: '/dashboard', + children: [ + AutoRoute(page: EvmRoute.page, path: 'evm'), + AutoRoute(page: ClientsRoute.page, path: 'clients'), + AutoRoute(page: EvmGrantsRoute.page, path: 'grants'), + AutoRoute(page: AboutRoute.page, path: 'about'), + ], + ), + ]; +} diff --git a/useragent/lib/router.gr.dart b/useragent/lib/router.gr.dart index bc417b9..39b2625 100644 --- a/useragent/lib/router.gr.dart +++ b/useragent/lib/router.gr.dart @@ -1,323 +1,323 @@ -// dart format width=80 -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ************************************************************************** -// AutoRouterGenerator -// ************************************************************************** - -// ignore_for_file: type=lint -// coverage:ignore-file - -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as _i15; -import 'package:arbiter/screens/bootstrap.dart' as _i2; -import 'package:arbiter/screens/dashboard.dart' as _i7; -import 'package:arbiter/screens/dashboard/about.dart' as _i1; -import 'package:arbiter/screens/dashboard/clients/details.dart' as _i3; -import 'package:arbiter/screens/dashboard/clients/details/client_details.dart' - as _i4; -import 'package:arbiter/screens/dashboard/clients/table.dart' as _i5; -import 'package:arbiter/screens/dashboard/evm/evm.dart' as _i9; -import 'package:arbiter/screens/dashboard/evm/grants/create/screen.dart' as _i6; -import 'package:arbiter/screens/dashboard/evm/grants/grants.dart' as _i8; -import 'package:arbiter/screens/server_connection.dart' as _i10; -import 'package:arbiter/screens/server_info_setup.dart' as _i11; -import 'package:arbiter/screens/vault_setup.dart' as _i12; -import 'package:auto_route/auto_route.dart' as _i13; -import 'package:flutter/material.dart' as _i14; - -/// generated route for -/// [_i1.AboutScreen] -class AboutRoute extends _i13.PageRouteInfo { - const AboutRoute({List<_i13.PageRouteInfo>? children}) - : super(AboutRoute.name, initialChildren: children); - - static const String name = 'AboutRoute'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - return const _i1.AboutScreen(); - }, - ); -} - -/// generated route for -/// [_i2.Bootstrap] -class Bootstrap extends _i13.PageRouteInfo { - const Bootstrap({List<_i13.PageRouteInfo>? children}) - : super(Bootstrap.name, initialChildren: children); - - static const String name = 'Bootstrap'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - return const _i2.Bootstrap(); - }, - ); -} - -/// generated route for -/// [_i3.ClientDetails] -class ClientDetails extends _i13.PageRouteInfo { - ClientDetails({ - _i14.Key? key, - required _i15.Entry client, - List<_i13.PageRouteInfo>? children, - }) : super( - ClientDetails.name, - args: ClientDetailsArgs(key: key, client: client), - initialChildren: children, - ); - - static const String name = 'ClientDetails'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - final args = data.argsAs(); - return _i3.ClientDetails(key: args.key, client: args.client); - }, - ); -} - -class ClientDetailsArgs { - const ClientDetailsArgs({this.key, required this.client}); - - final _i14.Key? key; - - final _i15.Entry client; - - @override - String toString() { - return 'ClientDetailsArgs{key: $key, client: $client}'; - } - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other is! ClientDetailsArgs) return false; - return key == other.key && client == other.client; - } - - @override - int get hashCode => key.hashCode ^ client.hashCode; -} - -/// generated route for -/// [_i4.ClientDetailsScreen] -class ClientDetailsRoute extends _i13.PageRouteInfo { - ClientDetailsRoute({ - _i14.Key? key, - required int clientId, - List<_i13.PageRouteInfo>? children, - }) : super( - ClientDetailsRoute.name, - args: ClientDetailsRouteArgs(key: key, clientId: clientId), - rawPathParams: {'clientId': clientId}, - initialChildren: children, - ); - - static const String name = 'ClientDetailsRoute'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - final pathParams = data.inheritedPathParams; - final args = data.argsAs( - orElse: () => - ClientDetailsRouteArgs(clientId: pathParams.getInt('clientId')), - ); - return _i4.ClientDetailsScreen(key: args.key, clientId: args.clientId); - }, - ); -} - -class ClientDetailsRouteArgs { - const ClientDetailsRouteArgs({this.key, required this.clientId}); - - final _i14.Key? key; - - final int clientId; - - @override - String toString() { - return 'ClientDetailsRouteArgs{key: $key, clientId: $clientId}'; - } - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other is! ClientDetailsRouteArgs) return false; - return key == other.key && clientId == other.clientId; - } - - @override - int get hashCode => key.hashCode ^ clientId.hashCode; -} - -/// generated route for -/// [_i5.ClientsScreen] -class ClientsRoute extends _i13.PageRouteInfo { - const ClientsRoute({List<_i13.PageRouteInfo>? children}) - : super(ClientsRoute.name, initialChildren: children); - - static const String name = 'ClientsRoute'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - return const _i5.ClientsScreen(); - }, - ); -} - -/// generated route for -/// [_i6.CreateEvmGrantScreen] -class CreateEvmGrantRoute extends _i13.PageRouteInfo { - const CreateEvmGrantRoute({List<_i13.PageRouteInfo>? children}) - : super(CreateEvmGrantRoute.name, initialChildren: children); - - static const String name = 'CreateEvmGrantRoute'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - return const _i6.CreateEvmGrantScreen(); - }, - ); -} - -/// generated route for -/// [_i7.DashboardRouter] -class DashboardRouter extends _i13.PageRouteInfo { - const DashboardRouter({List<_i13.PageRouteInfo>? children}) - : super(DashboardRouter.name, initialChildren: children); - - static const String name = 'DashboardRouter'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - return const _i7.DashboardRouter(); - }, - ); -} - -/// generated route for -/// [_i8.EvmGrantsScreen] -class EvmGrantsRoute extends _i13.PageRouteInfo { - const EvmGrantsRoute({List<_i13.PageRouteInfo>? children}) - : super(EvmGrantsRoute.name, initialChildren: children); - - static const String name = 'EvmGrantsRoute'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - return const _i8.EvmGrantsScreen(); - }, - ); -} - -/// generated route for -/// [_i9.EvmScreen] -class EvmRoute extends _i13.PageRouteInfo { - const EvmRoute({List<_i13.PageRouteInfo>? children}) - : super(EvmRoute.name, initialChildren: children); - - static const String name = 'EvmRoute'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - return const _i9.EvmScreen(); - }, - ); -} - -/// generated route for -/// [_i10.ServerConnectionScreen] -class ServerConnectionRoute - extends _i13.PageRouteInfo { - ServerConnectionRoute({ - _i14.Key? key, - String? arbiterUrl, - List<_i13.PageRouteInfo>? children, - }) : super( - ServerConnectionRoute.name, - args: ServerConnectionRouteArgs(key: key, arbiterUrl: arbiterUrl), - initialChildren: children, - ); - - static const String name = 'ServerConnectionRoute'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - final args = data.argsAs( - orElse: () => const ServerConnectionRouteArgs(), - ); - return _i10.ServerConnectionScreen( - key: args.key, - arbiterUrl: args.arbiterUrl, - ); - }, - ); -} - -class ServerConnectionRouteArgs { - const ServerConnectionRouteArgs({this.key, this.arbiterUrl}); - - final _i14.Key? key; - - final String? arbiterUrl; - - @override - String toString() { - return 'ServerConnectionRouteArgs{key: $key, arbiterUrl: $arbiterUrl}'; - } - - @override - bool operator ==(Object other) { - if (identical(this, other)) return true; - if (other is! ServerConnectionRouteArgs) return false; - return key == other.key && arbiterUrl == other.arbiterUrl; - } - - @override - int get hashCode => key.hashCode ^ arbiterUrl.hashCode; -} - -/// generated route for -/// [_i11.ServerInfoSetupScreen] -class ServerInfoSetupRoute extends _i13.PageRouteInfo { - const ServerInfoSetupRoute({List<_i13.PageRouteInfo>? children}) - : super(ServerInfoSetupRoute.name, initialChildren: children); - - static const String name = 'ServerInfoSetupRoute'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - return const _i11.ServerInfoSetupScreen(); - }, - ); -} - -/// generated route for -/// [_i12.VaultSetupScreen] -class VaultSetupRoute extends _i13.PageRouteInfo { - const VaultSetupRoute({List<_i13.PageRouteInfo>? children}) - : super(VaultSetupRoute.name, initialChildren: children); - - static const String name = 'VaultSetupRoute'; - - static _i13.PageInfo page = _i13.PageInfo( - name, - builder: (data) { - return const _i12.VaultSetupScreen(); - }, - ); -} +// dart format width=80 +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// AutoRouterGenerator +// ************************************************************************** + +// ignore_for_file: type=lint +// coverage:ignore-file + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as _i15; +import 'package:arbiter/screens/bootstrap.dart' as _i2; +import 'package:arbiter/screens/dashboard.dart' as _i7; +import 'package:arbiter/screens/dashboard/about.dart' as _i1; +import 'package:arbiter/screens/dashboard/clients/details.dart' as _i3; +import 'package:arbiter/screens/dashboard/clients/details/client_details.dart' + as _i4; +import 'package:arbiter/screens/dashboard/clients/table.dart' as _i5; +import 'package:arbiter/screens/dashboard/evm/evm.dart' as _i9; +import 'package:arbiter/screens/dashboard/evm/grants/create/screen.dart' as _i6; +import 'package:arbiter/screens/dashboard/evm/grants/grants.dart' as _i8; +import 'package:arbiter/screens/server_connection.dart' as _i10; +import 'package:arbiter/screens/server_info_setup.dart' as _i11; +import 'package:arbiter/screens/vault_setup.dart' as _i12; +import 'package:auto_route/auto_route.dart' as _i13; +import 'package:flutter/material.dart' as _i14; + +/// generated route for +/// [_i1.AboutScreen] +class AboutRoute extends _i13.PageRouteInfo { + const AboutRoute({List<_i13.PageRouteInfo>? children}) + : super(AboutRoute.name, initialChildren: children); + + static const String name = 'AboutRoute'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i1.AboutScreen(); + }, + ); +} + +/// generated route for +/// [_i2.Bootstrap] +class Bootstrap extends _i13.PageRouteInfo { + const Bootstrap({List<_i13.PageRouteInfo>? children}) + : super(Bootstrap.name, initialChildren: children); + + static const String name = 'Bootstrap'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i2.Bootstrap(); + }, + ); +} + +/// generated route for +/// [_i3.ClientDetails] +class ClientDetails extends _i13.PageRouteInfo { + ClientDetails({ + _i14.Key? key, + required _i15.Entry client, + List<_i13.PageRouteInfo>? children, + }) : super( + ClientDetails.name, + args: ClientDetailsArgs(key: key, client: client), + initialChildren: children, + ); + + static const String name = 'ClientDetails'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + final args = data.argsAs(); + return _i3.ClientDetails(key: args.key, client: args.client); + }, + ); +} + +class ClientDetailsArgs { + const ClientDetailsArgs({this.key, required this.client}); + + final _i14.Key? key; + + final _i15.Entry client; + + @override + String toString() { + return 'ClientDetailsArgs{key: $key, client: $client}'; + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other is! ClientDetailsArgs) return false; + return key == other.key && client == other.client; + } + + @override + int get hashCode => key.hashCode ^ client.hashCode; +} + +/// generated route for +/// [_i4.ClientDetailsScreen] +class ClientDetailsRoute extends _i13.PageRouteInfo { + ClientDetailsRoute({ + _i14.Key? key, + required int clientId, + List<_i13.PageRouteInfo>? children, + }) : super( + ClientDetailsRoute.name, + args: ClientDetailsRouteArgs(key: key, clientId: clientId), + rawPathParams: {'clientId': clientId}, + initialChildren: children, + ); + + static const String name = 'ClientDetailsRoute'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + final pathParams = data.inheritedPathParams; + final args = data.argsAs( + orElse: () => + ClientDetailsRouteArgs(clientId: pathParams.getInt('clientId')), + ); + return _i4.ClientDetailsScreen(key: args.key, clientId: args.clientId); + }, + ); +} + +class ClientDetailsRouteArgs { + const ClientDetailsRouteArgs({this.key, required this.clientId}); + + final _i14.Key? key; + + final int clientId; + + @override + String toString() { + return 'ClientDetailsRouteArgs{key: $key, clientId: $clientId}'; + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other is! ClientDetailsRouteArgs) return false; + return key == other.key && clientId == other.clientId; + } + + @override + int get hashCode => key.hashCode ^ clientId.hashCode; +} + +/// generated route for +/// [_i5.ClientsScreen] +class ClientsRoute extends _i13.PageRouteInfo { + const ClientsRoute({List<_i13.PageRouteInfo>? children}) + : super(ClientsRoute.name, initialChildren: children); + + static const String name = 'ClientsRoute'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i5.ClientsScreen(); + }, + ); +} + +/// generated route for +/// [_i6.CreateEvmGrantScreen] +class CreateEvmGrantRoute extends _i13.PageRouteInfo { + const CreateEvmGrantRoute({List<_i13.PageRouteInfo>? children}) + : super(CreateEvmGrantRoute.name, initialChildren: children); + + static const String name = 'CreateEvmGrantRoute'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i6.CreateEvmGrantScreen(); + }, + ); +} + +/// generated route for +/// [_i7.DashboardRouter] +class DashboardRouter extends _i13.PageRouteInfo { + const DashboardRouter({List<_i13.PageRouteInfo>? children}) + : super(DashboardRouter.name, initialChildren: children); + + static const String name = 'DashboardRouter'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i7.DashboardRouter(); + }, + ); +} + +/// generated route for +/// [_i8.EvmGrantsScreen] +class EvmGrantsRoute extends _i13.PageRouteInfo { + const EvmGrantsRoute({List<_i13.PageRouteInfo>? children}) + : super(EvmGrantsRoute.name, initialChildren: children); + + static const String name = 'EvmGrantsRoute'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i8.EvmGrantsScreen(); + }, + ); +} + +/// generated route for +/// [_i9.EvmScreen] +class EvmRoute extends _i13.PageRouteInfo { + const EvmRoute({List<_i13.PageRouteInfo>? children}) + : super(EvmRoute.name, initialChildren: children); + + static const String name = 'EvmRoute'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i9.EvmScreen(); + }, + ); +} + +/// generated route for +/// [_i10.ServerConnectionScreen] +class ServerConnectionRoute + extends _i13.PageRouteInfo { + ServerConnectionRoute({ + _i14.Key? key, + String? arbiterUrl, + List<_i13.PageRouteInfo>? children, + }) : super( + ServerConnectionRoute.name, + args: ServerConnectionRouteArgs(key: key, arbiterUrl: arbiterUrl), + initialChildren: children, + ); + + static const String name = 'ServerConnectionRoute'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + final args = data.argsAs( + orElse: () => const ServerConnectionRouteArgs(), + ); + return _i10.ServerConnectionScreen( + key: args.key, + arbiterUrl: args.arbiterUrl, + ); + }, + ); +} + +class ServerConnectionRouteArgs { + const ServerConnectionRouteArgs({this.key, this.arbiterUrl}); + + final _i14.Key? key; + + final String? arbiterUrl; + + @override + String toString() { + return 'ServerConnectionRouteArgs{key: $key, arbiterUrl: $arbiterUrl}'; + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other is! ServerConnectionRouteArgs) return false; + return key == other.key && arbiterUrl == other.arbiterUrl; + } + + @override + int get hashCode => key.hashCode ^ arbiterUrl.hashCode; +} + +/// generated route for +/// [_i11.ServerInfoSetupScreen] +class ServerInfoSetupRoute extends _i13.PageRouteInfo { + const ServerInfoSetupRoute({List<_i13.PageRouteInfo>? children}) + : super(ServerInfoSetupRoute.name, initialChildren: children); + + static const String name = 'ServerInfoSetupRoute'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i11.ServerInfoSetupScreen(); + }, + ); +} + +/// generated route for +/// [_i12.VaultSetupScreen] +class VaultSetupRoute extends _i13.PageRouteInfo { + const VaultSetupRoute({List<_i13.PageRouteInfo>? children}) + : super(VaultSetupRoute.name, initialChildren: children); + + static const String name = 'VaultSetupRoute'; + + static _i13.PageInfo page = _i13.PageInfo( + name, + builder: (data) { + return const _i12.VaultSetupScreen(); + }, + ); +} diff --git a/useragent/lib/screens/bootstrap.dart b/useragent/lib/screens/bootstrap.dart index 25f8657..9f73f0d 100644 --- a/useragent/lib/screens/bootstrap.dart +++ b/useragent/lib/screens/bootstrap.dart @@ -1,39 +1,39 @@ -import 'dart:async'; - -import 'package:arbiter/providers/key.dart'; -import 'package:arbiter/router.gr.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:mtcore/markettakers.dart'; - -@RoutePage() -class Bootstrap extends HookConsumerWidget { - const Bootstrap({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final container = ProviderScope.containerOf(context); - final completer = useMemoized(() { - final completer = Completer(); - completer.future.then((_) async { - if (context.mounted) { - final router = AutoRouter.of(context); - router.replace(const ServerInfoSetupRoute()); - } - }); - - return completer; - }, []); - final stages = useMemoized(() { - return [KeyBootstrapper(ref: container)]; - }, []); - final bootstrapper = useMemoized( - () => Bootstrapper(stages: stages, onCompleted: completer), - [stages], - ); - - return Scaffold(body: bootstrapper); - } -} +import 'dart:async'; + +import 'package:arbiter/providers/key.dart'; +import 'package:arbiter/router.gr.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:mtcore/markettakers.dart'; + +@RoutePage() +class Bootstrap extends HookConsumerWidget { + const Bootstrap({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final container = ProviderScope.containerOf(context); + final completer = useMemoized(() { + final completer = Completer(); + completer.future.then((_) async { + if (context.mounted) { + final router = AutoRouter.of(context); + router.replace(const ServerInfoSetupRoute()); + } + }); + + return completer; + }, []); + final stages = useMemoized(() { + return [KeyBootstrapper(ref: container)]; + }, []); + final bootstrapper = useMemoized( + () => Bootstrapper(stages: stages, onCompleted: completer), + [stages], + ); + + return Scaffold(body: bootstrapper); + } +} diff --git a/useragent/lib/screens/callouts/sdk_connect.dart b/useragent/lib/screens/callouts/sdk_connect.dart index aa7c194..a437b7e 100644 --- a/useragent/lib/screens/callouts/sdk_connect.dart +++ b/useragent/lib/screens/callouts/sdk_connect.dart @@ -1,143 +1,143 @@ -import 'package:arbiter/proto/shared/client.pb.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:arbiter/widgets/cream_frame.dart'; -import 'package:flutter/material.dart'; -import 'package:sizer/sizer.dart'; - -class SdkConnectCallout extends StatelessWidget { - const SdkConnectCallout({ - super.key, - required this.pubkey, - required this.clientInfo, - this.onAccept, - this.onDecline, - }); - - final String pubkey; - final ClientInfo clientInfo; - final VoidCallback? onAccept; - final VoidCallback? onDecline; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - final name = clientInfo.hasName() && clientInfo.name.isNotEmpty - ? clientInfo.name - : _shortPubkey(pubkey); - - final hasDescription = - clientInfo.hasDescription() && clientInfo.description.isNotEmpty; - final hasVersion = clientInfo.hasVersion() && clientInfo.version.isNotEmpty; - final showInfoCard = hasDescription || hasVersion; - - return CreamFrame( - padding: EdgeInsets.all(2.4.h), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - spacing: 1.6.h, - children: [ - // if (clientInfo.iconUrl != null) - // CircleAvatar( - // radius: 36, - // backgroundColor: Palette.line, - // backgroundImage: NetworkImage(iconUrl!), - // ), - Column( - crossAxisAlignment: CrossAxisAlignment.center, - spacing: 0.4.h, - children: [ - Text( - name, - textAlign: TextAlign.center, - style: theme.textTheme.titleLarge?.copyWith( - color: Palette.ink, - fontWeight: FontWeight.w800, - ), - ), - Text( - 'is requesting a connection', - textAlign: TextAlign.center, - style: theme.textTheme.bodyMedium?.copyWith( - color: Palette.ink.withValues(alpha: 0.55), - ), - ), - ], - ), - if (showInfoCard) - Container( - width: double.infinity, - decoration: BoxDecoration( - color: Palette.ink.withValues(alpha: 0.04), - borderRadius: BorderRadius.circular(14), - border: Border.all(color: Palette.line), - ), - padding: EdgeInsets.symmetric(horizontal: 1.6.w, vertical: 1.2.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - spacing: 0.6.h, - children: [ - if (hasDescription) - Text( - clientInfo.description, - style: theme.textTheme.bodyMedium?.copyWith( - color: Palette.ink.withValues(alpha: 0.80), - height: 1.5, - ), - ), - if (hasVersion) - Text( - 'v${clientInfo.version}', - style: theme.textTheme.bodySmall?.copyWith( - color: Palette.ink.withValues(alpha: 0.50), - ), - ), - ], - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - child: OutlinedButton( - onPressed: onDecline, - style: OutlinedButton.styleFrom( - foregroundColor: Palette.coral, - side: BorderSide( - color: Palette.coral.withValues(alpha: 0.50), - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(14), - ), - padding: EdgeInsets.symmetric(vertical: 1.4.h), - ), - child: const Text('Decline'), - ), - ), - Expanded( - child: FilledButton( - onPressed: onAccept, - style: FilledButton.styleFrom( - backgroundColor: Palette.ink, - foregroundColor: Palette.cream, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(14), - ), - padding: EdgeInsets.symmetric(vertical: 1.4.h), - ), - child: const Text('Accept'), - ), - ), - ], - ), - ], - ), - ); - } -} - -String _shortPubkey(String base64Pubkey) { - if (base64Pubkey.length < 12) return base64Pubkey; - return '${base64Pubkey.substring(0, 8)}…${base64Pubkey.substring(base64Pubkey.length - 4)}'; -} +import 'package:arbiter/proto/shared/client.pb.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:arbiter/widgets/cream_frame.dart'; +import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; + +class SdkConnectCallout extends StatelessWidget { + const SdkConnectCallout({ + super.key, + required this.pubkey, + required this.clientInfo, + this.onAccept, + this.onDecline, + }); + + final String pubkey; + final ClientInfo clientInfo; + final VoidCallback? onAccept; + final VoidCallback? onDecline; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + final name = clientInfo.hasName() && clientInfo.name.isNotEmpty + ? clientInfo.name + : _shortPubkey(pubkey); + + final hasDescription = + clientInfo.hasDescription() && clientInfo.description.isNotEmpty; + final hasVersion = clientInfo.hasVersion() && clientInfo.version.isNotEmpty; + final showInfoCard = hasDescription || hasVersion; + + return CreamFrame( + padding: EdgeInsets.all(2.4.h), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + spacing: 1.6.h, + children: [ + // if (clientInfo.iconUrl != null) + // CircleAvatar( + // radius: 36, + // backgroundColor: Palette.line, + // backgroundImage: NetworkImage(iconUrl!), + // ), + Column( + crossAxisAlignment: CrossAxisAlignment.center, + spacing: 0.4.h, + children: [ + Text( + name, + textAlign: TextAlign.center, + style: theme.textTheme.titleLarge?.copyWith( + color: Palette.ink, + fontWeight: FontWeight.w800, + ), + ), + Text( + 'is requesting a connection', + textAlign: TextAlign.center, + style: theme.textTheme.bodyMedium?.copyWith( + color: Palette.ink.withValues(alpha: 0.55), + ), + ), + ], + ), + if (showInfoCard) + Container( + width: double.infinity, + decoration: BoxDecoration( + color: Palette.ink.withValues(alpha: 0.04), + borderRadius: BorderRadius.circular(14), + border: Border.all(color: Palette.line), + ), + padding: EdgeInsets.symmetric(horizontal: 1.6.w, vertical: 1.2.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 0.6.h, + children: [ + if (hasDescription) + Text( + clientInfo.description, + style: theme.textTheme.bodyMedium?.copyWith( + color: Palette.ink.withValues(alpha: 0.80), + height: 1.5, + ), + ), + if (hasVersion) + Text( + 'v${clientInfo.version}', + style: theme.textTheme.bodySmall?.copyWith( + color: Palette.ink.withValues(alpha: 0.50), + ), + ), + ], + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: OutlinedButton( + onPressed: onDecline, + style: OutlinedButton.styleFrom( + foregroundColor: Palette.coral, + side: BorderSide( + color: Palette.coral.withValues(alpha: 0.50), + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(14), + ), + padding: EdgeInsets.symmetric(vertical: 1.4.h), + ), + child: const Text('Decline'), + ), + ), + Expanded( + child: FilledButton( + onPressed: onAccept, + style: FilledButton.styleFrom( + backgroundColor: Palette.ink, + foregroundColor: Palette.cream, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(14), + ), + padding: EdgeInsets.symmetric(vertical: 1.4.h), + ), + child: const Text('Accept'), + ), + ), + ], + ), + ], + ), + ); + } +} + +String _shortPubkey(String base64Pubkey) { + if (base64Pubkey.length < 12) return base64Pubkey; + return '${base64Pubkey.substring(0, 8)}…${base64Pubkey.substring(base64Pubkey.length - 4)}'; +} diff --git a/useragent/lib/screens/dashboard.dart b/useragent/lib/screens/dashboard.dart index 9a8c396..12a0e52 100644 --- a/useragent/lib/screens/dashboard.dart +++ b/useragent/lib/screens/dashboard.dart @@ -1,121 +1,121 @@ -import 'package:arbiter/features/callouts/callout_manager.dart'; -import 'package:arbiter/features/callouts/show_callout_list.dart'; -import 'package:arbiter/router.gr.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -const breakpoints = MaterialAdaptiveBreakpoints(); - -final routes = [ - const EvmRoute(), - const ClientsRoute(), - const EvmGrantsRoute(), - const AboutRoute(), -]; - -@RoutePage() -class DashboardRouter extends StatelessWidget { - const DashboardRouter({super.key}); - - @override - Widget build(BuildContext context) { - final title = Container( - margin: const EdgeInsets.all(16), - child: const Text( - "Arbiter", - style: TextStyle(fontWeight: FontWeight.w800), - ), - ); - - return AutoTabsRouter( - routes: routes, - transitionBuilder: (context, child, animation) => - FadeTransition(opacity: animation, child: child), - builder: (context, child) { - final tabsRouter = AutoTabsRouter.of(context); - final currentActive = tabsRouter.activeIndex; - return AdaptiveScaffold( - destinations: const [ - NavigationDestination( - icon: Icon(Icons.account_balance_wallet_outlined), - selectedIcon: Icon(Icons.account_balance_wallet), - label: "Wallets", - ), - NavigationDestination( - icon: Icon(Icons.devices_other_outlined), - selectedIcon: Icon(Icons.devices_other), - label: "Clients", - ), - NavigationDestination( - icon: Icon(Icons.policy_outlined), - selectedIcon: Icon(Icons.policy), - label: "Grants", - ), - NavigationDestination( - icon: Icon(Icons.info_outline), - selectedIcon: Icon(Icons.info), - label: "About", - ), - ], - body: (ctx) => child, - onSelectedIndexChange: (index) { - tabsRouter.navigate(routes[index]); - }, - leadingExtendedNavRail: title, - leadingUnextendedNavRail: title, - selectedIndex: currentActive, - transitionDuration: const Duration(milliseconds: 800), - internalAnimations: true, - - trailingNavRail: const _CalloutBell(), - ); - }, - ); - } -} - -class _CalloutBell extends ConsumerWidget { - const _CalloutBell(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final count = ref.watch(calloutManagerProvider.select((map) => map.length)); - - return IconButton( - onPressed: () => showCalloutList(context, ref), - icon: Stack( - clipBehavior: Clip.none, - children: [ - Icon( - count > 0 ? Icons.notifications : Icons.notifications_outlined, - color: Palette.ink, - ), - if (count > 0) - Positioned( - top: -2, - right: -4, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1), - decoration: BoxDecoration( - color: Colors.green, - borderRadius: BorderRadius.circular(10), - ), - child: Text( - count > 99 ? '99+' : '$count', - style: const TextStyle( - color: Colors.white, - fontSize: 9, - fontWeight: FontWeight.w800, - height: 1.2, - ), - ), - ), - ), - ], - ), - ); - } -} +import 'package:arbiter/features/callouts/callout_manager.dart'; +import 'package:arbiter/features/callouts/show_callout_list.dart'; +import 'package:arbiter/router.gr.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +const breakpoints = MaterialAdaptiveBreakpoints(); + +final routes = [ + const EvmRoute(), + const ClientsRoute(), + const EvmGrantsRoute(), + const AboutRoute(), +]; + +@RoutePage() +class DashboardRouter extends StatelessWidget { + const DashboardRouter({super.key}); + + @override + Widget build(BuildContext context) { + final title = Container( + margin: const EdgeInsets.all(16), + child: const Text( + "Arbiter", + style: TextStyle(fontWeight: FontWeight.w800), + ), + ); + + return AutoTabsRouter( + routes: routes, + transitionBuilder: (context, child, animation) => + FadeTransition(opacity: animation, child: child), + builder: (context, child) { + final tabsRouter = AutoTabsRouter.of(context); + final currentActive = tabsRouter.activeIndex; + return AdaptiveScaffold( + destinations: const [ + NavigationDestination( + icon: Icon(Icons.account_balance_wallet_outlined), + selectedIcon: Icon(Icons.account_balance_wallet), + label: "Wallets", + ), + NavigationDestination( + icon: Icon(Icons.devices_other_outlined), + selectedIcon: Icon(Icons.devices_other), + label: "Clients", + ), + NavigationDestination( + icon: Icon(Icons.policy_outlined), + selectedIcon: Icon(Icons.policy), + label: "Grants", + ), + NavigationDestination( + icon: Icon(Icons.info_outline), + selectedIcon: Icon(Icons.info), + label: "About", + ), + ], + body: (ctx) => child, + onSelectedIndexChange: (index) { + tabsRouter.navigate(routes[index]); + }, + leadingExtendedNavRail: title, + leadingUnextendedNavRail: title, + selectedIndex: currentActive, + transitionDuration: const Duration(milliseconds: 800), + internalAnimations: true, + + trailingNavRail: const _CalloutBell(), + ); + }, + ); + } +} + +class _CalloutBell extends ConsumerWidget { + const _CalloutBell(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final count = ref.watch(calloutManagerProvider.select((map) => map.length)); + + return IconButton( + onPressed: () => showCalloutList(context, ref), + icon: Stack( + clipBehavior: Clip.none, + children: [ + Icon( + count > 0 ? Icons.notifications : Icons.notifications_outlined, + color: Palette.ink, + ), + if (count > 0) + Positioned( + top: -2, + right: -4, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1), + decoration: BoxDecoration( + color: Colors.green, + borderRadius: BorderRadius.circular(10), + ), + child: Text( + count > 99 ? '99+' : '$count', + style: const TextStyle( + color: Colors.white, + fontSize: 9, + fontWeight: FontWeight.w800, + height: 1.2, + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/useragent/lib/screens/dashboard/about.dart b/useragent/lib/screens/dashboard/about.dart index 3745aec..1e2da1b 100644 --- a/useragent/lib/screens/dashboard/about.dart +++ b/useragent/lib/screens/dashboard/about.dart @@ -1,13 +1,13 @@ -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:mtcore/markettakers.dart' as mt; - -@RoutePage() -class AboutScreen extends StatelessWidget { - const AboutScreen({super.key}); - - @override - Widget build(BuildContext context) { - return mt.AboutScreen(decription: "Arbiter is bla bla bla"); - } -} +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:mtcore/markettakers.dart' as mt; + +@RoutePage() +class AboutScreen extends StatelessWidget { + const AboutScreen({super.key}); + + @override + Widget build(BuildContext context) { + return mt.AboutScreen(decription: "Arbiter is bla bla bla"); + } +} diff --git a/useragent/lib/screens/dashboard/clients/details.dart b/useragent/lib/screens/dashboard/clients/details.dart index 25c700d..1fef07f 100644 --- a/useragent/lib/screens/dashboard/clients/details.dart +++ b/useragent/lib/screens/dashboard/clients/details.dart @@ -1,15 +1,15 @@ -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -@RoutePage() -class ClientDetails extends ConsumerWidget { - final ua_sdk.Entry client; - const ClientDetails({super.key, required this.client}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - throw UnimplementedError(); - } -} +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +@RoutePage() +class ClientDetails extends ConsumerWidget { + final ua_sdk.Entry client; + const ClientDetails({super.key, required this.client}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + throw UnimplementedError(); + } +} diff --git a/useragent/lib/screens/dashboard/clients/details/client_details.dart b/useragent/lib/screens/dashboard/clients/details/client_details.dart index 49af73a..e2860f6 100644 --- a/useragent/lib/screens/dashboard/clients/details/client_details.dart +++ b/useragent/lib/screens/dashboard/clients/details/client_details.dart @@ -1,56 +1,56 @@ -import 'package:arbiter/providers/sdk_clients/details.dart'; -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/screens/dashboard/clients/details/widgets/client_details_content.dart'; -import 'package:arbiter/screens/dashboard/clients/details/widgets/client_details_state_panel.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -@RoutePage() -class ClientDetailsScreen extends ConsumerWidget { - const ClientDetailsScreen({super.key, @pathParam required this.clientId}); - - final int clientId; - - @override - Widget build(BuildContext context, WidgetRef ref) { - final clientAsync = ref.watch(clientDetailsProvider(clientId)); - return Scaffold( - body: SafeArea( - child: clientAsync.when( - data: (client) => - _ClientDetailsState(clientId: clientId, client: client), - error: (error, _) => ClientDetailsStatePanel( - title: 'Client unavailable', - body: error.toString(), - icon: Icons.sync_problem, - ), - loading: () => const ClientDetailsStatePanel( - title: 'Loading client', - body: 'Pulling client details from Arbiter.', - icon: Icons.hourglass_top, - ), - ), - ), - ); - } -} - -class _ClientDetailsState extends StatelessWidget { - const _ClientDetailsState({required this.clientId, required this.client}); - - final int clientId; - final ua_sdk.Entry? client; - - @override - Widget build(BuildContext context) { - if (client == null) { - return const ClientDetailsStatePanel( - title: 'Client not found', - body: 'The selected SDK client is no longer available.', - icon: Icons.person_off_outlined, - ); - } - return ClientDetailsContent(clientId: clientId, client: client!); - } -} +import 'package:arbiter/providers/sdk_clients/details.dart'; +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/screens/dashboard/clients/details/widgets/client_details_content.dart'; +import 'package:arbiter/screens/dashboard/clients/details/widgets/client_details_state_panel.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +@RoutePage() +class ClientDetailsScreen extends ConsumerWidget { + const ClientDetailsScreen({super.key, @pathParam required this.clientId}); + + final int clientId; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final clientAsync = ref.watch(clientDetailsProvider(clientId)); + return Scaffold( + body: SafeArea( + child: clientAsync.when( + data: (client) => + _ClientDetailsState(clientId: clientId, client: client), + error: (error, _) => ClientDetailsStatePanel( + title: 'Client unavailable', + body: error.toString(), + icon: Icons.sync_problem, + ), + loading: () => const ClientDetailsStatePanel( + title: 'Loading client', + body: 'Pulling client details from Arbiter.', + icon: Icons.hourglass_top, + ), + ), + ), + ); + } +} + +class _ClientDetailsState extends StatelessWidget { + const _ClientDetailsState({required this.clientId, required this.client}); + + final int clientId; + final ua_sdk.Entry? client; + + @override + Widget build(BuildContext context) { + if (client == null) { + return const ClientDetailsStatePanel( + title: 'Client not found', + body: 'The selected SDK client is no longer available.', + icon: Icons.person_off_outlined, + ); + } + return ClientDetailsContent(clientId: clientId, client: client!); + } +} diff --git a/useragent/lib/screens/dashboard/clients/details/widgets/client_details_content.dart b/useragent/lib/screens/dashboard/clients/details/widgets/client_details_content.dart index b7fb7cf..613af61 100644 --- a/useragent/lib/screens/dashboard/clients/details/widgets/client_details_content.dart +++ b/useragent/lib/screens/dashboard/clients/details/widgets/client_details_content.dart @@ -1,55 +1,55 @@ -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; -import 'package:arbiter/screens/dashboard/clients/details/widgets/client_details_header.dart'; -import 'package:arbiter/screens/dashboard/clients/details/widgets/client_summary_card.dart'; -import 'package:arbiter/screens/dashboard/clients/details/widgets/wallet_access_save_bar.dart'; -import 'package:arbiter/screens/dashboard/clients/details/widgets/wallet_access_section.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -class ClientDetailsContent extends ConsumerWidget { - const ClientDetailsContent({ - super.key, - required this.clientId, - required this.client, - }); - - final int clientId; - final ua_sdk.Entry client; - - @override - Widget build(BuildContext context, WidgetRef ref) { - final state = ref.watch(clientWalletAccessControllerProvider(clientId)); - final notifier = ref.read( - clientWalletAccessControllerProvider(clientId).notifier, - ); - final saveMutation = ref.watch(saveClientWalletAccessMutation(clientId)); - return ListView( - padding: const EdgeInsets.all(16), - children: [ - const ClientDetailsHeader(), - const SizedBox(height: 16), - ClientSummaryCard(client: client), - const SizedBox(height: 16), - WalletAccessSection( - clientId: clientId, - state: state, - accessSelectionAsync: ref.watch( - clientWalletAccessSelectionProvider(clientId), - ), - isSavePending: saveMutation is MutationPending, - onSearchChanged: notifier.setSearchQuery, - onToggleWallet: notifier.toggleWallet, - ), - const SizedBox(height: 16), - WalletAccessSaveBar( - state: state, - saveMutation: saveMutation, - onDiscard: notifier.discardChanges, - onSave: () => executeSaveClientWalletAccess(ref, clientId: clientId), - ), - ], - ); - } -} +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; +import 'package:arbiter/screens/dashboard/clients/details/widgets/client_details_header.dart'; +import 'package:arbiter/screens/dashboard/clients/details/widgets/client_summary_card.dart'; +import 'package:arbiter/screens/dashboard/clients/details/widgets/wallet_access_save_bar.dart'; +import 'package:arbiter/screens/dashboard/clients/details/widgets/wallet_access_section.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +class ClientDetailsContent extends ConsumerWidget { + const ClientDetailsContent({ + super.key, + required this.clientId, + required this.client, + }); + + final int clientId; + final ua_sdk.Entry client; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final state = ref.watch(clientWalletAccessControllerProvider(clientId)); + final notifier = ref.read( + clientWalletAccessControllerProvider(clientId).notifier, + ); + final saveMutation = ref.watch(saveClientWalletAccessMutation(clientId)); + return ListView( + padding: const EdgeInsets.all(16), + children: [ + const ClientDetailsHeader(), + const SizedBox(height: 16), + ClientSummaryCard(client: client), + const SizedBox(height: 16), + WalletAccessSection( + clientId: clientId, + state: state, + accessSelectionAsync: ref.watch( + clientWalletAccessSelectionProvider(clientId), + ), + isSavePending: saveMutation is MutationPending, + onSearchChanged: notifier.setSearchQuery, + onToggleWallet: notifier.toggleWallet, + ), + const SizedBox(height: 16), + WalletAccessSaveBar( + state: state, + saveMutation: saveMutation, + onDiscard: notifier.discardChanges, + onSave: () => executeSaveClientWalletAccess(ref, clientId: clientId), + ), + ], + ); + } +} diff --git a/useragent/lib/screens/dashboard/clients/details/widgets/client_details_header.dart b/useragent/lib/screens/dashboard/clients/details/widgets/client_details_header.dart index f93562a..27cc965 100644 --- a/useragent/lib/screens/dashboard/clients/details/widgets/client_details_header.dart +++ b/useragent/lib/screens/dashboard/clients/details/widgets/client_details_header.dart @@ -1,23 +1,23 @@ -import 'package:flutter/material.dart'; - -class ClientDetailsHeader extends StatelessWidget { - const ClientDetailsHeader({super.key}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return Row( - children: [ - BackButton(onPressed: () => Navigator.of(context).maybePop()), - Expanded( - child: Text( - 'Client Details', - style: theme.textTheme.headlineSmall?.copyWith( - fontWeight: FontWeight.w800, - ), - ), - ), - ], - ); - } -} +import 'package:flutter/material.dart'; + +class ClientDetailsHeader extends StatelessWidget { + const ClientDetailsHeader({super.key}); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Row( + children: [ + BackButton(onPressed: () => Navigator.of(context).maybePop()), + Expanded( + child: Text( + 'Client Details', + style: theme.textTheme.headlineSmall?.copyWith( + fontWeight: FontWeight.w800, + ), + ), + ), + ], + ); + } +} diff --git a/useragent/lib/screens/dashboard/clients/details/widgets/client_details_state_panel.dart b/useragent/lib/screens/dashboard/clients/details/widgets/client_details_state_panel.dart index 82f5b41..6a9344f 100644 --- a/useragent/lib/screens/dashboard/clients/details/widgets/client_details_state_panel.dart +++ b/useragent/lib/screens/dashboard/clients/details/widgets/client_details_state_panel.dart @@ -1,37 +1,37 @@ -import 'package:arbiter/theme/palette.dart'; -import 'package:arbiter/widgets/cream_frame.dart'; -import 'package:flutter/material.dart'; - -class ClientDetailsStatePanel extends StatelessWidget { - const ClientDetailsStatePanel({ - super.key, - required this.title, - required this.body, - required this.icon, - }); - - final String title; - final String body; - final IconData icon; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return Center( - child: CreamFrame( - margin: const EdgeInsets.all(24), - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(icon, color: Palette.coral), - const SizedBox(height: 12), - Text(title, style: theme.textTheme.titleLarge), - const SizedBox(height: 8), - Text(body, textAlign: TextAlign.center), - ], - ), - ), - ); - } -} +import 'package:arbiter/theme/palette.dart'; +import 'package:arbiter/widgets/cream_frame.dart'; +import 'package:flutter/material.dart'; + +class ClientDetailsStatePanel extends StatelessWidget { + const ClientDetailsStatePanel({ + super.key, + required this.title, + required this.body, + required this.icon, + }); + + final String title; + final String body; + final IconData icon; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Center( + child: CreamFrame( + margin: const EdgeInsets.all(24), + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, color: Palette.coral), + const SizedBox(height: 12), + Text(title, style: theme.textTheme.titleLarge), + const SizedBox(height: 8), + Text(body, textAlign: TextAlign.center), + ], + ), + ), + ); + } +} diff --git a/useragent/lib/screens/dashboard/clients/details/widgets/client_summary_card.dart b/useragent/lib/screens/dashboard/clients/details/widgets/client_summary_card.dart index 4de0b5d..53aa711 100644 --- a/useragent/lib/screens/dashboard/clients/details/widgets/client_summary_card.dart +++ b/useragent/lib/screens/dashboard/clients/details/widgets/client_summary_card.dart @@ -1,69 +1,69 @@ -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/widgets/cream_frame.dart'; -import 'package:flutter/material.dart'; - -class ClientSummaryCard extends StatelessWidget { - const ClientSummaryCard({super.key, required this.client}); - - final ua_sdk.Entry client; - - @override - Widget build(BuildContext context) { - return CreamFrame( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(client.info.name, style: Theme.of(context).textTheme.titleLarge), - const SizedBox(height: 8), - Text(client.info.description), - const SizedBox(height: 16), - Wrap( - runSpacing: 8, - spacing: 16, - children: [ - _Fact(label: 'Client ID', value: '${client.id}'), - _Fact(label: 'Version', value: client.info.version), - _Fact(label: 'Registered', value: _formatDate(client.createdAt)), - _Fact(label: 'Pubkey', value: _shortPubkey(client.pubkey)), - ], - ), - ], - ), - ); - } -} - -class _Fact extends StatelessWidget { - const _Fact({required this.label, required this.value}); - - final String label; - final String value; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(label, style: theme.textTheme.labelMedium), - Text(value.isEmpty ? '—' : value, style: theme.textTheme.bodyMedium), - ], - ); - } -} - -String _formatDate(int unixSecs) { - final dt = DateTime.fromMillisecondsSinceEpoch(unixSecs * 1000).toLocal(); - return '${dt.year}-${dt.month.toString().padLeft(2, '0')}-${dt.day.toString().padLeft(2, '0')}'; -} - -String _shortPubkey(List bytes) { - final hex = bytes - .map((byte) => byte.toRadixString(16).padLeft(2, '0')) - .join(); - if (hex.length < 12) { - return '0x$hex'; - } - return '0x${hex.substring(0, 8)}...${hex.substring(hex.length - 4)}'; -} +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/widgets/cream_frame.dart'; +import 'package:flutter/material.dart'; + +class ClientSummaryCard extends StatelessWidget { + const ClientSummaryCard({super.key, required this.client}); + + final ua_sdk.Entry client; + + @override + Widget build(BuildContext context) { + return CreamFrame( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(client.info.name, style: Theme.of(context).textTheme.titleLarge), + const SizedBox(height: 8), + Text(client.info.description), + const SizedBox(height: 16), + Wrap( + runSpacing: 8, + spacing: 16, + children: [ + _Fact(label: 'Client ID', value: '${client.id}'), + _Fact(label: 'Version', value: client.info.version), + _Fact(label: 'Registered', value: _formatDate(client.createdAt)), + _Fact(label: 'Pubkey', value: _shortPubkey(client.pubkey)), + ], + ), + ], + ), + ); + } +} + +class _Fact extends StatelessWidget { + const _Fact({required this.label, required this.value}); + + final String label; + final String value; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: theme.textTheme.labelMedium), + Text(value.isEmpty ? '—' : value, style: theme.textTheme.bodyMedium), + ], + ); + } +} + +String _formatDate(int unixSecs) { + final dt = DateTime.fromMillisecondsSinceEpoch(unixSecs * 1000).toLocal(); + return '${dt.year}-${dt.month.toString().padLeft(2, '0')}-${dt.day.toString().padLeft(2, '0')}'; +} + +String _shortPubkey(List bytes) { + final hex = bytes + .map((byte) => byte.toRadixString(16).padLeft(2, '0')) + .join(); + if (hex.length < 12) { + return '0x$hex'; + } + return '0x${hex.substring(0, 8)}...${hex.substring(hex.length - 4)}'; +} diff --git a/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_list.dart b/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_list.dart index a59a909..fd77fa8 100644 --- a/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_list.dart +++ b/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_list.dart @@ -1,33 +1,33 @@ -import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; -import 'package:arbiter/screens/dashboard/clients/details/widgets/wallet_access_tile.dart'; -import 'package:flutter/material.dart'; - -class WalletAccessList extends StatelessWidget { - const WalletAccessList({ - super.key, - required this.options, - required this.selectedWalletIds, - required this.enabled, - required this.onToggleWallet, - }); - - final List options; - final Set selectedWalletIds; - final bool enabled; - final ValueChanged onToggleWallet; - - @override - Widget build(BuildContext context) { - return Column( - children: [ - for (final option in options) - WalletAccessTile( - option: option, - value: selectedWalletIds.contains(option.walletId), - enabled: enabled, - onChanged: () => onToggleWallet(option.walletId), - ), - ], - ); - } -} +import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; +import 'package:arbiter/screens/dashboard/clients/details/widgets/wallet_access_tile.dart'; +import 'package:flutter/material.dart'; + +class WalletAccessList extends StatelessWidget { + const WalletAccessList({ + super.key, + required this.options, + required this.selectedWalletIds, + required this.enabled, + required this.onToggleWallet, + }); + + final List options; + final Set selectedWalletIds; + final bool enabled; + final ValueChanged onToggleWallet; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + for (final option in options) + WalletAccessTile( + option: option, + value: selectedWalletIds.contains(option.walletId), + enabled: enabled, + onChanged: () => onToggleWallet(option.walletId), + ), + ], + ); + } +} diff --git a/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_save_bar.dart b/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_save_bar.dart index d52828a..04f8f7d 100644 --- a/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_save_bar.dart +++ b/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_save_bar.dart @@ -1,54 +1,54 @@ -import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:arbiter/widgets/cream_frame.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; - -class WalletAccessSaveBar extends StatelessWidget { - const WalletAccessSaveBar({ - super.key, - required this.state, - required this.saveMutation, - required this.onDiscard, - required this.onSave, - }); - - final ClientWalletAccessState state; - final MutationState saveMutation; - final VoidCallback onDiscard; - final Future Function() onSave; - - @override - Widget build(BuildContext context) { - final isPending = saveMutation is MutationPending; - final errorText = switch (saveMutation) { - MutationError(:final error) => error.toString(), - _ => null, - }; - return CreamFrame( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (errorText != null) ...[ - Text(errorText, style: TextStyle(color: Palette.coral)), - const SizedBox(height: 12), - ], - Row( - children: [ - TextButton( - onPressed: state.hasChanges && !isPending ? onDiscard : null, - child: const Text('Reset'), - ), - const Spacer(), - FilledButton( - onPressed: state.hasChanges && !isPending ? onSave : null, - child: Text(isPending ? 'Saving...' : 'Save changes'), - ), - ], - ), - ], - ), - ); - } -} +import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:arbiter/widgets/cream_frame.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; + +class WalletAccessSaveBar extends StatelessWidget { + const WalletAccessSaveBar({ + super.key, + required this.state, + required this.saveMutation, + required this.onDiscard, + required this.onSave, + }); + + final ClientWalletAccessState state; + final MutationState saveMutation; + final VoidCallback onDiscard; + final Future Function() onSave; + + @override + Widget build(BuildContext context) { + final isPending = saveMutation is MutationPending; + final errorText = switch (saveMutation) { + MutationError(:final error) => error.toString(), + _ => null, + }; + return CreamFrame( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (errorText != null) ...[ + Text(errorText, style: TextStyle(color: Palette.coral)), + const SizedBox(height: 12), + ], + Row( + children: [ + TextButton( + onPressed: state.hasChanges && !isPending ? onDiscard : null, + child: const Text('Reset'), + ), + const Spacer(), + FilledButton( + onPressed: state.hasChanges && !isPending ? onSave : null, + child: Text(isPending ? 'Saving...' : 'Save changes'), + ), + ], + ), + ], + ), + ); + } +} diff --git a/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_search_field.dart b/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_search_field.dart index 62196c7..55c2ce5 100644 --- a/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_search_field.dart +++ b/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_search_field.dart @@ -1,24 +1,24 @@ -import 'package:flutter/material.dart'; - -class WalletAccessSearchField extends StatelessWidget { - const WalletAccessSearchField({ - super.key, - required this.searchQuery, - required this.onChanged, - }); - - final String searchQuery; - final ValueChanged onChanged; - - @override - Widget build(BuildContext context) { - return TextFormField( - initialValue: searchQuery, - decoration: const InputDecoration( - labelText: 'Search wallets', - prefixIcon: Icon(Icons.search), - ), - onChanged: onChanged, - ); - } -} +import 'package:flutter/material.dart'; + +class WalletAccessSearchField extends StatelessWidget { + const WalletAccessSearchField({ + super.key, + required this.searchQuery, + required this.onChanged, + }); + + final String searchQuery; + final ValueChanged onChanged; + + @override + Widget build(BuildContext context) { + return TextFormField( + initialValue: searchQuery, + decoration: const InputDecoration( + labelText: 'Search wallets', + prefixIcon: Icon(Icons.search), + ), + onChanged: onChanged, + ); + } +} diff --git a/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_section.dart b/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_section.dart index 54f348e..6efeb5f 100644 --- a/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_section.dart +++ b/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_section.dart @@ -1,166 +1,166 @@ -import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; -import 'package:arbiter/screens/dashboard/clients/details/widgets/client_details_state_panel.dart'; -import 'package:arbiter/screens/dashboard/clients/details/widgets/wallet_access_list.dart'; -import 'package:arbiter/screens/dashboard/clients/details/widgets/wallet_access_search_field.dart'; -import 'package:arbiter/widgets/cream_frame.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -class WalletAccessSection extends ConsumerWidget { - const WalletAccessSection({ - super.key, - required this.clientId, - required this.state, - required this.accessSelectionAsync, - required this.isSavePending, - required this.onSearchChanged, - required this.onToggleWallet, - }); - - final int clientId; - final ClientWalletAccessState state; - final AsyncValue> accessSelectionAsync; - final bool isSavePending; - final ValueChanged onSearchChanged; - final ValueChanged onToggleWallet; - - @override - Widget build(BuildContext context, WidgetRef ref) { - final optionsAsync = ref.watch(clientWalletOptionsProvider); - return CreamFrame( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Wallet access', style: Theme.of(context).textTheme.titleLarge), - const SizedBox(height: 8), - Text('Choose which managed wallets this client can see.'), - const SizedBox(height: 16), - _WalletAccessBody( - clientId: clientId, - state: state, - accessSelectionAsync: accessSelectionAsync, - isSavePending: isSavePending, - optionsAsync: optionsAsync, - onSearchChanged: onSearchChanged, - onToggleWallet: onToggleWallet, - ), - ], - ), - ); - } -} - -class _WalletAccessBody extends StatelessWidget { - const _WalletAccessBody({ - required this.clientId, - required this.state, - required this.accessSelectionAsync, - required this.isSavePending, - required this.optionsAsync, - required this.onSearchChanged, - required this.onToggleWallet, - }); - - final int clientId; - final ClientWalletAccessState state; - final AsyncValue> accessSelectionAsync; - final bool isSavePending; - final AsyncValue> optionsAsync; - final ValueChanged onSearchChanged; - final ValueChanged onToggleWallet; - - @override - Widget build(BuildContext context) { - final selectionState = accessSelectionAsync; - if (selectionState.isLoading) { - return const ClientDetailsStatePanel( - title: 'Loading wallet access', - body: 'Pulling the current wallet permissions for this client.', - icon: Icons.hourglass_top, - ); - } - if (selectionState.hasError) { - return ClientDetailsStatePanel( - title: 'Wallet access unavailable', - body: selectionState.error.toString(), - icon: Icons.lock_outline, - ); - } - return optionsAsync.when( - data: (options) => _WalletAccessLoaded( - state: state, - isSavePending: isSavePending, - options: options, - onSearchChanged: onSearchChanged, - onToggleWallet: onToggleWallet, - ), - error: (error, _) => ClientDetailsStatePanel( - title: 'Wallet list unavailable', - body: error.toString(), - icon: Icons.sync_problem, - ), - loading: () => const ClientDetailsStatePanel( - title: 'Loading wallets', - body: 'Pulling the managed wallet inventory.', - icon: Icons.hourglass_top, - ), - ); - } -} - -class _WalletAccessLoaded extends StatelessWidget { - const _WalletAccessLoaded({ - required this.state, - required this.isSavePending, - required this.options, - required this.onSearchChanged, - required this.onToggleWallet, - }); - - final ClientWalletAccessState state; - final bool isSavePending; - final List options; - final ValueChanged onSearchChanged; - final ValueChanged onToggleWallet; - - @override - Widget build(BuildContext context) { - if (options.isEmpty) { - return const ClientDetailsStatePanel( - title: 'No wallets yet', - body: 'Create a managed wallet before assigning client access.', - icon: Icons.account_balance_wallet_outlined, - ); - } - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - WalletAccessSearchField( - searchQuery: state.searchQuery, - onChanged: onSearchChanged, - ), - const SizedBox(height: 16), - WalletAccessList( - options: _filterOptions(options, state.searchQuery), - selectedWalletIds: state.selectedWalletIds, - enabled: !isSavePending, - onToggleWallet: onToggleWallet, - ), - ], - ); - } -} - -List _filterOptions( - List options, - String query, -) { - if (query.isEmpty) { - return options; - } - final normalized = query.toLowerCase(); - return options - .where((option) => option.address.toLowerCase().contains(normalized)) - .toList(growable: false); -} +import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; +import 'package:arbiter/screens/dashboard/clients/details/widgets/client_details_state_panel.dart'; +import 'package:arbiter/screens/dashboard/clients/details/widgets/wallet_access_list.dart'; +import 'package:arbiter/screens/dashboard/clients/details/widgets/wallet_access_search_field.dart'; +import 'package:arbiter/widgets/cream_frame.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +class WalletAccessSection extends ConsumerWidget { + const WalletAccessSection({ + super.key, + required this.clientId, + required this.state, + required this.accessSelectionAsync, + required this.isSavePending, + required this.onSearchChanged, + required this.onToggleWallet, + }); + + final int clientId; + final ClientWalletAccessState state; + final AsyncValue> accessSelectionAsync; + final bool isSavePending; + final ValueChanged onSearchChanged; + final ValueChanged onToggleWallet; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final optionsAsync = ref.watch(clientWalletOptionsProvider); + return CreamFrame( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Wallet access', style: Theme.of(context).textTheme.titleLarge), + const SizedBox(height: 8), + Text('Choose which managed wallets this client can see.'), + const SizedBox(height: 16), + _WalletAccessBody( + clientId: clientId, + state: state, + accessSelectionAsync: accessSelectionAsync, + isSavePending: isSavePending, + optionsAsync: optionsAsync, + onSearchChanged: onSearchChanged, + onToggleWallet: onToggleWallet, + ), + ], + ), + ); + } +} + +class _WalletAccessBody extends StatelessWidget { + const _WalletAccessBody({ + required this.clientId, + required this.state, + required this.accessSelectionAsync, + required this.isSavePending, + required this.optionsAsync, + required this.onSearchChanged, + required this.onToggleWallet, + }); + + final int clientId; + final ClientWalletAccessState state; + final AsyncValue> accessSelectionAsync; + final bool isSavePending; + final AsyncValue> optionsAsync; + final ValueChanged onSearchChanged; + final ValueChanged onToggleWallet; + + @override + Widget build(BuildContext context) { + final selectionState = accessSelectionAsync; + if (selectionState.isLoading) { + return const ClientDetailsStatePanel( + title: 'Loading wallet access', + body: 'Pulling the current wallet permissions for this client.', + icon: Icons.hourglass_top, + ); + } + if (selectionState.hasError) { + return ClientDetailsStatePanel( + title: 'Wallet access unavailable', + body: selectionState.error.toString(), + icon: Icons.lock_outline, + ); + } + return optionsAsync.when( + data: (options) => _WalletAccessLoaded( + state: state, + isSavePending: isSavePending, + options: options, + onSearchChanged: onSearchChanged, + onToggleWallet: onToggleWallet, + ), + error: (error, _) => ClientDetailsStatePanel( + title: 'Wallet list unavailable', + body: error.toString(), + icon: Icons.sync_problem, + ), + loading: () => const ClientDetailsStatePanel( + title: 'Loading wallets', + body: 'Pulling the managed wallet inventory.', + icon: Icons.hourglass_top, + ), + ); + } +} + +class _WalletAccessLoaded extends StatelessWidget { + const _WalletAccessLoaded({ + required this.state, + required this.isSavePending, + required this.options, + required this.onSearchChanged, + required this.onToggleWallet, + }); + + final ClientWalletAccessState state; + final bool isSavePending; + final List options; + final ValueChanged onSearchChanged; + final ValueChanged onToggleWallet; + + @override + Widget build(BuildContext context) { + if (options.isEmpty) { + return const ClientDetailsStatePanel( + title: 'No wallets yet', + body: 'Create a managed wallet before assigning client access.', + icon: Icons.account_balance_wallet_outlined, + ); + } + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + WalletAccessSearchField( + searchQuery: state.searchQuery, + onChanged: onSearchChanged, + ), + const SizedBox(height: 16), + WalletAccessList( + options: _filterOptions(options, state.searchQuery), + selectedWalletIds: state.selectedWalletIds, + enabled: !isSavePending, + onToggleWallet: onToggleWallet, + ), + ], + ); + } +} + +List _filterOptions( + List options, + String query, +) { + if (query.isEmpty) { + return options; + } + final normalized = query.toLowerCase(); + return options + .where((option) => option.address.toLowerCase().contains(normalized)) + .toList(growable: false); +} diff --git a/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_tile.dart b/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_tile.dart index 066c9fb..23ea00e 100644 --- a/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_tile.dart +++ b/useragent/lib/screens/dashboard/clients/details/widgets/wallet_access_tile.dart @@ -1,28 +1,28 @@ -import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; -import 'package:flutter/material.dart'; - -class WalletAccessTile extends StatelessWidget { - const WalletAccessTile({ - super.key, - required this.option, - required this.value, - required this.enabled, - required this.onChanged, - }); - - final ClientWalletOption option; - final bool value; - final bool enabled; - final VoidCallback onChanged; - - @override - Widget build(BuildContext context) { - return CheckboxListTile( - contentPadding: EdgeInsets.zero, - value: value, - onChanged: enabled ? (_) => onChanged() : null, - title: Text('Wallet ${option.walletId}'), - subtitle: Text(option.address), - ); - } -} +import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; +import 'package:flutter/material.dart'; + +class WalletAccessTile extends StatelessWidget { + const WalletAccessTile({ + super.key, + required this.option, + required this.value, + required this.enabled, + required this.onChanged, + }); + + final ClientWalletOption option; + final bool value; + final bool enabled; + final VoidCallback onChanged; + + @override + Widget build(BuildContext context) { + return CheckboxListTile( + contentPadding: EdgeInsets.zero, + value: value, + onChanged: enabled ? (_) => onChanged() : null, + title: Text('Wallet ${option.walletId}'), + subtitle: Text(option.address), + ); + } +} diff --git a/useragent/lib/screens/dashboard/clients/table.dart b/useragent/lib/screens/dashboard/clients/table.dart index 3d9a452..4aa814b 100644 --- a/useragent/lib/screens/dashboard/clients/table.dart +++ b/useragent/lib/screens/dashboard/clients/table.dart @@ -1,509 +1,509 @@ -import 'dart:math' as math; - -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:arbiter/router.gr.dart'; -import 'package:arbiter/providers/sdk_clients/list.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:arbiter/widgets/cream_frame.dart'; -import 'package:arbiter/widgets/state_panel.dart'; -import 'package:sizer/sizer.dart'; - -// ─── Column width getters ───────────────────────────────────────────────────── - -double get _accentStripWidth => 0.8.w; -double get _cellHPad => 1.8.w; -double get _colGap => 1.8.w; -double get _idColWidth => 8.w; -double get _nameColWidth => 20.w; -double get _versionColWidth => 12.w; -double get _registeredColWidth => 18.w; -double get _chevronColWidth => 4.w; -double get _tableMinWidth => 72.w; - -// ─── Helpers ────────────────────────────────────────────────────────────────── - -Color _accentColor(List bytes) { - final seed = bytes.fold(0, (v, b) => v + b); - final hue = (seed * 17) % 360; - return HSLColor.fromAHSL(1, hue.toDouble(), 0.68, 0.54).toColor(); -} - -// ed25519 public keys are always 32 bytes (64 hex chars); guard is defensive. -String _shortPubkey(List bytes) { - final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); - if (hex.length < 12) return '0x$hex'; - return '0x${hex.substring(0, 8)}...${hex.substring(hex.length - 4)}'; -} - -String _fullPubkey(List bytes) { - final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); - return '0x$hex'; -} - -String _formatDate(int unixSecs) { - final dt = DateTime.fromMillisecondsSinceEpoch(unixSecs * 1000).toLocal(); - return '${dt.year}-' - '${dt.month.toString().padLeft(2, '0')}-' - '${dt.day.toString().padLeft(2, '0')}'; -} - -String _formatError(Object error) { - final message = error.toString(); - if (message.startsWith('Exception: ')) { - return message.substring('Exception: '.length); - } - return message; -} - -// ─── Header ─────────────────────────────────────────────────────────────────── - -class _Header extends StatelessWidget { - const _Header({required this.isBusy, required this.onRefresh}); - - final bool isBusy; - final Future Function() onRefresh; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - return Container( - padding: EdgeInsets.symmetric(horizontal: 1.6.w, vertical: 1.2.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(18), - color: Palette.cream, - border: Border.all(color: Palette.line), - ), - child: Row( - children: [ - Expanded( - child: Text( - 'SDK Clients', - style: theme.textTheme.titleMedium?.copyWith( - color: Palette.ink, - fontWeight: FontWeight.w800, - ), - ), - ), - if (isBusy) ...[ - Text( - 'Syncing', - style: theme.textTheme.bodySmall?.copyWith( - color: Palette.ink.withValues(alpha: 0.62), - fontWeight: FontWeight.w700, - ), - ), - SizedBox(width: 1.w), - ], - OutlinedButton.icon( - onPressed: () => onRefresh(), - style: OutlinedButton.styleFrom( - foregroundColor: Palette.ink, - side: BorderSide(color: Palette.line), - padding: EdgeInsets.symmetric(horizontal: 1.4.w, vertical: 1.2.h), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(14), - ), - ), - icon: const Icon(Icons.refresh, size: 18), - label: const Text('Refresh'), - ), - ], - ), - ); - } -} - -// ─── Table header row ───────────────────────────────────────────────────────── - -class _ClientTableHeader extends StatelessWidget { - const _ClientTableHeader(); - - @override - Widget build(BuildContext context) { - final style = Theme.of(context).textTheme.labelLarge?.copyWith( - color: Palette.ink.withValues(alpha: 0.72), - fontWeight: FontWeight.w800, - letterSpacing: 0.3, - ); - - return Container( - padding: EdgeInsets.symmetric(vertical: 1.4.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), - color: Palette.ink.withValues(alpha: 0.04), - ), - child: Row( - children: [ - SizedBox(width: _accentStripWidth + _cellHPad), - SizedBox( - width: _idColWidth, - child: Text('ID', style: style), - ), - SizedBox(width: _colGap), - SizedBox( - width: _nameColWidth, - child: Text('Name', style: style), - ), - SizedBox(width: _colGap), - SizedBox( - width: _versionColWidth, - child: Text('Version', style: style), - ), - SizedBox(width: _colGap), - SizedBox( - width: _registeredColWidth, - child: Text('Registered', style: style), - ), - SizedBox(width: _colGap), - SizedBox(width: _chevronColWidth), - SizedBox(width: _cellHPad), - ], - ), - ); - } -} - -// ─── Table row (owns its own expand state) ──────────────────────────────────── - -class _ClientTableRow extends HookWidget { - const _ClientTableRow({required this.client}); - - final ua_sdk.Entry client; - - @override - Widget build(BuildContext context) { - final expanded = useState(false); - final accent = _accentColor(client.pubkey); - final theme = Theme.of(context); - final muted = Palette.ink.withValues(alpha: 0.62); - - final name = client.info.name.isEmpty ? '—' : client.info.name; - final version = client.info.version.isEmpty ? '—' : client.info.version; - final registered = _formatDate(client.createdAt); - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // ── Collapsed row ────────────────────────────────────────────────────── - GestureDetector( - onTap: () => expanded.value = !expanded.value, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(18), - color: accent.withValues(alpha: 0.10), - border: Border.all(color: accent.withValues(alpha: 0.28)), - ), - child: IntrinsicHeight( - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - width: _accentStripWidth, - decoration: BoxDecoration( - color: accent, - borderRadius: const BorderRadius.horizontal( - left: Radius.circular(18), - ), - ), - ), - Expanded( - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: _cellHPad, - vertical: 1.4.h, - ), - child: Row( - children: [ - SizedBox( - width: _idColWidth, - child: Text( - '${client.id}', - style: theme.textTheme.bodyLarge?.copyWith( - color: Palette.ink, - ), - ), - ), - SizedBox(width: _colGap), - SizedBox( - width: _nameColWidth, - child: Text( - name, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.bodyMedium?.copyWith( - color: Palette.ink, - ), - ), - ), - SizedBox(width: _colGap), - SizedBox( - width: _versionColWidth, - child: Text( - version, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.bodySmall?.copyWith( - color: muted, - ), - ), - ), - SizedBox(width: _colGap), - SizedBox( - width: _registeredColWidth, - child: Text( - registered, - style: theme.textTheme.bodySmall?.copyWith( - color: muted, - ), - ), - ), - SizedBox(width: _colGap), - SizedBox( - width: _chevronColWidth, - child: Icon( - expanded.value - ? Icons.expand_more - : Icons.chevron_right, - color: muted, - ), - ), - ], - ), - ), - ), - ], - ), - ), - ), - ), - // ── Expansion panel (AnimatedSize wraps only this section) ──────────── - AnimatedSize( - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, - child: expanded.value - ? Container( - margin: EdgeInsets.only(top: 0.6.h), - padding: EdgeInsets.symmetric( - horizontal: 1.6.w, - vertical: 1.4.h, - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(14), - color: accent.withValues(alpha: 0.06), - border: Border( - left: BorderSide(color: accent, width: 0.4.w), - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - client.info.description.isEmpty - ? 'No description provided.' - : client.info.description, - style: theme.textTheme.bodyMedium?.copyWith( - color: muted, - height: 1.5, - ), - ), - SizedBox(height: 1.h), - Row( - children: [ - Expanded( - child: Text( - _shortPubkey(client.pubkey), - style: theme.textTheme.bodySmall?.copyWith( - color: Palette.ink, - fontFamily: 'monospace', - ), - ), - ), - IconButton( - icon: const Icon(Icons.copy_rounded, size: 18), - color: muted, - onPressed: () async { - await Clipboard.setData( - ClipboardData(text: _fullPubkey(client.pubkey)), - ); - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('Public key copied.'), - behavior: SnackBarBehavior.floating, - ), - ); - }, - ), - FilledButton.tonal( - onPressed: () { - context.router.push( - ClientDetailsRoute(clientId: client.id), - ); - }, - child: const Text('Manage access'), - ), - ], - ), - ], - ), - ) - : const SizedBox.shrink(), - ), - ], - ); - } -} - -// ─── Table container ────────────────────────────────────────────────────────── - -class _ClientTable extends StatelessWidget { - const _ClientTable({required this.clients}); - - final List clients; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - return CreamFrame( - padding: EdgeInsets.all(2.h), - child: LayoutBuilder( - builder: (context, constraints) { - final tableWidth = math.max(_tableMinWidth, constraints.maxWidth); - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Registered clients', - style: theme.textTheme.titleLarge?.copyWith( - color: Palette.ink, - fontWeight: FontWeight.w800, - ), - ), - SizedBox(height: 0.6.h), - Text( - 'Every entry here has authenticated with Arbiter at least once.', - style: theme.textTheme.bodyMedium?.copyWith( - color: Palette.ink.withValues(alpha: 0.70), - height: 1.4, - ), - ), - SizedBox(height: 1.6.h), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: SizedBox( - width: tableWidth, - child: Column( - children: [ - const _ClientTableHeader(), - SizedBox(height: 1.h), - for (var i = 0; i < clients.length; i++) - Padding( - padding: EdgeInsets.only( - bottom: i == clients.length - 1 ? 0 : 1.h, - ), - child: _ClientTableRow(client: clients[i]), - ), - ], - ), - ), - ), - ], - ); - }, - ), - ); - } -} - -// ─── Screen ─────────────────────────────────────────────────────────────────── - -@RoutePage() -class ClientsScreen extends HookConsumerWidget { - const ClientsScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final clientsAsync = ref.watch(sdkClientsProvider); - final isConnected = - ref.watch(connectionManagerProvider).asData?.value != null; - - void showMessage(String message) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), - ); - } - - Future refresh() async { - try { - final future = ref.refresh(sdkClientsProvider.future); - await future; - } catch (error) { - showMessage(_formatError(error)); - } - } - - final clients = clientsAsync.asData?.value; - - final content = switch (clientsAsync) { - AsyncLoading() when clients == null => const StatePanel( - icon: Icons.hourglass_top, - title: 'Loading clients', - body: 'Pulling client registry from Arbiter.', - busy: true, - ), - AsyncError(:final error) => StatePanel( - icon: Icons.sync_problem, - title: 'Client registry unavailable', - body: _formatError(error), - actionLabel: 'Retry', - onAction: refresh, - ), - _ when !isConnected => StatePanel( - icon: Icons.portable_wifi_off, - title: 'No active server connection', - body: 'Reconnect to Arbiter to list SDK clients.', - actionLabel: 'Refresh', - onAction: refresh, - ), - _ when clients != null && clients.isEmpty => StatePanel( - icon: Icons.devices_other_outlined, - title: 'No clients yet', - body: 'SDK clients appear here once they register with Arbiter.', - actionLabel: 'Refresh', - onAction: refresh, - ), - _ => _ClientTable(clients: clients ?? const []), - }; - - return Scaffold( - body: SafeArea( - child: RefreshIndicator.adaptive( - color: Palette.ink, - backgroundColor: Colors.white, - onRefresh: refresh, - child: ListView( - physics: const BouncingScrollPhysics( - parent: AlwaysScrollableScrollPhysics(), - ), - padding: EdgeInsets.fromLTRB(2.4.w, 2.4.h, 2.4.w, 3.2.h), - children: [ - _Header(isBusy: clientsAsync.isLoading, onRefresh: refresh), - SizedBox(height: 1.8.h), - content, - ], - ), - ), - ), - ); - } -} +import 'dart:math' as math; + +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:arbiter/router.gr.dart'; +import 'package:arbiter/providers/sdk_clients/list.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:arbiter/widgets/cream_frame.dart'; +import 'package:arbiter/widgets/state_panel.dart'; +import 'package:sizer/sizer.dart'; + +// ─── Column width getters ───────────────────────────────────────────────────── + +double get _accentStripWidth => 0.8.w; +double get _cellHPad => 1.8.w; +double get _colGap => 1.8.w; +double get _idColWidth => 8.w; +double get _nameColWidth => 20.w; +double get _versionColWidth => 12.w; +double get _registeredColWidth => 18.w; +double get _chevronColWidth => 4.w; +double get _tableMinWidth => 72.w; + +// ─── Helpers ────────────────────────────────────────────────────────────────── + +Color _accentColor(List bytes) { + final seed = bytes.fold(0, (v, b) => v + b); + final hue = (seed * 17) % 360; + return HSLColor.fromAHSL(1, hue.toDouble(), 0.68, 0.54).toColor(); +} + +// ed25519 public keys are always 32 bytes (64 hex chars); guard is defensive. +String _shortPubkey(List bytes) { + final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); + if (hex.length < 12) return '0x$hex'; + return '0x${hex.substring(0, 8)}...${hex.substring(hex.length - 4)}'; +} + +String _fullPubkey(List bytes) { + final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); + return '0x$hex'; +} + +String _formatDate(int unixSecs) { + final dt = DateTime.fromMillisecondsSinceEpoch(unixSecs * 1000).toLocal(); + return '${dt.year}-' + '${dt.month.toString().padLeft(2, '0')}-' + '${dt.day.toString().padLeft(2, '0')}'; +} + +String _formatError(Object error) { + final message = error.toString(); + if (message.startsWith('Exception: ')) { + return message.substring('Exception: '.length); + } + return message; +} + +// ─── Header ─────────────────────────────────────────────────────────────────── + +class _Header extends StatelessWidget { + const _Header({required this.isBusy, required this.onRefresh}); + + final bool isBusy; + final Future Function() onRefresh; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Container( + padding: EdgeInsets.symmetric(horizontal: 1.6.w, vertical: 1.2.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(18), + color: Palette.cream, + border: Border.all(color: Palette.line), + ), + child: Row( + children: [ + Expanded( + child: Text( + 'SDK Clients', + style: theme.textTheme.titleMedium?.copyWith( + color: Palette.ink, + fontWeight: FontWeight.w800, + ), + ), + ), + if (isBusy) ...[ + Text( + 'Syncing', + style: theme.textTheme.bodySmall?.copyWith( + color: Palette.ink.withValues(alpha: 0.62), + fontWeight: FontWeight.w700, + ), + ), + SizedBox(width: 1.w), + ], + OutlinedButton.icon( + onPressed: () => onRefresh(), + style: OutlinedButton.styleFrom( + foregroundColor: Palette.ink, + side: BorderSide(color: Palette.line), + padding: EdgeInsets.symmetric(horizontal: 1.4.w, vertical: 1.2.h), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(14), + ), + ), + icon: const Icon(Icons.refresh, size: 18), + label: const Text('Refresh'), + ), + ], + ), + ); + } +} + +// ─── Table header row ───────────────────────────────────────────────────────── + +class _ClientTableHeader extends StatelessWidget { + const _ClientTableHeader(); + + @override + Widget build(BuildContext context) { + final style = Theme.of(context).textTheme.labelLarge?.copyWith( + color: Palette.ink.withValues(alpha: 0.72), + fontWeight: FontWeight.w800, + letterSpacing: 0.3, + ); + + return Container( + padding: EdgeInsets.symmetric(vertical: 1.4.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: Palette.ink.withValues(alpha: 0.04), + ), + child: Row( + children: [ + SizedBox(width: _accentStripWidth + _cellHPad), + SizedBox( + width: _idColWidth, + child: Text('ID', style: style), + ), + SizedBox(width: _colGap), + SizedBox( + width: _nameColWidth, + child: Text('Name', style: style), + ), + SizedBox(width: _colGap), + SizedBox( + width: _versionColWidth, + child: Text('Version', style: style), + ), + SizedBox(width: _colGap), + SizedBox( + width: _registeredColWidth, + child: Text('Registered', style: style), + ), + SizedBox(width: _colGap), + SizedBox(width: _chevronColWidth), + SizedBox(width: _cellHPad), + ], + ), + ); + } +} + +// ─── Table row (owns its own expand state) ──────────────────────────────────── + +class _ClientTableRow extends HookWidget { + const _ClientTableRow({required this.client}); + + final ua_sdk.Entry client; + + @override + Widget build(BuildContext context) { + final expanded = useState(false); + final accent = _accentColor(client.pubkey); + final theme = Theme.of(context); + final muted = Palette.ink.withValues(alpha: 0.62); + + final name = client.info.name.isEmpty ? '—' : client.info.name; + final version = client.info.version.isEmpty ? '—' : client.info.version; + final registered = _formatDate(client.createdAt); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // ── Collapsed row ────────────────────────────────────────────────────── + GestureDetector( + onTap: () => expanded.value = !expanded.value, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(18), + color: accent.withValues(alpha: 0.10), + border: Border.all(color: accent.withValues(alpha: 0.28)), + ), + child: IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + width: _accentStripWidth, + decoration: BoxDecoration( + color: accent, + borderRadius: const BorderRadius.horizontal( + left: Radius.circular(18), + ), + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: _cellHPad, + vertical: 1.4.h, + ), + child: Row( + children: [ + SizedBox( + width: _idColWidth, + child: Text( + '${client.id}', + style: theme.textTheme.bodyLarge?.copyWith( + color: Palette.ink, + ), + ), + ), + SizedBox(width: _colGap), + SizedBox( + width: _nameColWidth, + child: Text( + name, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodyMedium?.copyWith( + color: Palette.ink, + ), + ), + ), + SizedBox(width: _colGap), + SizedBox( + width: _versionColWidth, + child: Text( + version, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodySmall?.copyWith( + color: muted, + ), + ), + ), + SizedBox(width: _colGap), + SizedBox( + width: _registeredColWidth, + child: Text( + registered, + style: theme.textTheme.bodySmall?.copyWith( + color: muted, + ), + ), + ), + SizedBox(width: _colGap), + SizedBox( + width: _chevronColWidth, + child: Icon( + expanded.value + ? Icons.expand_more + : Icons.chevron_right, + color: muted, + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + // ── Expansion panel (AnimatedSize wraps only this section) ──────────── + AnimatedSize( + duration: const Duration(milliseconds: 200), + curve: Curves.easeInOut, + child: expanded.value + ? Container( + margin: EdgeInsets.only(top: 0.6.h), + padding: EdgeInsets.symmetric( + horizontal: 1.6.w, + vertical: 1.4.h, + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(14), + color: accent.withValues(alpha: 0.06), + border: Border( + left: BorderSide(color: accent, width: 0.4.w), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + client.info.description.isEmpty + ? 'No description provided.' + : client.info.description, + style: theme.textTheme.bodyMedium?.copyWith( + color: muted, + height: 1.5, + ), + ), + SizedBox(height: 1.h), + Row( + children: [ + Expanded( + child: Text( + _shortPubkey(client.pubkey), + style: theme.textTheme.bodySmall?.copyWith( + color: Palette.ink, + fontFamily: 'monospace', + ), + ), + ), + IconButton( + icon: const Icon(Icons.copy_rounded, size: 18), + color: muted, + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: _fullPubkey(client.pubkey)), + ); + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Public key copied.'), + behavior: SnackBarBehavior.floating, + ), + ); + }, + ), + FilledButton.tonal( + onPressed: () { + context.router.push( + ClientDetailsRoute(clientId: client.id), + ); + }, + child: const Text('Manage access'), + ), + ], + ), + ], + ), + ) + : const SizedBox.shrink(), + ), + ], + ); + } +} + +// ─── Table container ────────────────────────────────────────────────────────── + +class _ClientTable extends StatelessWidget { + const _ClientTable({required this.clients}); + + final List clients; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return CreamFrame( + padding: EdgeInsets.all(2.h), + child: LayoutBuilder( + builder: (context, constraints) { + final tableWidth = math.max(_tableMinWidth, constraints.maxWidth); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Registered clients', + style: theme.textTheme.titleLarge?.copyWith( + color: Palette.ink, + fontWeight: FontWeight.w800, + ), + ), + SizedBox(height: 0.6.h), + Text( + 'Every entry here has authenticated with Arbiter at least once.', + style: theme.textTheme.bodyMedium?.copyWith( + color: Palette.ink.withValues(alpha: 0.70), + height: 1.4, + ), + ), + SizedBox(height: 1.6.h), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SizedBox( + width: tableWidth, + child: Column( + children: [ + const _ClientTableHeader(), + SizedBox(height: 1.h), + for (var i = 0; i < clients.length; i++) + Padding( + padding: EdgeInsets.only( + bottom: i == clients.length - 1 ? 0 : 1.h, + ), + child: _ClientTableRow(client: clients[i]), + ), + ], + ), + ), + ), + ], + ); + }, + ), + ); + } +} + +// ─── Screen ─────────────────────────────────────────────────────────────────── + +@RoutePage() +class ClientsScreen extends HookConsumerWidget { + const ClientsScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final clientsAsync = ref.watch(sdkClientsProvider); + final isConnected = + ref.watch(connectionManagerProvider).asData?.value != null; + + void showMessage(String message) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), + ); + } + + Future refresh() async { + try { + final future = ref.refresh(sdkClientsProvider.future); + await future; + } catch (error) { + showMessage(_formatError(error)); + } + } + + final clients = clientsAsync.asData?.value; + + final content = switch (clientsAsync) { + AsyncLoading() when clients == null => const StatePanel( + icon: Icons.hourglass_top, + title: 'Loading clients', + body: 'Pulling client registry from Arbiter.', + busy: true, + ), + AsyncError(:final error) => StatePanel( + icon: Icons.sync_problem, + title: 'Client registry unavailable', + body: _formatError(error), + actionLabel: 'Retry', + onAction: refresh, + ), + _ when !isConnected => StatePanel( + icon: Icons.portable_wifi_off, + title: 'No active server connection', + body: 'Reconnect to Arbiter to list SDK clients.', + actionLabel: 'Refresh', + onAction: refresh, + ), + _ when clients != null && clients.isEmpty => StatePanel( + icon: Icons.devices_other_outlined, + title: 'No clients yet', + body: 'SDK clients appear here once they register with Arbiter.', + actionLabel: 'Refresh', + onAction: refresh, + ), + _ => _ClientTable(clients: clients ?? const []), + }; + + return Scaffold( + body: SafeArea( + child: RefreshIndicator.adaptive( + color: Palette.ink, + backgroundColor: Colors.white, + onRefresh: refresh, + child: ListView( + physics: const BouncingScrollPhysics( + parent: AlwaysScrollableScrollPhysics(), + ), + padding: EdgeInsets.fromLTRB(2.4.w, 2.4.h, 2.4.w, 3.2.h), + children: [ + _Header(isBusy: clientsAsync.isLoading, onRefresh: refresh), + SizedBox(height: 1.8.h), + content, + ], + ), + ), + ), + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/evm.dart b/useragent/lib/screens/dashboard/evm/evm.dart index 89bab30..f283f4c 100644 --- a/useragent/lib/screens/dashboard/evm/evm.dart +++ b/useragent/lib/screens/dashboard/evm/evm.dart @@ -1,100 +1,100 @@ -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/screens/dashboard/evm/wallets/header.dart'; -import 'package:arbiter/screens/dashboard/evm/wallets/table.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:arbiter/providers/evm/evm.dart'; -import 'package:arbiter/widgets/page_header.dart'; -import 'package:arbiter/widgets/state_panel.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -@RoutePage() -class EvmScreen extends HookConsumerWidget { - const EvmScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final evm = ref.watch(evmProvider); - - final wallets = evm.asData?.value; - final loadedWallets = wallets ?? const []; - - void showMessage(String message) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), - ); - } - - Future refreshWallets() async { - try { - await ref.read(evmProvider.notifier).refreshWallets(); - } catch (e) { - showMessage('Failed to refresh wallets: ${_formatError(e)}'); - } - } - - final content = switch (evm) { - AsyncLoading() when wallets == null => const StatePanel( - icon: Icons.hourglass_top, - title: 'Loading wallets', - body: 'Pulling wallet registry from Arbiter.', - busy: true, - ), - AsyncError(:final error) => StatePanel( - icon: Icons.sync_problem, - title: 'Wallet registry unavailable', - body: _formatError(error), - actionLabel: 'Retry', - onAction: refreshWallets, - ), - AsyncData(:final value) when value == null => StatePanel( - icon: Icons.portable_wifi_off, - title: 'No active server connection', - body: 'Reconnect to Arbiter to list or create EVM wallets.', - actionLabel: 'Refresh', - onAction: () => refreshWallets(), - ), - _ => WalletTable(wallets: loadedWallets), - }; - - return Scaffold( - body: SafeArea( - child: RefreshIndicator.adaptive( - color: Palette.ink, - backgroundColor: Colors.white, - onRefresh: refreshWallets, - child: ListView( - physics: const BouncingScrollPhysics( - parent: AlwaysScrollableScrollPhysics(), - ), - padding: EdgeInsets.fromLTRB(2.4.w, 2.4.h, 2.4.w, 3.2.h), - children: [ - PageHeader( - title: 'EVM Wallet Vault', - isBusy: evm.isLoading, - actions: [ - const CreateWalletButton(), - SizedBox(width: 1.w), - const RefreshWalletButton(), - ], - ), - SizedBox(height: 1.8.h), - content, - ], - ), - ), - ), - ); - } -} - -String _formatError(Object error) { - final message = error.toString(); - if (message.startsWith('Exception: ')) { - return message.substring('Exception: '.length); - } - return message; -} +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/screens/dashboard/evm/wallets/header.dart'; +import 'package:arbiter/screens/dashboard/evm/wallets/table.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:arbiter/providers/evm/evm.dart'; +import 'package:arbiter/widgets/page_header.dart'; +import 'package:arbiter/widgets/state_panel.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +@RoutePage() +class EvmScreen extends HookConsumerWidget { + const EvmScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final evm = ref.watch(evmProvider); + + final wallets = evm.asData?.value; + final loadedWallets = wallets ?? const []; + + void showMessage(String message) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), + ); + } + + Future refreshWallets() async { + try { + await ref.read(evmProvider.notifier).refreshWallets(); + } catch (e) { + showMessage('Failed to refresh wallets: ${_formatError(e)}'); + } + } + + final content = switch (evm) { + AsyncLoading() when wallets == null => const StatePanel( + icon: Icons.hourglass_top, + title: 'Loading wallets', + body: 'Pulling wallet registry from Arbiter.', + busy: true, + ), + AsyncError(:final error) => StatePanel( + icon: Icons.sync_problem, + title: 'Wallet registry unavailable', + body: _formatError(error), + actionLabel: 'Retry', + onAction: refreshWallets, + ), + AsyncData(:final value) when value == null => StatePanel( + icon: Icons.portable_wifi_off, + title: 'No active server connection', + body: 'Reconnect to Arbiter to list or create EVM wallets.', + actionLabel: 'Refresh', + onAction: () => refreshWallets(), + ), + _ => WalletTable(wallets: loadedWallets), + }; + + return Scaffold( + body: SafeArea( + child: RefreshIndicator.adaptive( + color: Palette.ink, + backgroundColor: Colors.white, + onRefresh: refreshWallets, + child: ListView( + physics: const BouncingScrollPhysics( + parent: AlwaysScrollableScrollPhysics(), + ), + padding: EdgeInsets.fromLTRB(2.4.w, 2.4.h, 2.4.w, 3.2.h), + children: [ + PageHeader( + title: 'EVM Wallet Vault', + isBusy: evm.isLoading, + actions: [ + const CreateWalletButton(), + SizedBox(width: 1.w), + const RefreshWalletButton(), + ], + ), + SizedBox(height: 1.8.h), + content, + ], + ), + ), + ), + ); + } +} + +String _formatError(Object error) { + final message = error.toString(); + if (message.startsWith('Exception: ')) { + return message.substring('Exception: '.length); + } + return message; +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/fields/chain_id_field.dart b/useragent/lib/screens/dashboard/evm/grants/create/fields/chain_id_field.dart index 8d2d318..67525f3 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/fields/chain_id_field.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/fields/chain_id_field.dart @@ -1,21 +1,21 @@ -// lib/screens/dashboard/evm/grants/create/fields/chain_id_field.dart -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; - -class ChainIdField extends StatelessWidget { - const ChainIdField({super.key}); - - @override - Widget build(BuildContext context) { - return FormBuilderTextField( - name: 'chainId', - initialValue: '1', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Chain ID', - hintText: '1', - border: OutlineInputBorder(), - ), - ); - } -} +// lib/screens/dashboard/evm/grants/create/fields/chain_id_field.dart +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; + +class ChainIdField extends StatelessWidget { + const ChainIdField({super.key}); + + @override + Widget build(BuildContext context) { + return FormBuilderTextField( + name: 'chainId', + initialValue: '1', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Chain ID', + hintText: '1', + border: OutlineInputBorder(), + ), + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/fields/client_picker_field.dart b/useragent/lib/screens/dashboard/evm/grants/create/fields/client_picker_field.dart index 6be82e5..455c319 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/fields/client_picker_field.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/fields/client_picker_field.dart @@ -1,40 +1,40 @@ -// lib/screens/dashboard/evm/grants/create/fields/client_picker_field.dart -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/providers/sdk_clients/list.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -class ClientPickerField extends ConsumerWidget { - const ClientPickerField({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final clients = - ref.watch(sdkClientsProvider).asData?.value ?? const []; - - return FormBuilderDropdown( - name: 'clientId', - decoration: const InputDecoration( - labelText: 'Client', - border: OutlineInputBorder(), - ), - items: [ - for (final c in clients) - DropdownMenuItem( - value: c.id, - child: Text(c.info.name.isEmpty ? 'Client #${c.id}' : c.info.name), - ), - ], - onChanged: clients.isEmpty - ? null - : (value) { - ref.read(grantCreationProvider.notifier).setClientId(value); - FormBuilder.of( - context, - )?.fields['walletAccessId']?.didChange(null); - }, - ); - } -} +// lib/screens/dashboard/evm/grants/create/fields/client_picker_field.dart +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/providers/sdk_clients/list.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +class ClientPickerField extends ConsumerWidget { + const ClientPickerField({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final clients = + ref.watch(sdkClientsProvider).asData?.value ?? const []; + + return FormBuilderDropdown( + name: 'clientId', + decoration: const InputDecoration( + labelText: 'Client', + border: OutlineInputBorder(), + ), + items: [ + for (final c in clients) + DropdownMenuItem( + value: c.id, + child: Text(c.info.name.isEmpty ? 'Client #${c.id}' : c.info.name), + ), + ], + onChanged: clients.isEmpty + ? null + : (value) { + ref.read(grantCreationProvider.notifier).setClientId(value); + FormBuilder.of( + context, + )?.fields['walletAccessId']?.didChange(null); + }, + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/fields/date_time_field.dart b/useragent/lib/screens/dashboard/evm/grants/create/fields/date_time_field.dart index 62d3ddb..673d8ec 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/fields/date_time_field.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/fields/date_time_field.dart @@ -1,63 +1,63 @@ -// lib/screens/dashboard/evm/grants/create/fields/date_time_field.dart -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:sizer/sizer.dart'; - -/// A [FormBuilderField] that opens a date picker followed by a time picker. -/// Long-press clears the value. -class FormBuilderDateTimeField extends FormBuilderField { - final String label; - - FormBuilderDateTimeField({ - super.key, - required super.name, - required this.label, - super.initialValue, - super.onChanged, - super.validator, - }) : super( - builder: (FormFieldState field) { - final value = field.value; - return OutlinedButton( - onPressed: () async { - final ctx = field.context; - final now = DateTime.now(); - final date = await showDatePicker( - context: ctx, - firstDate: DateTime(now.year - 5), - lastDate: DateTime(now.year + 10), - initialDate: value ?? now, - ); - if (date == null) return; - if (!ctx.mounted) return; - final time = await showTimePicker( - context: ctx, - initialTime: TimeOfDay.fromDateTime(value ?? now), - ); - if (time == null) return; - field.didChange( - DateTime( - date.year, - date.month, - date.day, - time.hour, - time.minute, - ), - ); - }, - onLongPress: value == null ? null : () => field.didChange(null), - child: Padding( - padding: EdgeInsets.symmetric(vertical: 1.8.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(label), - SizedBox(height: 0.6.h), - Text(value?.toLocal().toString() ?? 'Not set'), - ], - ), - ), - ); - }, - ); -} +// lib/screens/dashboard/evm/grants/create/fields/date_time_field.dart +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:sizer/sizer.dart'; + +/// A [FormBuilderField] that opens a date picker followed by a time picker. +/// Long-press clears the value. +class FormBuilderDateTimeField extends FormBuilderField { + final String label; + + FormBuilderDateTimeField({ + super.key, + required super.name, + required this.label, + super.initialValue, + super.onChanged, + super.validator, + }) : super( + builder: (FormFieldState field) { + final value = field.value; + return OutlinedButton( + onPressed: () async { + final ctx = field.context; + final now = DateTime.now(); + final date = await showDatePicker( + context: ctx, + firstDate: DateTime(now.year - 5), + lastDate: DateTime(now.year + 10), + initialDate: value ?? now, + ); + if (date == null) return; + if (!ctx.mounted) return; + final time = await showTimePicker( + context: ctx, + initialTime: TimeOfDay.fromDateTime(value ?? now), + ); + if (time == null) return; + field.didChange( + DateTime( + date.year, + date.month, + date.day, + time.hour, + time.minute, + ), + ); + }, + onLongPress: value == null ? null : () => field.didChange(null), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 1.8.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label), + SizedBox(height: 0.6.h), + Text(value?.toLocal().toString() ?? 'Not set'), + ], + ), + ), + ); + }, + ); +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart b/useragent/lib/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart index 86e3dd0..2039f33 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart @@ -1,39 +1,39 @@ -// lib/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:sizer/sizer.dart'; - -class GasFeeOptionsField extends StatelessWidget { - const GasFeeOptionsField({super.key}); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: FormBuilderTextField( - name: 'maxGasFeePerGas', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Max gas fee / gas', - hintText: '1000000000', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 1.w), - Expanded( - child: FormBuilderTextField( - name: 'maxPriorityFeePerGas', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Max priority fee / gas', - hintText: '100000000', - border: OutlineInputBorder(), - ), - ), - ), - ], - ); - } -} +// lib/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:sizer/sizer.dart'; + +class GasFeeOptionsField extends StatelessWidget { + const GasFeeOptionsField({super.key}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: FormBuilderTextField( + name: 'maxGasFeePerGas', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Max gas fee / gas', + hintText: '1000000000', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 1.w), + Expanded( + child: FormBuilderTextField( + name: 'maxPriorityFeePerGas', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Max priority fee / gas', + hintText: '100000000', + border: OutlineInputBorder(), + ), + ), + ), + ], + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart b/useragent/lib/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart index f63a1d8..a726e5a 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart @@ -1,39 +1,39 @@ -// lib/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:sizer/sizer.dart'; - -class TransactionRateLimitField extends StatelessWidget { - const TransactionRateLimitField({super.key}); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: FormBuilderTextField( - name: 'txCount', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Tx count limit', - hintText: '10', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 1.w), - Expanded( - child: FormBuilderTextField( - name: 'txWindow', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Window (seconds)', - hintText: '3600', - border: OutlineInputBorder(), - ), - ), - ), - ], - ); - } -} +// lib/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:sizer/sizer.dart'; + +class TransactionRateLimitField extends StatelessWidget { + const TransactionRateLimitField({super.key}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: FormBuilderTextField( + name: 'txCount', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Tx count limit', + hintText: '10', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 1.w), + Expanded( + child: FormBuilderTextField( + name: 'txWindow', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Window (seconds)', + hintText: '3600', + border: OutlineInputBorder(), + ), + ), + ), + ], + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/fields/validity_window_field.dart b/useragent/lib/screens/dashboard/evm/grants/create/fields/validity_window_field.dart index e86afda..6d2a9cb 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/fields/validity_window_field.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/fields/validity_window_field.dart @@ -1,29 +1,29 @@ -// lib/screens/dashboard/evm/grants/create/fields/validity_window_field.dart -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/date_time_field.dart'; -import 'package:flutter/material.dart'; -import 'package:sizer/sizer.dart'; - -class ValidityWindowField extends StatelessWidget { - const ValidityWindowField({super.key}); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: FormBuilderDateTimeField( - name: 'validFrom', - label: 'Valid from', - ), - ), - SizedBox(width: 1.w), - Expanded( - child: FormBuilderDateTimeField( - name: 'validUntil', - label: 'Valid until', - ), - ), - ], - ); - } -} +// lib/screens/dashboard/evm/grants/create/fields/validity_window_field.dart +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/date_time_field.dart'; +import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; + +class ValidityWindowField extends StatelessWidget { + const ValidityWindowField({super.key}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: FormBuilderDateTimeField( + name: 'validFrom', + label: 'Valid from', + ), + ), + SizedBox(width: 1.w), + Expanded( + child: FormBuilderDateTimeField( + name: 'validUntil', + label: 'Valid until', + ), + ), + ], + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart b/useragent/lib/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart index cde8d17..b7730a3 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart @@ -1,57 +1,57 @@ -// lib/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/providers/evm/evm.dart'; -import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -class WalletAccessPickerField extends ConsumerWidget { - const WalletAccessPickerField({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final state = ref.watch(grantCreationProvider); - final allAccesses = - ref.watch(walletAccessListProvider).asData?.value ?? - const []; - final wallets = - ref.watch(evmProvider).asData?.value ?? const []; - - final walletById = {for (final w in wallets) w.id: w}; - final accesses = state.selectedClientId == null - ? const [] - : allAccesses - .where((a) => a.access.sdkClientId == state.selectedClientId) - .toList(); - - return FormBuilderDropdown( - name: 'walletAccessId', - enabled: accesses.isNotEmpty, - decoration: InputDecoration( - labelText: 'Wallet access', - helperText: state.selectedClientId == null - ? 'Select a client first' - : accesses.isEmpty - ? 'No wallet accesses for this client' - : null, - border: const OutlineInputBorder(), - ), - items: [ - for (final a in accesses) - DropdownMenuItem( - value: a.id, - child: Text(() { - final wallet = walletById[a.access.walletId]; - return wallet != null - ? shortAddress(wallet.address) - : 'Wallet #${a.access.walletId}'; - }()), - ), - ], - ); - } -} +// lib/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/providers/evm/evm.dart'; +import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +class WalletAccessPickerField extends ConsumerWidget { + const WalletAccessPickerField({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final state = ref.watch(grantCreationProvider); + final allAccesses = + ref.watch(walletAccessListProvider).asData?.value ?? + const []; + final wallets = + ref.watch(evmProvider).asData?.value ?? const []; + + final walletById = {for (final w in wallets) w.id: w}; + final accesses = state.selectedClientId == null + ? const [] + : allAccesses + .where((a) => a.access.sdkClientId == state.selectedClientId) + .toList(); + + return FormBuilderDropdown( + name: 'walletAccessId', + enabled: accesses.isNotEmpty, + decoration: InputDecoration( + labelText: 'Wallet access', + helperText: state.selectedClientId == null + ? 'Select a client first' + : accesses.isEmpty + ? 'No wallet accesses for this client' + : null, + border: const OutlineInputBorder(), + ), + items: [ + for (final a in accesses) + DropdownMenuItem( + value: a.id, + child: Text(() { + final wallet = walletById[a.access.walletId]; + return wallet != null + ? shortAddress(wallet.address) + : 'Wallet #${a.access.walletId}'; + }()), + ), + ], + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart b/useragent/lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart index bc7bda6..944fea0 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart @@ -1,225 +1,225 @@ -// lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:sizer/sizer.dart'; - -part 'ether_transfer_grant.g.dart'; - -class EtherTargetEntry { - EtherTargetEntry({required this.id, this.address = ''}); - - final int id; - final String address; - - EtherTargetEntry copyWith({String? address}) => - EtherTargetEntry(id: id, address: address ?? this.address); -} - -@riverpod -class EtherGrantTargets extends _$EtherGrantTargets { - int _nextId = 0; - int _newId() => _nextId++; - - @override - List build() => [EtherTargetEntry(id: _newId())]; - - void add() => state = [...state, EtherTargetEntry(id: _newId())]; - - void update(int index, EtherTargetEntry entry) { - final updated = [...state]; - updated[index] = entry; - state = updated; - } - - void remove(int index) => state = [...state]..removeAt(index); -} - -class EtherTransferGrantHandler implements GrantFormHandler { - const EtherTransferGrantHandler(); - - @override - Widget buildForm(BuildContext context, WidgetRef ref) => - const _EtherTransferForm(); - - @override - SpecificGrant buildSpecificGrant( - Map formValues, - WidgetRef ref, - ) { - final targets = ref.read(etherGrantTargetsProvider); - - return SpecificGrant( - etherTransfer: EtherTransferSettings( - targets: targets - .where((e) => e.address.trim().isNotEmpty) - .map((e) => parseHexAddress(e.address)) - .toList(), - limit: buildVolumeLimit( - formValues['etherVolume'] as String? ?? '', - formValues['etherVolumeWindow'] as String? ?? '', - ), - ), - ); - } -} - -// --------------------------------------------------------------------------- -// Form widget -// --------------------------------------------------------------------------- - -class _EtherTransferForm extends ConsumerWidget { - const _EtherTransferForm(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final targets = ref.watch(etherGrantTargetsProvider); - final notifier = ref.read(etherGrantTargetsProvider.notifier); - - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - _EtherTargetsField( - values: targets, - onAdd: notifier.add, - onUpdate: notifier.update, - onRemove: notifier.remove, - ), - SizedBox(height: 1.6.h), - Text( - 'Ether volume limit', - style: Theme.of( - context, - ).textTheme.labelLarge?.copyWith(fontWeight: FontWeight.w800), - ), - SizedBox(height: 0.8.h), - Row( - children: [ - Expanded( - child: FormBuilderTextField( - name: 'etherVolume', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Max volume', - hintText: '1000000000000000000', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 1.w), - Expanded( - child: FormBuilderTextField( - name: 'etherVolumeWindow', - keyboardType: TextInputType.number, - decoration: const InputDecoration( - labelText: 'Window (seconds)', - hintText: '86400', - border: OutlineInputBorder(), - ), - ), - ), - ], - ), - ], - ); - } -} - -// --------------------------------------------------------------------------- -// Targets list widget -// --------------------------------------------------------------------------- - -class _EtherTargetsField extends StatelessWidget { - const _EtherTargetsField({ - required this.values, - required this.onAdd, - required this.onUpdate, - required this.onRemove, - }); - - final List values; - final VoidCallback onAdd; - final void Function(int index, EtherTargetEntry entry) onUpdate; - final void Function(int index) onRemove; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Text( - 'Ether targets', - style: Theme.of( - context, - ).textTheme.labelLarge?.copyWith(fontWeight: FontWeight.w800), - ), - ), - TextButton.icon( - onPressed: onAdd, - icon: const Icon(Icons.add_rounded), - label: const Text('Add'), - ), - ], - ), - SizedBox(height: 0.8.h), - for (var i = 0; i < values.length; i++) - Padding( - padding: EdgeInsets.only(bottom: 1.h), - child: _EtherTargetRow( - key: ValueKey(values[i].id), - value: values[i], - onChanged: (entry) => onUpdate(i, entry), - onRemove: values.length == 1 ? null : () => onRemove(i), - ), - ), - ], - ); - } -} - -class _EtherTargetRow extends HookWidget { - const _EtherTargetRow({ - super.key, - required this.value, - required this.onChanged, - required this.onRemove, - }); - - final EtherTargetEntry value; - final ValueChanged onChanged; - final VoidCallback? onRemove; - - @override - Widget build(BuildContext context) { - final addressController = useTextEditingController(text: value.address); - - return Row( - children: [ - Expanded( - child: TextField( - controller: addressController, - onChanged: (next) => onChanged(value.copyWith(address: next)), - decoration: const InputDecoration( - labelText: 'Address', - hintText: '0x...', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 0.4.w), - IconButton( - onPressed: onRemove, - icon: const Icon(Icons.remove_circle_outline_rounded), - ), - ], - ); - } -} +// lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:sizer/sizer.dart'; + +part 'ether_transfer_grant.g.dart'; + +class EtherTargetEntry { + EtherTargetEntry({required this.id, this.address = ''}); + + final int id; + final String address; + + EtherTargetEntry copyWith({String? address}) => + EtherTargetEntry(id: id, address: address ?? this.address); +} + +@riverpod +class EtherGrantTargets extends _$EtherGrantTargets { + int _nextId = 0; + int _newId() => _nextId++; + + @override + List build() => [EtherTargetEntry(id: _newId())]; + + void add() => state = [...state, EtherTargetEntry(id: _newId())]; + + void update(int index, EtherTargetEntry entry) { + final updated = [...state]; + updated[index] = entry; + state = updated; + } + + void remove(int index) => state = [...state]..removeAt(index); +} + +class EtherTransferGrantHandler implements GrantFormHandler { + const EtherTransferGrantHandler(); + + @override + Widget buildForm(BuildContext context, WidgetRef ref) => + const _EtherTransferForm(); + + @override + SpecificGrant buildSpecificGrant( + Map formValues, + WidgetRef ref, + ) { + final targets = ref.read(etherGrantTargetsProvider); + + return SpecificGrant( + etherTransfer: EtherTransferSettings( + targets: targets + .where((e) => e.address.trim().isNotEmpty) + .map((e) => parseHexAddress(e.address)) + .toList(), + limit: buildVolumeLimit( + formValues['etherVolume'] as String? ?? '', + formValues['etherVolumeWindow'] as String? ?? '', + ), + ), + ); + } +} + +// --------------------------------------------------------------------------- +// Form widget +// --------------------------------------------------------------------------- + +class _EtherTransferForm extends ConsumerWidget { + const _EtherTransferForm(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final targets = ref.watch(etherGrantTargetsProvider); + final notifier = ref.read(etherGrantTargetsProvider.notifier); + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _EtherTargetsField( + values: targets, + onAdd: notifier.add, + onUpdate: notifier.update, + onRemove: notifier.remove, + ), + SizedBox(height: 1.6.h), + Text( + 'Ether volume limit', + style: Theme.of( + context, + ).textTheme.labelLarge?.copyWith(fontWeight: FontWeight.w800), + ), + SizedBox(height: 0.8.h), + Row( + children: [ + Expanded( + child: FormBuilderTextField( + name: 'etherVolume', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Max volume', + hintText: '1000000000000000000', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 1.w), + Expanded( + child: FormBuilderTextField( + name: 'etherVolumeWindow', + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Window (seconds)', + hintText: '86400', + border: OutlineInputBorder(), + ), + ), + ), + ], + ), + ], + ); + } +} + +// --------------------------------------------------------------------------- +// Targets list widget +// --------------------------------------------------------------------------- + +class _EtherTargetsField extends StatelessWidget { + const _EtherTargetsField({ + required this.values, + required this.onAdd, + required this.onUpdate, + required this.onRemove, + }); + + final List values; + final VoidCallback onAdd; + final void Function(int index, EtherTargetEntry entry) onUpdate; + final void Function(int index) onRemove; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + 'Ether targets', + style: Theme.of( + context, + ).textTheme.labelLarge?.copyWith(fontWeight: FontWeight.w800), + ), + ), + TextButton.icon( + onPressed: onAdd, + icon: const Icon(Icons.add_rounded), + label: const Text('Add'), + ), + ], + ), + SizedBox(height: 0.8.h), + for (var i = 0; i < values.length; i++) + Padding( + padding: EdgeInsets.only(bottom: 1.h), + child: _EtherTargetRow( + key: ValueKey(values[i].id), + value: values[i], + onChanged: (entry) => onUpdate(i, entry), + onRemove: values.length == 1 ? null : () => onRemove(i), + ), + ), + ], + ); + } +} + +class _EtherTargetRow extends HookWidget { + const _EtherTargetRow({ + super.key, + required this.value, + required this.onChanged, + required this.onRemove, + }); + + final EtherTargetEntry value; + final ValueChanged onChanged; + final VoidCallback? onRemove; + + @override + Widget build(BuildContext context) { + final addressController = useTextEditingController(text: value.address); + + return Row( + children: [ + Expanded( + child: TextField( + controller: addressController, + onChanged: (next) => onChanged(value.copyWith(address: next)), + decoration: const InputDecoration( + labelText: 'Address', + hintText: '0x...', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 0.4.w), + IconButton( + onPressed: onRemove, + icon: const Icon(Icons.remove_circle_outline_rounded), + ), + ], + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.g.dart b/useragent/lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.g.dart index 420340a..f0d5c56 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.g.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.g.dart @@ -1,63 +1,63 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'ether_transfer_grant.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(EtherGrantTargets) -final etherGrantTargetsProvider = EtherGrantTargetsProvider._(); - -final class EtherGrantTargetsProvider - extends $NotifierProvider> { - EtherGrantTargetsProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'etherGrantTargetsProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$etherGrantTargetsHash(); - - @$internal - @override - EtherGrantTargets create() => EtherGrantTargets(); - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(List value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider>(value), - ); - } -} - -String _$etherGrantTargetsHash() => r'063aa3180d5e5bbc1525702272686f1fd8ca751d'; - -abstract class _$EtherGrantTargets extends $Notifier> { - List build(); - @$mustCallSuper - @override - void runBuild() { - final ref = - this.ref as $Ref, List>; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, List>, - List, - Object?, - Object? - >; - element.handleCreate(ref, build); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ether_transfer_grant.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(EtherGrantTargets) +final etherGrantTargetsProvider = EtherGrantTargetsProvider._(); + +final class EtherGrantTargetsProvider + extends $NotifierProvider> { + EtherGrantTargetsProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'etherGrantTargetsProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$etherGrantTargetsHash(); + + @$internal + @override + EtherGrantTargets create() => EtherGrantTargets(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(List value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider>(value), + ); + } +} + +String _$etherGrantTargetsHash() => r'063aa3180d5e5bbc1525702272686f1fd8ca751d'; + +abstract class _$EtherGrantTargets extends $Notifier> { + List build(); + @$mustCallSuper + @override + void runBuild() { + final ref = + this.ref as $Ref, List>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, List>, + List, + Object?, + Object? + >; + element.handleCreate(ref, build); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart b/useragent/lib/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart index 542f2b3..63ae68c 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart @@ -1,26 +1,26 @@ -// lib/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:flutter/widgets.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -abstract class GrantFormHandler { - /// Renders the grant-specific form section. - /// - /// The returned widget must be a descendant of the [FormBuilder] in the - /// screen so its [FormBuilderField] children register automatically. - /// - /// **Field name contract:** All `name:` values used by this handler must be - /// unique across ALL [GrantFormHandler] implementations. [FormBuilder] - /// retains field state across handler switches, so name collisions cause - /// silent data corruption. - Widget buildForm(BuildContext context, WidgetRef ref); - - /// Assembles a [SpecificGrant] proto. - /// - /// [formValues] — `formKey.currentState!.value` after `saveAndValidate()`. - /// [ref] — read any provider the handler owns (e.g. token volume limits). - SpecificGrant buildSpecificGrant( - Map formValues, - WidgetRef ref, - ); -} +// lib/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:flutter/widgets.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +abstract class GrantFormHandler { + /// Renders the grant-specific form section. + /// + /// The returned widget must be a descendant of the [FormBuilder] in the + /// screen so its [FormBuilderField] children register automatically. + /// + /// **Field name contract:** All `name:` values used by this handler must be + /// unique across ALL [GrantFormHandler] implementations. [FormBuilder] + /// retains field state across handler switches, so name collisions cause + /// silent data corruption. + Widget buildForm(BuildContext context, WidgetRef ref); + + /// Assembles a [SpecificGrant] proto. + /// + /// [formValues] — `formKey.currentState!.value` after `saveAndValidate()`. + /// [ref] — read any provider the handler owns (e.g. token volume limits). + SpecificGrant buildSpecificGrant( + Map formValues, + WidgetRef ref, + ); +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart b/useragent/lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart index 58e27de..b32a677 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart @@ -1,241 +1,241 @@ -// lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; -import 'package:fixnum/fixnum.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:sizer/sizer.dart'; - -part 'token_transfer_grant.g.dart'; - -class VolumeLimitEntry { - VolumeLimitEntry({ - required this.id, - this.amount = '', - this.windowSeconds = '', - }); - - final int id; - final String amount; - final String windowSeconds; - - VolumeLimitEntry copyWith({String? amount, String? windowSeconds}) => - VolumeLimitEntry( - id: id, - amount: amount ?? this.amount, - windowSeconds: windowSeconds ?? this.windowSeconds, - ); -} - -@riverpod -class TokenGrantLimits extends _$TokenGrantLimits { - int _nextId = 0; - int _newId() => _nextId++; - - @override - List build() => [VolumeLimitEntry(id: _newId())]; - - void add() => state = [...state, VolumeLimitEntry(id: _newId())]; - - void update(int index, VolumeLimitEntry entry) { - final updated = [...state]; - updated[index] = entry; - state = updated; - } - - void remove(int index) => state = [...state]..removeAt(index); -} - -class TokenTransferGrantHandler implements GrantFormHandler { - const TokenTransferGrantHandler(); - - @override - Widget buildForm(BuildContext context, WidgetRef ref) => - const _TokenTransferForm(); - - @override - SpecificGrant buildSpecificGrant( - Map formValues, - WidgetRef ref, - ) { - final limits = ref.read(tokenGrantLimitsProvider); - final targetText = formValues['tokenTarget'] as String? ?? ''; - - return SpecificGrant( - tokenTransfer: TokenTransferSettings( - tokenContract: parseHexAddress( - formValues['tokenContract'] as String? ?? '', - ), - target: targetText.trim().isEmpty ? null : parseHexAddress(targetText), - volumeLimits: limits - .where( - (e) => - e.amount.trim().isNotEmpty && - e.windowSeconds.trim().isNotEmpty, - ) - .map( - (e) => VolumeRateLimit( - maxVolume: parseBigIntBytes(e.amount), - windowSecs: Int64.parseInt(e.windowSeconds), - ), - ) - .toList(), - ), - ); - } -} - -// --------------------------------------------------------------------------- -// Form widget -// --------------------------------------------------------------------------- - -class _TokenTransferForm extends ConsumerWidget { - const _TokenTransferForm(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final limits = ref.watch(tokenGrantLimitsProvider); - final notifier = ref.read(tokenGrantLimitsProvider.notifier); - - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - FormBuilderTextField( - name: 'tokenContract', - decoration: const InputDecoration( - labelText: 'Token contract', - hintText: '0x...', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 1.6.h), - FormBuilderTextField( - name: 'tokenTarget', - decoration: const InputDecoration( - labelText: 'Token recipient', - hintText: '0x... or leave empty for any recipient', - border: OutlineInputBorder(), - ), - ), - SizedBox(height: 1.6.h), - _TokenVolumeLimitsField( - values: limits, - onAdd: notifier.add, - onUpdate: notifier.update, - onRemove: notifier.remove, - ), - ], - ); - } -} - -// --------------------------------------------------------------------------- -// Volume limits list widget -// --------------------------------------------------------------------------- - -class _TokenVolumeLimitsField extends StatelessWidget { - const _TokenVolumeLimitsField({ - required this.values, - required this.onAdd, - required this.onUpdate, - required this.onRemove, - }); - - final List values; - final VoidCallback onAdd; - final void Function(int index, VolumeLimitEntry entry) onUpdate; - final void Function(int index) onRemove; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: Text( - 'Token volume limits', - style: Theme.of( - context, - ).textTheme.labelLarge?.copyWith(fontWeight: FontWeight.w800), - ), - ), - TextButton.icon( - onPressed: onAdd, - icon: const Icon(Icons.add_rounded), - label: const Text('Add'), - ), - ], - ), - SizedBox(height: 0.8.h), - for (var i = 0; i < values.length; i++) - Padding( - padding: EdgeInsets.only(bottom: 1.h), - child: _TokenVolumeLimitRow( - key: ValueKey(values[i].id), - value: values[i], - onChanged: (entry) => onUpdate(i, entry), - onRemove: values.length == 1 ? null : () => onRemove(i), - ), - ), - ], - ); - } -} - -class _TokenVolumeLimitRow extends HookWidget { - const _TokenVolumeLimitRow({ - super.key, - required this.value, - required this.onChanged, - required this.onRemove, - }); - - final VolumeLimitEntry value; - final ValueChanged onChanged; - final VoidCallback? onRemove; - - @override - Widget build(BuildContext context) { - final amountController = useTextEditingController(text: value.amount); - final windowController = useTextEditingController( - text: value.windowSeconds, - ); - - return Row( - children: [ - Expanded( - child: TextField( - controller: amountController, - onChanged: (next) => onChanged(value.copyWith(amount: next)), - decoration: const InputDecoration( - labelText: 'Max volume', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 1.w), - Expanded( - child: TextField( - controller: windowController, - onChanged: (next) => onChanged(value.copyWith(windowSeconds: next)), - decoration: const InputDecoration( - labelText: 'Window (seconds)', - border: OutlineInputBorder(), - ), - ), - ), - SizedBox(width: 0.4.w), - IconButton( - onPressed: onRemove, - icon: const Icon(Icons.remove_circle_outline_rounded), - ), - ], - ); - } -} +// lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; +import 'package:fixnum/fixnum.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:sizer/sizer.dart'; + +part 'token_transfer_grant.g.dart'; + +class VolumeLimitEntry { + VolumeLimitEntry({ + required this.id, + this.amount = '', + this.windowSeconds = '', + }); + + final int id; + final String amount; + final String windowSeconds; + + VolumeLimitEntry copyWith({String? amount, String? windowSeconds}) => + VolumeLimitEntry( + id: id, + amount: amount ?? this.amount, + windowSeconds: windowSeconds ?? this.windowSeconds, + ); +} + +@riverpod +class TokenGrantLimits extends _$TokenGrantLimits { + int _nextId = 0; + int _newId() => _nextId++; + + @override + List build() => [VolumeLimitEntry(id: _newId())]; + + void add() => state = [...state, VolumeLimitEntry(id: _newId())]; + + void update(int index, VolumeLimitEntry entry) { + final updated = [...state]; + updated[index] = entry; + state = updated; + } + + void remove(int index) => state = [...state]..removeAt(index); +} + +class TokenTransferGrantHandler implements GrantFormHandler { + const TokenTransferGrantHandler(); + + @override + Widget buildForm(BuildContext context, WidgetRef ref) => + const _TokenTransferForm(); + + @override + SpecificGrant buildSpecificGrant( + Map formValues, + WidgetRef ref, + ) { + final limits = ref.read(tokenGrantLimitsProvider); + final targetText = formValues['tokenTarget'] as String? ?? ''; + + return SpecificGrant( + tokenTransfer: TokenTransferSettings( + tokenContract: parseHexAddress( + formValues['tokenContract'] as String? ?? '', + ), + target: targetText.trim().isEmpty ? null : parseHexAddress(targetText), + volumeLimits: limits + .where( + (e) => + e.amount.trim().isNotEmpty && + e.windowSeconds.trim().isNotEmpty, + ) + .map( + (e) => VolumeRateLimit( + maxVolume: parseBigIntBytes(e.amount), + windowSecs: Int64.parseInt(e.windowSeconds), + ), + ) + .toList(), + ), + ); + } +} + +// --------------------------------------------------------------------------- +// Form widget +// --------------------------------------------------------------------------- + +class _TokenTransferForm extends ConsumerWidget { + const _TokenTransferForm(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final limits = ref.watch(tokenGrantLimitsProvider); + final notifier = ref.read(tokenGrantLimitsProvider.notifier); + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + FormBuilderTextField( + name: 'tokenContract', + decoration: const InputDecoration( + labelText: 'Token contract', + hintText: '0x...', + border: OutlineInputBorder(), + ), + ), + SizedBox(height: 1.6.h), + FormBuilderTextField( + name: 'tokenTarget', + decoration: const InputDecoration( + labelText: 'Token recipient', + hintText: '0x... or leave empty for any recipient', + border: OutlineInputBorder(), + ), + ), + SizedBox(height: 1.6.h), + _TokenVolumeLimitsField( + values: limits, + onAdd: notifier.add, + onUpdate: notifier.update, + onRemove: notifier.remove, + ), + ], + ); + } +} + +// --------------------------------------------------------------------------- +// Volume limits list widget +// --------------------------------------------------------------------------- + +class _TokenVolumeLimitsField extends StatelessWidget { + const _TokenVolumeLimitsField({ + required this.values, + required this.onAdd, + required this.onUpdate, + required this.onRemove, + }); + + final List values; + final VoidCallback onAdd; + final void Function(int index, VolumeLimitEntry entry) onUpdate; + final void Function(int index) onRemove; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + 'Token volume limits', + style: Theme.of( + context, + ).textTheme.labelLarge?.copyWith(fontWeight: FontWeight.w800), + ), + ), + TextButton.icon( + onPressed: onAdd, + icon: const Icon(Icons.add_rounded), + label: const Text('Add'), + ), + ], + ), + SizedBox(height: 0.8.h), + for (var i = 0; i < values.length; i++) + Padding( + padding: EdgeInsets.only(bottom: 1.h), + child: _TokenVolumeLimitRow( + key: ValueKey(values[i].id), + value: values[i], + onChanged: (entry) => onUpdate(i, entry), + onRemove: values.length == 1 ? null : () => onRemove(i), + ), + ), + ], + ); + } +} + +class _TokenVolumeLimitRow extends HookWidget { + const _TokenVolumeLimitRow({ + super.key, + required this.value, + required this.onChanged, + required this.onRemove, + }); + + final VolumeLimitEntry value; + final ValueChanged onChanged; + final VoidCallback? onRemove; + + @override + Widget build(BuildContext context) { + final amountController = useTextEditingController(text: value.amount); + final windowController = useTextEditingController( + text: value.windowSeconds, + ); + + return Row( + children: [ + Expanded( + child: TextField( + controller: amountController, + onChanged: (next) => onChanged(value.copyWith(amount: next)), + decoration: const InputDecoration( + labelText: 'Max volume', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 1.w), + Expanded( + child: TextField( + controller: windowController, + onChanged: (next) => onChanged(value.copyWith(windowSeconds: next)), + decoration: const InputDecoration( + labelText: 'Window (seconds)', + border: OutlineInputBorder(), + ), + ), + ), + SizedBox(width: 0.4.w), + IconButton( + onPressed: onRemove, + icon: const Icon(Icons.remove_circle_outline_rounded), + ), + ], + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.g.dart b/useragent/lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.g.dart index e3e7bd9..663fd05 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.g.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/grants/token_transfer_grant.g.dart @@ -1,63 +1,63 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'token_transfer_grant.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(TokenGrantLimits) -final tokenGrantLimitsProvider = TokenGrantLimitsProvider._(); - -final class TokenGrantLimitsProvider - extends $NotifierProvider> { - TokenGrantLimitsProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'tokenGrantLimitsProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$tokenGrantLimitsHash(); - - @$internal - @override - TokenGrantLimits create() => TokenGrantLimits(); - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(List value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider>(value), - ); - } -} - -String _$tokenGrantLimitsHash() => r'84db377f24940d215af82052e27863ab40c02b24'; - -abstract class _$TokenGrantLimits extends $Notifier> { - List build(); - @$mustCallSuper - @override - void runBuild() { - final ref = - this.ref as $Ref, List>; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, List>, - List, - Object?, - Object? - >; - element.handleCreate(ref, build); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'token_transfer_grant.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(TokenGrantLimits) +final tokenGrantLimitsProvider = TokenGrantLimitsProvider._(); + +final class TokenGrantLimitsProvider + extends $NotifierProvider> { + TokenGrantLimitsProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'tokenGrantLimitsProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$tokenGrantLimitsHash(); + + @$internal + @override + TokenGrantLimits create() => TokenGrantLimits(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(List value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider>(value), + ); + } +} + +String _$tokenGrantLimitsHash() => r'84db377f24940d215af82052e27863ab40c02b24'; + +abstract class _$TokenGrantLimits extends $Notifier> { + List build(); + @$mustCallSuper + @override + void runBuild() { + final ref = + this.ref as $Ref, List>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, List>, + List, + Object?, + Object? + >; + element.handleCreate(ref, build); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/provider.dart b/useragent/lib/screens/dashboard/evm/grants/create/provider.dart index 89aefeb..3ac0466 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/provider.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/provider.dart @@ -1,24 +1,24 @@ -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'provider.freezed.dart'; -part 'provider.g.dart'; - -@freezed -abstract class GrantCreationState with _$GrantCreationState { - const factory GrantCreationState({ - int? selectedClientId, - @Default(SpecificGrant_Grant.etherTransfer) SpecificGrant_Grant grantType, - }) = _GrantCreationState; -} - -@riverpod -class GrantCreation extends _$GrantCreation { - @override - GrantCreationState build() => const GrantCreationState(); - - void setClientId(int? id) => state = state.copyWith(selectedClientId: id); - void setGrantType(SpecificGrant_Grant type) => - state = state.copyWith(grantType: type); -} +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'provider.freezed.dart'; +part 'provider.g.dart'; + +@freezed +abstract class GrantCreationState with _$GrantCreationState { + const factory GrantCreationState({ + int? selectedClientId, + @Default(SpecificGrant_Grant.etherTransfer) SpecificGrant_Grant grantType, + }) = _GrantCreationState; +} + +@riverpod +class GrantCreation extends _$GrantCreation { + @override + GrantCreationState build() => const GrantCreationState(); + + void setClientId(int? id) => state = state.copyWith(selectedClientId: id); + void setGrantType(SpecificGrant_Grant type) => + state = state.copyWith(grantType: type); +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/provider.freezed.dart b/useragent/lib/screens/dashboard/evm/grants/create/provider.freezed.dart index e16d346..f45db33 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/provider.freezed.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/provider.freezed.dart @@ -1,274 +1,274 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND -// coverage:ignore-file -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'provider.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -// dart format off -T _$identity(T value) => value; -/// @nodoc -mixin _$GrantCreationState { - - int? get selectedClientId; SpecificGrant_Grant get grantType; -/// Create a copy of GrantCreationState -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$GrantCreationStateCopyWith get copyWith => _$GrantCreationStateCopyWithImpl(this as GrantCreationState, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is GrantCreationState&&(identical(other.selectedClientId, selectedClientId) || other.selectedClientId == selectedClientId)&&(identical(other.grantType, grantType) || other.grantType == grantType)); -} - - -@override -int get hashCode => Object.hash(runtimeType,selectedClientId,grantType); - -@override -String toString() { - return 'GrantCreationState(selectedClientId: $selectedClientId, grantType: $grantType)'; -} - - -} - -/// @nodoc -abstract mixin class $GrantCreationStateCopyWith<$Res> { - factory $GrantCreationStateCopyWith(GrantCreationState value, $Res Function(GrantCreationState) _then) = _$GrantCreationStateCopyWithImpl; -@useResult -$Res call({ - int? selectedClientId, SpecificGrant_Grant grantType -}); - - - - -} -/// @nodoc -class _$GrantCreationStateCopyWithImpl<$Res> - implements $GrantCreationStateCopyWith<$Res> { - _$GrantCreationStateCopyWithImpl(this._self, this._then); - - final GrantCreationState _self; - final $Res Function(GrantCreationState) _then; - -/// Create a copy of GrantCreationState -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? selectedClientId = freezed,Object? grantType = null,}) { - return _then(_self.copyWith( -selectedClientId: freezed == selectedClientId ? _self.selectedClientId : selectedClientId // ignore: cast_nullable_to_non_nullable -as int?,grantType: null == grantType ? _self.grantType : grantType // ignore: cast_nullable_to_non_nullable -as SpecificGrant_Grant, - )); -} - -} - - -/// Adds pattern-matching-related methods to [GrantCreationState]. -extension GrantCreationStatePatterns on GrantCreationState { -/// A variant of `map` that fallback to returning `orElse`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeMap(TResult Function( _GrantCreationState value)? $default,{required TResult orElse(),}){ -final _that = this; -switch (_that) { -case _GrantCreationState() when $default != null: -return $default(_that);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// Callbacks receives the raw object, upcasted. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case final Subclass2 value: -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult map(TResult Function( _GrantCreationState value) $default,){ -final _that = this; -switch (_that) { -case _GrantCreationState(): -return $default(_that);case _: - throw StateError('Unexpected subclass'); - -} -} -/// A variant of `map` that fallback to returning `null`. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case final Subclass value: -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? mapOrNull(TResult? Function( _GrantCreationState value)? $default,){ -final _that = this; -switch (_that) { -case _GrantCreationState() when $default != null: -return $default(_that);case _: - return null; - -} -} -/// A variant of `when` that fallback to an `orElse` callback. -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return orElse(); -/// } -/// ``` - -@optionalTypeArgs TResult maybeWhen(TResult Function( int? selectedClientId, SpecificGrant_Grant grantType)? $default,{required TResult orElse(),}) {final _that = this; -switch (_that) { -case _GrantCreationState() when $default != null: -return $default(_that.selectedClientId,_that.grantType);case _: - return orElse(); - -} -} -/// A `switch`-like method, using callbacks. -/// -/// As opposed to `map`, this offers destructuring. -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case Subclass2(:final field2): -/// return ...; -/// } -/// ``` - -@optionalTypeArgs TResult when(TResult Function( int? selectedClientId, SpecificGrant_Grant grantType) $default,) {final _that = this; -switch (_that) { -case _GrantCreationState(): -return $default(_that.selectedClientId,_that.grantType);case _: - throw StateError('Unexpected subclass'); - -} -} -/// A variant of `when` that fallback to returning `null` -/// -/// It is equivalent to doing: -/// ```dart -/// switch (sealedClass) { -/// case Subclass(:final field): -/// return ...; -/// case _: -/// return null; -/// } -/// ``` - -@optionalTypeArgs TResult? whenOrNull(TResult? Function( int? selectedClientId, SpecificGrant_Grant grantType)? $default,) {final _that = this; -switch (_that) { -case _GrantCreationState() when $default != null: -return $default(_that.selectedClientId,_that.grantType);case _: - return null; - -} -} - -} - -/// @nodoc - - -class _GrantCreationState implements GrantCreationState { - const _GrantCreationState({this.selectedClientId, this.grantType = SpecificGrant_Grant.etherTransfer}); - - -@override final int? selectedClientId; -@override@JsonKey() final SpecificGrant_Grant grantType; - -/// Create a copy of GrantCreationState -/// with the given fields replaced by the non-null parameter values. -@override @JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -_$GrantCreationStateCopyWith<_GrantCreationState> get copyWith => __$GrantCreationStateCopyWithImpl<_GrantCreationState>(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _GrantCreationState&&(identical(other.selectedClientId, selectedClientId) || other.selectedClientId == selectedClientId)&&(identical(other.grantType, grantType) || other.grantType == grantType)); -} - - -@override -int get hashCode => Object.hash(runtimeType,selectedClientId,grantType); - -@override -String toString() { - return 'GrantCreationState(selectedClientId: $selectedClientId, grantType: $grantType)'; -} - - -} - -/// @nodoc -abstract mixin class _$GrantCreationStateCopyWith<$Res> implements $GrantCreationStateCopyWith<$Res> { - factory _$GrantCreationStateCopyWith(_GrantCreationState value, $Res Function(_GrantCreationState) _then) = __$GrantCreationStateCopyWithImpl; -@override @useResult -$Res call({ - int? selectedClientId, SpecificGrant_Grant grantType -}); - - - - -} -/// @nodoc -class __$GrantCreationStateCopyWithImpl<$Res> - implements _$GrantCreationStateCopyWith<$Res> { - __$GrantCreationStateCopyWithImpl(this._self, this._then); - - final _GrantCreationState _self; - final $Res Function(_GrantCreationState) _then; - -/// Create a copy of GrantCreationState -/// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? selectedClientId = freezed,Object? grantType = null,}) { - return _then(_GrantCreationState( -selectedClientId: freezed == selectedClientId ? _self.selectedClientId : selectedClientId // ignore: cast_nullable_to_non_nullable -as int?,grantType: null == grantType ? _self.grantType : grantType // ignore: cast_nullable_to_non_nullable -as SpecificGrant_Grant, - )); -} - - -} - -// dart format on +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'provider.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$GrantCreationState { + + int? get selectedClientId; SpecificGrant_Grant get grantType; +/// Create a copy of GrantCreationState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$GrantCreationStateCopyWith get copyWith => _$GrantCreationStateCopyWithImpl(this as GrantCreationState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is GrantCreationState&&(identical(other.selectedClientId, selectedClientId) || other.selectedClientId == selectedClientId)&&(identical(other.grantType, grantType) || other.grantType == grantType)); +} + + +@override +int get hashCode => Object.hash(runtimeType,selectedClientId,grantType); + +@override +String toString() { + return 'GrantCreationState(selectedClientId: $selectedClientId, grantType: $grantType)'; +} + + +} + +/// @nodoc +abstract mixin class $GrantCreationStateCopyWith<$Res> { + factory $GrantCreationStateCopyWith(GrantCreationState value, $Res Function(GrantCreationState) _then) = _$GrantCreationStateCopyWithImpl; +@useResult +$Res call({ + int? selectedClientId, SpecificGrant_Grant grantType +}); + + + + +} +/// @nodoc +class _$GrantCreationStateCopyWithImpl<$Res> + implements $GrantCreationStateCopyWith<$Res> { + _$GrantCreationStateCopyWithImpl(this._self, this._then); + + final GrantCreationState _self; + final $Res Function(GrantCreationState) _then; + +/// Create a copy of GrantCreationState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? selectedClientId = freezed,Object? grantType = null,}) { + return _then(_self.copyWith( +selectedClientId: freezed == selectedClientId ? _self.selectedClientId : selectedClientId // ignore: cast_nullable_to_non_nullable +as int?,grantType: null == grantType ? _self.grantType : grantType // ignore: cast_nullable_to_non_nullable +as SpecificGrant_Grant, + )); +} + +} + + +/// Adds pattern-matching-related methods to [GrantCreationState]. +extension GrantCreationStatePatterns on GrantCreationState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _GrantCreationState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _GrantCreationState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _GrantCreationState value) $default,){ +final _that = this; +switch (_that) { +case _GrantCreationState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _GrantCreationState value)? $default,){ +final _that = this; +switch (_that) { +case _GrantCreationState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int? selectedClientId, SpecificGrant_Grant grantType)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _GrantCreationState() when $default != null: +return $default(_that.selectedClientId,_that.grantType);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int? selectedClientId, SpecificGrant_Grant grantType) $default,) {final _that = this; +switch (_that) { +case _GrantCreationState(): +return $default(_that.selectedClientId,_that.grantType);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int? selectedClientId, SpecificGrant_Grant grantType)? $default,) {final _that = this; +switch (_that) { +case _GrantCreationState() when $default != null: +return $default(_that.selectedClientId,_that.grantType);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _GrantCreationState implements GrantCreationState { + const _GrantCreationState({this.selectedClientId, this.grantType = SpecificGrant_Grant.etherTransfer}); + + +@override final int? selectedClientId; +@override@JsonKey() final SpecificGrant_Grant grantType; + +/// Create a copy of GrantCreationState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$GrantCreationStateCopyWith<_GrantCreationState> get copyWith => __$GrantCreationStateCopyWithImpl<_GrantCreationState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _GrantCreationState&&(identical(other.selectedClientId, selectedClientId) || other.selectedClientId == selectedClientId)&&(identical(other.grantType, grantType) || other.grantType == grantType)); +} + + +@override +int get hashCode => Object.hash(runtimeType,selectedClientId,grantType); + +@override +String toString() { + return 'GrantCreationState(selectedClientId: $selectedClientId, grantType: $grantType)'; +} + + +} + +/// @nodoc +abstract mixin class _$GrantCreationStateCopyWith<$Res> implements $GrantCreationStateCopyWith<$Res> { + factory _$GrantCreationStateCopyWith(_GrantCreationState value, $Res Function(_GrantCreationState) _then) = __$GrantCreationStateCopyWithImpl; +@override @useResult +$Res call({ + int? selectedClientId, SpecificGrant_Grant grantType +}); + + + + +} +/// @nodoc +class __$GrantCreationStateCopyWithImpl<$Res> + implements _$GrantCreationStateCopyWith<$Res> { + __$GrantCreationStateCopyWithImpl(this._self, this._then); + + final _GrantCreationState _self; + final $Res Function(_GrantCreationState) _then; + +/// Create a copy of GrantCreationState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? selectedClientId = freezed,Object? grantType = null,}) { + return _then(_GrantCreationState( +selectedClientId: freezed == selectedClientId ? _self.selectedClientId : selectedClientId // ignore: cast_nullable_to_non_nullable +as int?,grantType: null == grantType ? _self.grantType : grantType // ignore: cast_nullable_to_non_nullable +as SpecificGrant_Grant, + )); +} + + +} + +// dart format on diff --git a/useragent/lib/screens/dashboard/evm/grants/create/provider.g.dart b/useragent/lib/screens/dashboard/evm/grants/create/provider.g.dart index 9ec5c71..256c48d 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/provider.g.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/provider.g.dart @@ -1,62 +1,62 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'provider.dart'; - -// ************************************************************************** -// RiverpodGenerator -// ************************************************************************** - -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint, type=warning - -@ProviderFor(GrantCreation) -final grantCreationProvider = GrantCreationProvider._(); - -final class GrantCreationProvider - extends $NotifierProvider { - GrantCreationProvider._() - : super( - from: null, - argument: null, - retry: null, - name: r'grantCreationProvider', - isAutoDispose: true, - dependencies: null, - $allTransitiveDependencies: null, - ); - - @override - String debugGetCreateSourceHash() => _$grantCreationHash(); - - @$internal - @override - GrantCreation create() => GrantCreation(); - - /// {@macro riverpod.override_with_value} - Override overrideWithValue(GrantCreationState value) { - return $ProviderOverride( - origin: this, - providerOverride: $SyncValueProvider(value), - ); - } -} - -String _$grantCreationHash() => r'3733d45da30990ef8ecbee946d2eae81bc7f5fc9'; - -abstract class _$GrantCreation extends $Notifier { - GrantCreationState build(); - @$mustCallSuper - @override - void runBuild() { - final ref = this.ref as $Ref; - final element = - ref.element - as $ClassProviderElement< - AnyNotifier, - GrantCreationState, - Object?, - Object? - >; - element.handleCreate(ref, build); - } -} +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning + +@ProviderFor(GrantCreation) +final grantCreationProvider = GrantCreationProvider._(); + +final class GrantCreationProvider + extends $NotifierProvider { + GrantCreationProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'grantCreationProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$grantCreationHash(); + + @$internal + @override + GrantCreation create() => GrantCreation(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(GrantCreationState value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } +} + +String _$grantCreationHash() => r'3733d45da30990ef8ecbee946d2eae81bc7f5fc9'; + +abstract class _$GrantCreation extends $Notifier { + GrantCreationState build(); + @$mustCallSuper + @override + void runBuild() { + final ref = this.ref as $Ref; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, + GrantCreationState, + Object?, + Object? + >; + element.handleCreate(ref, build); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/screen.dart b/useragent/lib/screens/dashboard/evm/grants/create/screen.dart index 8808e3e..c7c883b 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/screen.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/screen.dart @@ -1,351 +1,351 @@ -// lib/screens/dashboard/evm/grants/create/screen.dart -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/providers/evm/evm_grants.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/chain_id_field.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/validity_window_field.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/shared_grant_fields.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:fixnum/fixnum.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; -import 'package:sizer/sizer.dart'; - -const _etherHandler = EtherTransferGrantHandler(); -const _tokenHandler = TokenTransferGrantHandler(); - -GrantFormHandler _handlerFor(SpecificGrant_Grant type) => switch (type) { - SpecificGrant_Grant.etherTransfer => _etherHandler, - SpecificGrant_Grant.tokenTransfer => _tokenHandler, - _ => throw ArgumentError('Unsupported grant type: $type'), -}; - -@RoutePage() -class CreateEvmGrantScreen extends HookConsumerWidget { - const CreateEvmGrantScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final formKey = useMemoized(() => GlobalKey()); - final createMutation = ref.watch(createEvmGrantMutation); - final state = ref.watch(grantCreationProvider); - final notifier = ref.read(grantCreationProvider.notifier); - final handler = _handlerFor(state.grantType); - - Future submit() async { - if (!(formKey.currentState?.saveAndValidate() ?? false)) return; - final formValues = formKey.currentState!.value; - - final accessId = formValues['walletAccessId'] as int?; - if (accessId == null) { - _showSnackBar(context, 'Select a client and wallet access.'); - return; - } - - try { - final specific = handler.buildSpecificGrant(formValues, ref); - final sharedSettings = SharedSettings( - walletAccessId: accessId, - chainId: Int64.parseInt( - (formValues['chainId'] as String? ?? '').trim(), - ), - ); - final validFrom = formValues['validFrom'] as DateTime?; - final validUntil = formValues['validUntil'] as DateTime?; - if (validFrom != null) - sharedSettings.validFrom = toTimestamp(validFrom); - if (validUntil != null) { - sharedSettings.validUntil = toTimestamp(validUntil); - } - final gasBytes = optionalBigIntBytes( - formValues['maxGasFeePerGas'] as String? ?? '', - ); - if (gasBytes != null) sharedSettings.maxGasFeePerGas = gasBytes; - final priorityBytes = optionalBigIntBytes( - formValues['maxPriorityFeePerGas'] as String? ?? '', - ); - if (priorityBytes != null) { - sharedSettings.maxPriorityFeePerGas = priorityBytes; - } - final rateLimit = buildRateLimit( - formValues['txCount'] as String? ?? '', - formValues['txWindow'] as String? ?? '', - ); - if (rateLimit != null) sharedSettings.rateLimit = rateLimit; - - await executeCreateEvmGrant( - ref, - sharedSettings: sharedSettings, - specific: specific, - ); - if (!context.mounted) return; - context.router.pop(); - } catch (error) { - if (!context.mounted) return; - _showSnackBar(context, _formatError(error)); - } - } - - return Scaffold( - appBar: AppBar(title: const Text('Create EVM Grant')), - body: SafeArea( - child: FormBuilder( - key: formKey, - child: ListView( - padding: EdgeInsets.fromLTRB(2.4.w, 2.h, 2.4.w, 3.2.h), - children: [ - const _IntroCard(), - SizedBox(height: 1.8.h), - const _Section( - title: 'Authorization', - tooltip: - 'Select which SDK client receives this grant and ' - 'which of its wallet accesses it applies to.', - child: AuthorizationFields(), - ), - SizedBox(height: 1.8.h), - IntrinsicHeight( - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Expanded( - child: _Section( - title: 'Chain', - tooltip: - 'Restrict this grant to a specific EVM chain ID. ' - 'Leave empty to allow any chain.', - optional: true, - child: ChainIdField(), - ), - ), - SizedBox(width: 1.8.w), - const Expanded( - child: _Section( - title: 'Timing', - tooltip: - 'Set an optional validity window. ' - 'Signing requests outside this period will be rejected.', - optional: true, - child: ValidityWindowField(), - ), - ), - ], - ), - ), - SizedBox(height: 1.8.h), - IntrinsicHeight( - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Expanded( - child: _Section( - title: 'Gas limits', - tooltip: - 'Cap the gas fees this grant may authorize. ' - 'Transactions exceeding these values will be rejected.', - optional: true, - child: GasFeeOptionsField(), - ), - ), - SizedBox(width: 1.8.w), - const Expanded( - child: _Section( - title: 'Transaction limits', - tooltip: - 'Limit how many transactions can be signed ' - 'within a rolling time window.', - optional: true, - child: TransactionRateLimitField(), - ), - ), - ], - ), - ), - SizedBox(height: 1.8.h), - _GrantTypeSelector( - value: state.grantType, - onChanged: notifier.setGrantType, - ), - SizedBox(height: 1.8.h), - _Section( - title: 'Grant-specific options', - tooltip: - 'Rules specific to the selected transfer type. ' - 'Switch between Ether and token above to change these fields.', - child: handler.buildForm(context, ref), - ), - SizedBox(height: 2.2.h), - Align( - alignment: Alignment.centerRight, - child: FilledButton.icon( - onPressed: createMutation is MutationPending ? null : submit, - icon: createMutation is MutationPending - ? SizedBox( - width: 1.8.h, - height: 1.8.h, - child: const CircularProgressIndicator( - strokeWidth: 2.2, - ), - ) - : const Icon(Icons.check_rounded), - label: Text( - createMutation is MutationPending - ? 'Creating...' - : 'Create grant', - ), - ), - ), - ], - ), - ), - ), - ); - } -} - -// --------------------------------------------------------------------------- -// Layout helpers -// --------------------------------------------------------------------------- - -class _IntroCard extends StatelessWidget { - const _IntroCard(); - - @override - Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.all(2.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), - gradient: const LinearGradient( - colors: [Palette.introGradientStart, Palette.introGradientEnd], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - border: Border.all(color: Palette.cardBorder), - ), - child: Text( - 'Pick a client, then select one of the wallet accesses already granted ' - 'to it. Compose shared constraints once, then switch between Ether and ' - 'token transfer rules.', - style: Theme.of(context).textTheme.bodyLarge?.copyWith(height: 1.5), - ), - ); - } -} - -class _Section extends StatelessWidget { - const _Section({ - required this.title, - required this.tooltip, - required this.child, - this.optional = false, - }); - - final String title; - final String tooltip; - final Widget child; - final bool optional; - - @override - Widget build(BuildContext context) { - final subtleColor = Theme.of(context).colorScheme.outline; - return Container( - padding: EdgeInsets.all(2.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), - color: Colors.white, - border: Border.all(color: Palette.cardBorder), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Text( - title, - style: Theme.of( - context, - ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w800), - ), - SizedBox(width: 0.4.w), - Tooltip( - message: tooltip, - child: Icon( - Icons.info_outline_rounded, - size: 16, - color: subtleColor, - ), - ), - if (optional) ...[ - SizedBox(width: 0.6.w), - Text( - '(optional)', - style: Theme.of( - context, - ).textTheme.bodySmall?.copyWith(color: subtleColor), - ), - ], - ], - ), - SizedBox(height: 1.4.h), - child, - ], - ), - ); - } -} - -class _GrantTypeSelector extends StatelessWidget { - const _GrantTypeSelector({required this.value, required this.onChanged}); - - final SpecificGrant_Grant value; - final ValueChanged onChanged; - - @override - Widget build(BuildContext context) { - return SegmentedButton( - segments: const [ - ButtonSegment( - value: SpecificGrant_Grant.etherTransfer, - label: Text('Ether'), - icon: Icon(Icons.bolt_rounded), - ), - ButtonSegment( - value: SpecificGrant_Grant.tokenTransfer, - label: Text('Token'), - icon: Icon(Icons.token_rounded), - ), - ], - selected: {value}, - onSelectionChanged: (selection) => onChanged(selection.first), - ); - } -} - -// --------------------------------------------------------------------------- -// Utilities -// --------------------------------------------------------------------------- - -void _showSnackBar(BuildContext context, String message) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), - ); -} - -String _formatError(Object error) { - final text = error.toString(); - return text.startsWith('Exception: ') - ? text.substring('Exception: '.length) - : text; -} +// lib/screens/dashboard/evm/grants/create/screen.dart +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/providers/evm/evm_grants.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/grants/ether_transfer_grant.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/grants/grant_form_handler.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/grants/token_transfer_grant.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/provider.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/chain_id_field.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/gas_fee_options_field.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/transaction_rate_limit_field.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/validity_window_field.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/shared_grant_fields.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/utils.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:fixnum/fixnum.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; +import 'package:sizer/sizer.dart'; + +const _etherHandler = EtherTransferGrantHandler(); +const _tokenHandler = TokenTransferGrantHandler(); + +GrantFormHandler _handlerFor(SpecificGrant_Grant type) => switch (type) { + SpecificGrant_Grant.etherTransfer => _etherHandler, + SpecificGrant_Grant.tokenTransfer => _tokenHandler, + _ => throw ArgumentError('Unsupported grant type: $type'), +}; + +@RoutePage() +class CreateEvmGrantScreen extends HookConsumerWidget { + const CreateEvmGrantScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final formKey = useMemoized(() => GlobalKey()); + final createMutation = ref.watch(createEvmGrantMutation); + final state = ref.watch(grantCreationProvider); + final notifier = ref.read(grantCreationProvider.notifier); + final handler = _handlerFor(state.grantType); + + Future submit() async { + if (!(formKey.currentState?.saveAndValidate() ?? false)) return; + final formValues = formKey.currentState!.value; + + final accessId = formValues['walletAccessId'] as int?; + if (accessId == null) { + _showSnackBar(context, 'Select a client and wallet access.'); + return; + } + + try { + final specific = handler.buildSpecificGrant(formValues, ref); + final sharedSettings = SharedSettings( + walletAccessId: accessId, + chainId: Int64.parseInt( + (formValues['chainId'] as String? ?? '').trim(), + ), + ); + final validFrom = formValues['validFrom'] as DateTime?; + final validUntil = formValues['validUntil'] as DateTime?; + if (validFrom != null) + sharedSettings.validFrom = toTimestamp(validFrom); + if (validUntil != null) { + sharedSettings.validUntil = toTimestamp(validUntil); + } + final gasBytes = optionalBigIntBytes( + formValues['maxGasFeePerGas'] as String? ?? '', + ); + if (gasBytes != null) sharedSettings.maxGasFeePerGas = gasBytes; + final priorityBytes = optionalBigIntBytes( + formValues['maxPriorityFeePerGas'] as String? ?? '', + ); + if (priorityBytes != null) { + sharedSettings.maxPriorityFeePerGas = priorityBytes; + } + final rateLimit = buildRateLimit( + formValues['txCount'] as String? ?? '', + formValues['txWindow'] as String? ?? '', + ); + if (rateLimit != null) sharedSettings.rateLimit = rateLimit; + + await executeCreateEvmGrant( + ref, + sharedSettings: sharedSettings, + specific: specific, + ); + if (!context.mounted) return; + context.router.pop(); + } catch (error) { + if (!context.mounted) return; + _showSnackBar(context, _formatError(error)); + } + } + + return Scaffold( + appBar: AppBar(title: const Text('Create EVM Grant')), + body: SafeArea( + child: FormBuilder( + key: formKey, + child: ListView( + padding: EdgeInsets.fromLTRB(2.4.w, 2.h, 2.4.w, 3.2.h), + children: [ + const _IntroCard(), + SizedBox(height: 1.8.h), + const _Section( + title: 'Authorization', + tooltip: + 'Select which SDK client receives this grant and ' + 'which of its wallet accesses it applies to.', + child: AuthorizationFields(), + ), + SizedBox(height: 1.8.h), + IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Expanded( + child: _Section( + title: 'Chain', + tooltip: + 'Restrict this grant to a specific EVM chain ID. ' + 'Leave empty to allow any chain.', + optional: true, + child: ChainIdField(), + ), + ), + SizedBox(width: 1.8.w), + const Expanded( + child: _Section( + title: 'Timing', + tooltip: + 'Set an optional validity window. ' + 'Signing requests outside this period will be rejected.', + optional: true, + child: ValidityWindowField(), + ), + ), + ], + ), + ), + SizedBox(height: 1.8.h), + IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Expanded( + child: _Section( + title: 'Gas limits', + tooltip: + 'Cap the gas fees this grant may authorize. ' + 'Transactions exceeding these values will be rejected.', + optional: true, + child: GasFeeOptionsField(), + ), + ), + SizedBox(width: 1.8.w), + const Expanded( + child: _Section( + title: 'Transaction limits', + tooltip: + 'Limit how many transactions can be signed ' + 'within a rolling time window.', + optional: true, + child: TransactionRateLimitField(), + ), + ), + ], + ), + ), + SizedBox(height: 1.8.h), + _GrantTypeSelector( + value: state.grantType, + onChanged: notifier.setGrantType, + ), + SizedBox(height: 1.8.h), + _Section( + title: 'Grant-specific options', + tooltip: + 'Rules specific to the selected transfer type. ' + 'Switch between Ether and token above to change these fields.', + child: handler.buildForm(context, ref), + ), + SizedBox(height: 2.2.h), + Align( + alignment: Alignment.centerRight, + child: FilledButton.icon( + onPressed: createMutation is MutationPending ? null : submit, + icon: createMutation is MutationPending + ? SizedBox( + width: 1.8.h, + height: 1.8.h, + child: const CircularProgressIndicator( + strokeWidth: 2.2, + ), + ) + : const Icon(Icons.check_rounded), + label: Text( + createMutation is MutationPending + ? 'Creating...' + : 'Create grant', + ), + ), + ), + ], + ), + ), + ), + ); + } +} + +// --------------------------------------------------------------------------- +// Layout helpers +// --------------------------------------------------------------------------- + +class _IntroCard extends StatelessWidget { + const _IntroCard(); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(2.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + gradient: const LinearGradient( + colors: [Palette.introGradientStart, Palette.introGradientEnd], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + border: Border.all(color: Palette.cardBorder), + ), + child: Text( + 'Pick a client, then select one of the wallet accesses already granted ' + 'to it. Compose shared constraints once, then switch between Ether and ' + 'token transfer rules.', + style: Theme.of(context).textTheme.bodyLarge?.copyWith(height: 1.5), + ), + ); + } +} + +class _Section extends StatelessWidget { + const _Section({ + required this.title, + required this.tooltip, + required this.child, + this.optional = false, + }); + + final String title; + final String tooltip; + final Widget child; + final bool optional; + + @override + Widget build(BuildContext context) { + final subtleColor = Theme.of(context).colorScheme.outline; + return Container( + padding: EdgeInsets.all(2.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + color: Colors.white, + border: Border.all(color: Palette.cardBorder), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + title, + style: Theme.of( + context, + ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w800), + ), + SizedBox(width: 0.4.w), + Tooltip( + message: tooltip, + child: Icon( + Icons.info_outline_rounded, + size: 16, + color: subtleColor, + ), + ), + if (optional) ...[ + SizedBox(width: 0.6.w), + Text( + '(optional)', + style: Theme.of( + context, + ).textTheme.bodySmall?.copyWith(color: subtleColor), + ), + ], + ], + ), + SizedBox(height: 1.4.h), + child, + ], + ), + ); + } +} + +class _GrantTypeSelector extends StatelessWidget { + const _GrantTypeSelector({required this.value, required this.onChanged}); + + final SpecificGrant_Grant value; + final ValueChanged onChanged; + + @override + Widget build(BuildContext context) { + return SegmentedButton( + segments: const [ + ButtonSegment( + value: SpecificGrant_Grant.etherTransfer, + label: Text('Ether'), + icon: Icon(Icons.bolt_rounded), + ), + ButtonSegment( + value: SpecificGrant_Grant.tokenTransfer, + label: Text('Token'), + icon: Icon(Icons.token_rounded), + ), + ], + selected: {value}, + onSelectionChanged: (selection) => onChanged(selection.first), + ); + } +} + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- + +void _showSnackBar(BuildContext context, String message) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), + ); +} + +String _formatError(Object error) { + final text = error.toString(); + return text.startsWith('Exception: ') + ? text.substring('Exception: '.length) + : text; +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart b/useragent/lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart index 65aba62..1aa546d 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart @@ -1,21 +1,21 @@ -// lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/client_picker_field.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart'; -import 'package:flutter/material.dart'; -import 'package:sizer/sizer.dart'; - -class AuthorizationFields extends StatelessWidget { - const AuthorizationFields({super.key}); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const ClientPickerField(), - SizedBox(height: 1.6.h), - const WalletAccessPickerField(), - ], - ); - } -} +// lib/screens/dashboard/evm/grants/create/shared_grant_fields.dart +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/client_picker_field.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/create/fields/wallet_access_picker_field.dart'; +import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; + +class AuthorizationFields extends StatelessWidget { + const AuthorizationFields({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const ClientPickerField(), + SizedBox(height: 1.6.h), + const WalletAccessPickerField(), + ], + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/create/utils.dart b/useragent/lib/screens/dashboard/evm/grants/create/utils.dart index 08dad7c..89ba933 100644 --- a/useragent/lib/screens/dashboard/evm/grants/create/utils.dart +++ b/useragent/lib/screens/dashboard/evm/grants/create/utils.dart @@ -1,73 +1,73 @@ -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:fixnum/fixnum.dart'; -import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart'; - -Timestamp toTimestamp(DateTime value) { - final utc = value.toUtc(); - return Timestamp() - ..seconds = Int64(utc.millisecondsSinceEpoch ~/ 1000) - ..nanos = (utc.microsecondsSinceEpoch % 1000000) * 1000; -} - -TransactionRateLimit? buildRateLimit(String countText, String windowText) { - if (countText.trim().isEmpty || windowText.trim().isEmpty) { - return null; - } - return TransactionRateLimit( - count: int.parse(countText.trim()), - windowSecs: Int64.parseInt(windowText.trim()), - ); -} - -VolumeRateLimit? buildVolumeLimit(String amountText, String windowText) { - if (amountText.trim().isEmpty || windowText.trim().isEmpty) { - return null; - } - return VolumeRateLimit( - maxVolume: parseBigIntBytes(amountText), - windowSecs: Int64.parseInt(windowText.trim()), - ); -} - -List? optionalBigIntBytes(String value) { - if (value.trim().isEmpty) { - return null; - } - return parseBigIntBytes(value); -} - -List parseBigIntBytes(String value) { - final number = BigInt.parse(value.trim()); - if (number < BigInt.zero) { - throw Exception('Numeric values must be positive.'); - } - if (number == BigInt.zero) { - return [0]; - } - - var remaining = number; - final bytes = []; - while (remaining > BigInt.zero) { - bytes.insert(0, (remaining & BigInt.from(0xff)).toInt()); - remaining >>= 8; - } - return bytes; -} - -List parseHexAddress(String value) { - final normalized = value.trim().replaceFirst(RegExp(r'^0x'), ''); - if (normalized.length != 40) { - throw Exception('Expected a 20-byte hex address.'); - } - return [ - for (var i = 0; i < normalized.length; i += 2) - int.parse(normalized.substring(i, i + 2), radix: 16), - ]; -} - -String shortAddress(List bytes) { - final hex = bytes - .map((byte) => byte.toRadixString(16).padLeft(2, '0')) - .join(); - return '0x${hex.substring(0, 6)}...${hex.substring(hex.length - 4)}'; -} +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:fixnum/fixnum.dart'; +import 'package:protobuf/well_known_types/google/protobuf/timestamp.pb.dart'; + +Timestamp toTimestamp(DateTime value) { + final utc = value.toUtc(); + return Timestamp() + ..seconds = Int64(utc.millisecondsSinceEpoch ~/ 1000) + ..nanos = (utc.microsecondsSinceEpoch % 1000000) * 1000; +} + +TransactionRateLimit? buildRateLimit(String countText, String windowText) { + if (countText.trim().isEmpty || windowText.trim().isEmpty) { + return null; + } + return TransactionRateLimit( + count: int.parse(countText.trim()), + windowSecs: Int64.parseInt(windowText.trim()), + ); +} + +VolumeRateLimit? buildVolumeLimit(String amountText, String windowText) { + if (amountText.trim().isEmpty || windowText.trim().isEmpty) { + return null; + } + return VolumeRateLimit( + maxVolume: parseBigIntBytes(amountText), + windowSecs: Int64.parseInt(windowText.trim()), + ); +} + +List? optionalBigIntBytes(String value) { + if (value.trim().isEmpty) { + return null; + } + return parseBigIntBytes(value); +} + +List parseBigIntBytes(String value) { + final number = BigInt.parse(value.trim()); + if (number < BigInt.zero) { + throw Exception('Numeric values must be positive.'); + } + if (number == BigInt.zero) { + return [0]; + } + + var remaining = number; + final bytes = []; + while (remaining > BigInt.zero) { + bytes.insert(0, (remaining & BigInt.from(0xff)).toInt()); + remaining >>= 8; + } + return bytes; +} + +List parseHexAddress(String value) { + final normalized = value.trim().replaceFirst(RegExp(r'^0x'), ''); + if (normalized.length != 40) { + throw Exception('Expected a 20-byte hex address.'); + } + return [ + for (var i = 0; i < normalized.length; i += 2) + int.parse(normalized.substring(i, i + 2), radix: 16), + ]; +} + +String shortAddress(List bytes) { + final hex = bytes + .map((byte) => byte.toRadixString(16).padLeft(2, '0')) + .join(); + return '0x${hex.substring(0, 6)}...${hex.substring(hex.length - 4)}'; +} diff --git a/useragent/lib/screens/dashboard/evm/grants/grants.dart b/useragent/lib/screens/dashboard/evm/grants/grants.dart index cccec5d..3fae2b6 100644 --- a/useragent/lib/screens/dashboard/evm/grants/grants.dart +++ b/useragent/lib/screens/dashboard/evm/grants/grants.dart @@ -1,157 +1,157 @@ -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/providers/evm/evm_grants.dart'; -import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; -import 'package:arbiter/router.gr.dart'; -import 'package:arbiter/screens/dashboard/evm/grants/widgets/grant_card.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:arbiter/widgets/page_header.dart'; -import 'package:arbiter/widgets/state_panel.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -String _formatError(Object error) { - final message = error.toString(); - if (message.startsWith('Exception: ')) { - return message.substring('Exception: '.length); - } - return message; -} - -class _GrantList extends StatelessWidget { - const _GrantList({required this.grants}); - - final List grants; - - @override - Widget build(BuildContext context) { - return SingleChildScrollView( - child: Column( - children: [ - for (var i = 0; i < grants.length; i++) - Padding( - padding: EdgeInsets.only( - bottom: i == grants.length - 1 ? 0 : 1.8.h, - ), - child: GrantCard(grant: grants[i]), - ), - ], - ), - ); - } -} - -@RoutePage() -class EvmGrantsScreen extends ConsumerWidget { - const EvmGrantsScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - // Screen watches only the grant list for top-level state decisions - final grantsAsync = ref.watch(evmGrantsProvider); - - Future refresh() async { - ref.invalidate(walletAccessListProvider); - ref.invalidate(evmGrantsProvider); - } - - void showMessage(String message) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), - ); - } - - Future safeRefresh() async { - try { - await refresh(); - } catch (e) { - showMessage(_formatError(e)); - } - } - - final grantsState = grantsAsync.asData?.value; - final grants = grantsState?.grants; - - final content = switch (grantsAsync) { - AsyncLoading() when grantsState == null => const StatePanel( - icon: Icons.hourglass_top, - title: 'Loading grants', - body: 'Pulling grant registry from Arbiter.', - busy: true, - ), - AsyncError(:final error) => StatePanel( - icon: Icons.sync_problem, - title: 'Grant registry unavailable', - body: _formatError(error), - actionLabel: 'Retry', - onAction: safeRefresh, - ), - AsyncData(:final value) when value == null => StatePanel( - icon: Icons.portable_wifi_off, - title: 'No active server connection', - body: 'Reconnect to Arbiter to list EVM grants.', - actionLabel: 'Refresh', - onAction: safeRefresh, - ), - _ when grants != null && grants.isEmpty => StatePanel( - icon: Icons.policy_outlined, - title: 'No grants yet', - body: 'Create a grant to allow SDK clients to sign transactions.', - actionLabel: 'Create grant', - onAction: () async => context.router.push(const CreateEvmGrantRoute()), - ), - _ => _GrantList(grants: grants ?? const []), - }; - - return Scaffold( - body: SafeArea( - child: RefreshIndicator.adaptive( - color: Palette.ink, - backgroundColor: Colors.white, - onRefresh: safeRefresh, - child: ListView( - physics: const BouncingScrollPhysics( - parent: AlwaysScrollableScrollPhysics(), - ), - padding: EdgeInsets.fromLTRB(2.4.w, 2.4.h, 2.4.w, 3.2.h), - children: [ - PageHeader( - title: 'EVM Grants', - isBusy: grantsAsync.isLoading, - actions: [ - FilledButton.icon( - onPressed: () => - context.router.push(const CreateEvmGrantRoute()), - icon: const Icon(Icons.add_rounded), - label: const Text('Create grant'), - ), - SizedBox(width: 1.w), - OutlinedButton.icon( - onPressed: safeRefresh, - style: OutlinedButton.styleFrom( - foregroundColor: Palette.ink, - side: BorderSide(color: Palette.line), - padding: EdgeInsets.symmetric( - horizontal: 1.4.w, - vertical: 1.2.h, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(14), - ), - ), - icon: const Icon(Icons.refresh, size: 18), - label: const Text('Refresh'), - ), - ], - ), - SizedBox(height: 1.8.h), - content, - ], - ), - ), - ), - ); - } -} +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/providers/evm/evm_grants.dart'; +import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; +import 'package:arbiter/router.gr.dart'; +import 'package:arbiter/screens/dashboard/evm/grants/widgets/grant_card.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:arbiter/widgets/page_header.dart'; +import 'package:arbiter/widgets/state_panel.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +String _formatError(Object error) { + final message = error.toString(); + if (message.startsWith('Exception: ')) { + return message.substring('Exception: '.length); + } + return message; +} + +class _GrantList extends StatelessWidget { + const _GrantList({required this.grants}); + + final List grants; + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Column( + children: [ + for (var i = 0; i < grants.length; i++) + Padding( + padding: EdgeInsets.only( + bottom: i == grants.length - 1 ? 0 : 1.8.h, + ), + child: GrantCard(grant: grants[i]), + ), + ], + ), + ); + } +} + +@RoutePage() +class EvmGrantsScreen extends ConsumerWidget { + const EvmGrantsScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + // Screen watches only the grant list for top-level state decisions + final grantsAsync = ref.watch(evmGrantsProvider); + + Future refresh() async { + ref.invalidate(walletAccessListProvider); + ref.invalidate(evmGrantsProvider); + } + + void showMessage(String message) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), + ); + } + + Future safeRefresh() async { + try { + await refresh(); + } catch (e) { + showMessage(_formatError(e)); + } + } + + final grantsState = grantsAsync.asData?.value; + final grants = grantsState?.grants; + + final content = switch (grantsAsync) { + AsyncLoading() when grantsState == null => const StatePanel( + icon: Icons.hourglass_top, + title: 'Loading grants', + body: 'Pulling grant registry from Arbiter.', + busy: true, + ), + AsyncError(:final error) => StatePanel( + icon: Icons.sync_problem, + title: 'Grant registry unavailable', + body: _formatError(error), + actionLabel: 'Retry', + onAction: safeRefresh, + ), + AsyncData(:final value) when value == null => StatePanel( + icon: Icons.portable_wifi_off, + title: 'No active server connection', + body: 'Reconnect to Arbiter to list EVM grants.', + actionLabel: 'Refresh', + onAction: safeRefresh, + ), + _ when grants != null && grants.isEmpty => StatePanel( + icon: Icons.policy_outlined, + title: 'No grants yet', + body: 'Create a grant to allow SDK clients to sign transactions.', + actionLabel: 'Create grant', + onAction: () async => context.router.push(const CreateEvmGrantRoute()), + ), + _ => _GrantList(grants: grants ?? const []), + }; + + return Scaffold( + body: SafeArea( + child: RefreshIndicator.adaptive( + color: Palette.ink, + backgroundColor: Colors.white, + onRefresh: safeRefresh, + child: ListView( + physics: const BouncingScrollPhysics( + parent: AlwaysScrollableScrollPhysics(), + ), + padding: EdgeInsets.fromLTRB(2.4.w, 2.4.h, 2.4.w, 3.2.h), + children: [ + PageHeader( + title: 'EVM Grants', + isBusy: grantsAsync.isLoading, + actions: [ + FilledButton.icon( + onPressed: () => + context.router.push(const CreateEvmGrantRoute()), + icon: const Icon(Icons.add_rounded), + label: const Text('Create grant'), + ), + SizedBox(width: 1.w), + OutlinedButton.icon( + onPressed: safeRefresh, + style: OutlinedButton.styleFrom( + foregroundColor: Palette.ink, + side: BorderSide(color: Palette.line), + padding: EdgeInsets.symmetric( + horizontal: 1.4.w, + vertical: 1.2.h, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(14), + ), + ), + icon: const Icon(Icons.refresh, size: 18), + label: const Text('Refresh'), + ), + ], + ), + SizedBox(height: 1.8.h), + content, + ], + ), + ), + ), + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/grants/widgets/grant_card.dart b/useragent/lib/screens/dashboard/evm/grants/widgets/grant_card.dart index 76857fd..125ecdf 100644 --- a/useragent/lib/screens/dashboard/evm/grants/widgets/grant_card.dart +++ b/useragent/lib/screens/dashboard/evm/grants/widgets/grant_card.dart @@ -1,219 +1,219 @@ -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; -import 'package:arbiter/providers/evm/evm.dart'; -import 'package:arbiter/providers/evm/evm_grants.dart'; -import 'package:arbiter/providers/sdk_clients/list.dart'; -import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -String _shortAddress(List bytes) { - final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); - return '0x${hex.substring(0, 6)}...${hex.substring(hex.length - 4)}'; -} - -String _formatError(Object error) { - final message = error.toString(); - if (message.startsWith('Exception: ')) { - return message.substring('Exception: '.length); - } - return message; -} - -class GrantCard extends ConsumerWidget { - const GrantCard({super.key, required this.grant}); - - final GrantEntry grant; - - @override - Widget build(BuildContext context, WidgetRef ref) { - final walletAccesses = - ref.watch(walletAccessListProvider).asData?.value ?? const []; - final wallets = ref.watch(evmProvider).asData?.value ?? const []; - final clients = ref.watch(sdkClientsProvider).asData?.value ?? const []; - final revoking = ref.watch(revokeEvmGrantMutation) is MutationPending; - - final isEther = - grant.specific.whichGrant() == SpecificGrant_Grant.etherTransfer; - final accent = isEther ? Palette.coral : Palette.token; - final typeLabel = isEther ? 'Ether' : 'Token'; - final theme = Theme.of(context); - final muted = Palette.ink.withValues(alpha: 0.62); - - final accessById = { - for (final a in walletAccesses) a.id: a, - }; - final walletById = {for (final w in wallets) w.id: w}; - final clientNameById = { - for (final c in clients) c.id: c.info.name, - }; - - final accessId = grant.shared.walletAccessId; - final access = accessById[accessId]; - final wallet = access != null ? walletById[access.access.walletId] : null; - - final walletLabel = wallet != null - ? _shortAddress(wallet.address) - : 'Access #$accessId'; - - final clientLabel = () { - if (access == null) return ''; - final name = clientNameById[access.access.sdkClientId] ?? ''; - return name.isEmpty ? 'Client #${access.access.sdkClientId}' : name; - }(); - - void showError(String message) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), - ); - } - - Future revoke() async { - try { - await executeRevokeEvmGrant(ref, grantId: grant.id); - } catch (e) { - showError(_formatError(e)); - } - } - - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), - color: Palette.cream.withValues(alpha: 0.92), - border: Border.all(color: Palette.line), - ), - child: IntrinsicHeight( - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - width: 0.8.w, - decoration: BoxDecoration( - color: accent, - borderRadius: const BorderRadius.horizontal( - left: Radius.circular(24), - ), - ), - ), - Expanded( - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: 1.6.w, - vertical: 1.4.h, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Container( - padding: EdgeInsets.symmetric( - horizontal: 1.w, - vertical: 0.4.h, - ), - decoration: BoxDecoration( - color: accent.withValues(alpha: 0.15), - borderRadius: BorderRadius.circular(8), - ), - child: Text( - typeLabel, - style: theme.textTheme.labelSmall?.copyWith( - color: accent, - fontWeight: FontWeight.w800, - ), - ), - ), - SizedBox(width: 1.w), - Container( - padding: EdgeInsets.symmetric( - horizontal: 1.w, - vertical: 0.4.h, - ), - decoration: BoxDecoration( - color: Palette.ink.withValues(alpha: 0.06), - borderRadius: BorderRadius.circular(8), - ), - child: Text( - 'Chain ${grant.shared.chainId}', - style: theme.textTheme.labelSmall?.copyWith( - color: muted, - fontWeight: FontWeight.w700, - ), - ), - ), - const Spacer(), - if (revoking) - SizedBox( - width: 1.8.h, - height: 1.8.h, - child: CircularProgressIndicator( - strokeWidth: 2, - color: Palette.coral, - ), - ) - else - OutlinedButton.icon( - onPressed: revoke, - style: OutlinedButton.styleFrom( - foregroundColor: Palette.coral, - side: BorderSide( - color: Palette.coral.withValues(alpha: 0.4), - ), - padding: EdgeInsets.symmetric( - horizontal: 1.w, - vertical: 0.6.h, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - ), - icon: const Icon(Icons.block_rounded, size: 16), - label: const Text('Revoke'), - ), - ], - ), - SizedBox(height: 0.8.h), - Row( - children: [ - Text( - walletLabel, - style: theme.textTheme.bodySmall?.copyWith( - color: Palette.ink, - fontFamily: 'monospace', - ), - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: 0.8.w), - child: Text( - '·', - style: theme.textTheme.bodySmall?.copyWith( - color: muted, - ), - ), - ), - Expanded( - child: Text( - clientLabel, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.bodySmall?.copyWith( - color: muted, - ), - ), - ), - ], - ), - ], - ), - ), - ), - ], - ), - ), - ); - } -} +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart' as ua_sdk; +import 'package:arbiter/providers/evm/evm.dart'; +import 'package:arbiter/providers/evm/evm_grants.dart'; +import 'package:arbiter/providers/sdk_clients/list.dart'; +import 'package:arbiter/providers/sdk_clients/wallet_access_list.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +String _shortAddress(List bytes) { + final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); + return '0x${hex.substring(0, 6)}...${hex.substring(hex.length - 4)}'; +} + +String _formatError(Object error) { + final message = error.toString(); + if (message.startsWith('Exception: ')) { + return message.substring('Exception: '.length); + } + return message; +} + +class GrantCard extends ConsumerWidget { + const GrantCard({super.key, required this.grant}); + + final GrantEntry grant; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final walletAccesses = + ref.watch(walletAccessListProvider).asData?.value ?? const []; + final wallets = ref.watch(evmProvider).asData?.value ?? const []; + final clients = ref.watch(sdkClientsProvider).asData?.value ?? const []; + final revoking = ref.watch(revokeEvmGrantMutation) is MutationPending; + + final isEther = + grant.specific.whichGrant() == SpecificGrant_Grant.etherTransfer; + final accent = isEther ? Palette.coral : Palette.token; + final typeLabel = isEther ? 'Ether' : 'Token'; + final theme = Theme.of(context); + final muted = Palette.ink.withValues(alpha: 0.62); + + final accessById = { + for (final a in walletAccesses) a.id: a, + }; + final walletById = {for (final w in wallets) w.id: w}; + final clientNameById = { + for (final c in clients) c.id: c.info.name, + }; + + final accessId = grant.shared.walletAccessId; + final access = accessById[accessId]; + final wallet = access != null ? walletById[access.access.walletId] : null; + + final walletLabel = wallet != null + ? _shortAddress(wallet.address) + : 'Access #$accessId'; + + final clientLabel = () { + if (access == null) return ''; + final name = clientNameById[access.access.sdkClientId] ?? ''; + return name.isEmpty ? 'Client #${access.access.sdkClientId}' : name; + }(); + + void showError(String message) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(message), behavior: SnackBarBehavior.floating), + ); + } + + Future revoke() async { + try { + await executeRevokeEvmGrant(ref, grantId: grant.id); + } catch (e) { + showError(_formatError(e)); + } + } + + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + color: Palette.cream.withValues(alpha: 0.92), + border: Border.all(color: Palette.line), + ), + child: IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + width: 0.8.w, + decoration: BoxDecoration( + color: accent, + borderRadius: const BorderRadius.horizontal( + left: Radius.circular(24), + ), + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: 1.6.w, + vertical: 1.4.h, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Container( + padding: EdgeInsets.symmetric( + horizontal: 1.w, + vertical: 0.4.h, + ), + decoration: BoxDecoration( + color: accent.withValues(alpha: 0.15), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + typeLabel, + style: theme.textTheme.labelSmall?.copyWith( + color: accent, + fontWeight: FontWeight.w800, + ), + ), + ), + SizedBox(width: 1.w), + Container( + padding: EdgeInsets.symmetric( + horizontal: 1.w, + vertical: 0.4.h, + ), + decoration: BoxDecoration( + color: Palette.ink.withValues(alpha: 0.06), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + 'Chain ${grant.shared.chainId}', + style: theme.textTheme.labelSmall?.copyWith( + color: muted, + fontWeight: FontWeight.w700, + ), + ), + ), + const Spacer(), + if (revoking) + SizedBox( + width: 1.8.h, + height: 1.8.h, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Palette.coral, + ), + ) + else + OutlinedButton.icon( + onPressed: revoke, + style: OutlinedButton.styleFrom( + foregroundColor: Palette.coral, + side: BorderSide( + color: Palette.coral.withValues(alpha: 0.4), + ), + padding: EdgeInsets.symmetric( + horizontal: 1.w, + vertical: 0.6.h, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + icon: const Icon(Icons.block_rounded, size: 16), + label: const Text('Revoke'), + ), + ], + ), + SizedBox(height: 0.8.h), + Row( + children: [ + Text( + walletLabel, + style: theme.textTheme.bodySmall?.copyWith( + color: Palette.ink, + fontFamily: 'monospace', + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 0.8.w), + child: Text( + '·', + style: theme.textTheme.bodySmall?.copyWith( + color: muted, + ), + ), + ), + Expanded( + child: Text( + clientLabel, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodySmall?.copyWith( + color: muted, + ), + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/useragent/lib/screens/dashboard/evm/wallets/header.dart b/useragent/lib/screens/dashboard/evm/wallets/header.dart index b74a50a..a41e71b 100644 --- a/useragent/lib/screens/dashboard/evm/wallets/header.dart +++ b/useragent/lib/screens/dashboard/evm/wallets/header.dart @@ -1,96 +1,96 @@ -import 'package:arbiter/providers/evm/evm.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -class CreateWalletButton extends ConsumerWidget { - const CreateWalletButton({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final createWallet = ref.watch(createEvmWallet); - final isCreating = createWallet is MutationPending; - - Future handleCreateWallet() async { - try { - await executeCreateEvmWallet(ref); - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text('New wallet created successfully.'), - behavior: SnackBarBehavior.floating, - ), - ); - } catch (e) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Failed to create wallet: ${_formatError(e)}'), - behavior: SnackBarBehavior.floating, - ), - ); - } - } - - return FilledButton.icon( - onPressed: isCreating ? null : () => handleCreateWallet(), - style: FilledButton.styleFrom( - backgroundColor: Palette.ink, - foregroundColor: Colors.white, - padding: EdgeInsets.symmetric(horizontal: 1.4.w, vertical: 1.2.h), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)), - ), - icon: isCreating - ? SizedBox( - width: 1.6.h, - height: 1.6.h, - child: CircularProgressIndicator(strokeWidth: 2.2), - ) - : const Icon(Icons.add_circle_outline, size: 18), - label: Text(isCreating ? 'Creating...' : 'Create'), - ); - } -} - -class RefreshWalletButton extends ConsumerWidget { - const RefreshWalletButton({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - Future handleRefreshWallets() async { - try { - await ref.read(evmProvider.notifier).refreshWallets(); - } catch (e) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Failed to refresh wallets: ${_formatError(e)}'), - behavior: SnackBarBehavior.floating, - ), - ); - } - } - - return OutlinedButton.icon( - onPressed: () => handleRefreshWallets(), - style: OutlinedButton.styleFrom( - foregroundColor: Palette.ink, - side: BorderSide(color: Palette.line), - padding: EdgeInsets.symmetric(horizontal: 1.4.w, vertical: 1.2.h), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)), - ), - icon: const Icon(Icons.refresh, size: 18), - label: const Text('Refresh'), - ); - } -} - -String _formatError(Object error) { - final message = error.toString(); - if (message.startsWith('Exception: ')) { - return message.substring('Exception: '.length); - } - return message; -} +import 'package:arbiter/providers/evm/evm.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +class CreateWalletButton extends ConsumerWidget { + const CreateWalletButton({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final createWallet = ref.watch(createEvmWallet); + final isCreating = createWallet is MutationPending; + + Future handleCreateWallet() async { + try { + await executeCreateEvmWallet(ref); + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('New wallet created successfully.'), + behavior: SnackBarBehavior.floating, + ), + ); + } catch (e) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Failed to create wallet: ${_formatError(e)}'), + behavior: SnackBarBehavior.floating, + ), + ); + } + } + + return FilledButton.icon( + onPressed: isCreating ? null : () => handleCreateWallet(), + style: FilledButton.styleFrom( + backgroundColor: Palette.ink, + foregroundColor: Colors.white, + padding: EdgeInsets.symmetric(horizontal: 1.4.w, vertical: 1.2.h), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)), + ), + icon: isCreating + ? SizedBox( + width: 1.6.h, + height: 1.6.h, + child: CircularProgressIndicator(strokeWidth: 2.2), + ) + : const Icon(Icons.add_circle_outline, size: 18), + label: Text(isCreating ? 'Creating...' : 'Create'), + ); + } +} + +class RefreshWalletButton extends ConsumerWidget { + const RefreshWalletButton({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + Future handleRefreshWallets() async { + try { + await ref.read(evmProvider.notifier).refreshWallets(); + } catch (e) { + if (!context.mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Failed to refresh wallets: ${_formatError(e)}'), + behavior: SnackBarBehavior.floating, + ), + ); + } + } + + return OutlinedButton.icon( + onPressed: () => handleRefreshWallets(), + style: OutlinedButton.styleFrom( + foregroundColor: Palette.ink, + side: BorderSide(color: Palette.line), + padding: EdgeInsets.symmetric(horizontal: 1.4.w, vertical: 1.2.h), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)), + ), + icon: const Icon(Icons.refresh, size: 18), + label: const Text('Refresh'), + ); + } +} + +String _formatError(Object error) { + final message = error.toString(); + if (message.startsWith('Exception: ')) { + return message.substring('Exception: '.length); + } + return message; +} diff --git a/useragent/lib/screens/dashboard/evm/wallets/table.dart b/useragent/lib/screens/dashboard/evm/wallets/table.dart index 6d850e1..9bbcefc 100644 --- a/useragent/lib/screens/dashboard/evm/wallets/table.dart +++ b/useragent/lib/screens/dashboard/evm/wallets/table.dart @@ -1,200 +1,200 @@ -import 'dart:math' as math; -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:arbiter/widgets/cream_frame.dart'; -import 'package:flutter/material.dart'; -import 'package:sizer/sizer.dart'; - -double get _accentStripWidth => 0.8.w; -double get _cellHorizontalPadding => 1.8.w; -double get _walletColumnWidth => 18.w; -double get _columnGap => 1.8.w; -double get _tableMinWidth => 72.w; - -String _hexAddress(List bytes) { - final hex = bytes - .map((byte) => byte.toRadixString(16).padLeft(2, '0')) - .join(); - return '0x$hex'; -} - -Color _accentColor(List bytes) { - final seed = bytes.fold(0, (value, byte) => value + byte); - final hue = (seed * 17) % 360; - return HSLColor.fromAHSL(1, hue.toDouble(), 0.68, 0.54).toColor(); -} - -class WalletTable extends StatelessWidget { - const WalletTable({super.key, required this.wallets}); - - final List wallets; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - return CreamFrame( - padding: EdgeInsets.all(2.h), - child: LayoutBuilder( - builder: (context, constraints) { - final tableWidth = math.max(_tableMinWidth, constraints.maxWidth); - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Managed wallets', - style: theme.textTheme.titleLarge?.copyWith( - color: Palette.ink, - fontWeight: FontWeight.w800, - ), - ), - SizedBox(height: 0.6.h), - Text( - 'Every address here is generated and held by Arbiter.', - style: theme.textTheme.bodyMedium?.copyWith( - color: Palette.ink.withValues(alpha: 0.70), - height: 1.4, - ), - ), - SizedBox(height: 1.6.h), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: SizedBox( - width: tableWidth, - child: Column( - children: [ - const _WalletTableHeader(), - SizedBox(height: 1.h), - for (var i = 0; i < wallets.length; i++) - Padding( - padding: EdgeInsets.only( - bottom: i == wallets.length - 1 ? 0 : 1.h, - ), - child: _WalletTableRow(wallet: wallets[i], index: i), - ), - ], - ), - ), - ), - ], - ); - }, - ), - ); - } -} - -class _WalletTableHeader extends StatelessWidget { - const _WalletTableHeader(); - - @override - Widget build(BuildContext context) { - final style = Theme.of(context).textTheme.labelLarge?.copyWith( - color: Palette.ink.withValues(alpha: 0.72), - fontWeight: FontWeight.w800, - letterSpacing: 0.3, - ); - - return Container( - padding: EdgeInsets.symmetric(vertical: 1.4.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), - color: Palette.ink.withValues(alpha: 0.04), - ), - child: Row( - children: [ - SizedBox(width: _accentStripWidth + _cellHorizontalPadding), - SizedBox( - width: _walletColumnWidth, - child: Text('Wallet', style: style), - ), - SizedBox(width: _columnGap), - Expanded(child: Text('Address', style: style)), - SizedBox(width: _cellHorizontalPadding), - ], - ), - ); - } -} - -class _WalletTableRow extends StatelessWidget { - const _WalletTableRow({required this.wallet, required this.index}); - - final WalletEntry wallet; - final int index; - - @override - Widget build(BuildContext context) { - final accent = _accentColor(wallet.address); - final address = _hexAddress(wallet.address); - final rowHeight = 5.h; - final walletStyle = Theme.of( - context, - ).textTheme.bodyLarge?.copyWith(color: Palette.ink); - final addressStyle = Theme.of( - context, - ).textTheme.bodyMedium?.copyWith(color: Palette.ink); - - return Container( - height: rowHeight, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(18), - color: accent.withValues(alpha: 0.10), - border: Border.all(color: accent.withValues(alpha: 0.28)), - ), - child: Row( - children: [ - Container( - width: _accentStripWidth, - height: rowHeight, - decoration: BoxDecoration( - color: accent, - borderRadius: const BorderRadius.horizontal( - left: Radius.circular(18), - ), - ), - ), - Expanded( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: _cellHorizontalPadding), - child: Row( - children: [ - SizedBox( - width: _walletColumnWidth, - child: Row( - children: [ - Container( - width: 1.2.h, - height: 1.2.h, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: accent, - ), - ), - SizedBox(width: 1.w), - Text( - 'Wallet ${(index + 1).toString().padLeft(2, '0')}', - style: walletStyle, - ), - ], - ), - ), - SizedBox(width: _columnGap), - Expanded( - child: Text( - address, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: addressStyle, - ), - ), - ], - ), - ), - ), - ], - ), - ); - } -} +import 'dart:math' as math; +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:arbiter/widgets/cream_frame.dart'; +import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; + +double get _accentStripWidth => 0.8.w; +double get _cellHorizontalPadding => 1.8.w; +double get _walletColumnWidth => 18.w; +double get _columnGap => 1.8.w; +double get _tableMinWidth => 72.w; + +String _hexAddress(List bytes) { + final hex = bytes + .map((byte) => byte.toRadixString(16).padLeft(2, '0')) + .join(); + return '0x$hex'; +} + +Color _accentColor(List bytes) { + final seed = bytes.fold(0, (value, byte) => value + byte); + final hue = (seed * 17) % 360; + return HSLColor.fromAHSL(1, hue.toDouble(), 0.68, 0.54).toColor(); +} + +class WalletTable extends StatelessWidget { + const WalletTable({super.key, required this.wallets}); + + final List wallets; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return CreamFrame( + padding: EdgeInsets.all(2.h), + child: LayoutBuilder( + builder: (context, constraints) { + final tableWidth = math.max(_tableMinWidth, constraints.maxWidth); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Managed wallets', + style: theme.textTheme.titleLarge?.copyWith( + color: Palette.ink, + fontWeight: FontWeight.w800, + ), + ), + SizedBox(height: 0.6.h), + Text( + 'Every address here is generated and held by Arbiter.', + style: theme.textTheme.bodyMedium?.copyWith( + color: Palette.ink.withValues(alpha: 0.70), + height: 1.4, + ), + ), + SizedBox(height: 1.6.h), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SizedBox( + width: tableWidth, + child: Column( + children: [ + const _WalletTableHeader(), + SizedBox(height: 1.h), + for (var i = 0; i < wallets.length; i++) + Padding( + padding: EdgeInsets.only( + bottom: i == wallets.length - 1 ? 0 : 1.h, + ), + child: _WalletTableRow(wallet: wallets[i], index: i), + ), + ], + ), + ), + ), + ], + ); + }, + ), + ); + } +} + +class _WalletTableHeader extends StatelessWidget { + const _WalletTableHeader(); + + @override + Widget build(BuildContext context) { + final style = Theme.of(context).textTheme.labelLarge?.copyWith( + color: Palette.ink.withValues(alpha: 0.72), + fontWeight: FontWeight.w800, + letterSpacing: 0.3, + ); + + return Container( + padding: EdgeInsets.symmetric(vertical: 1.4.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: Palette.ink.withValues(alpha: 0.04), + ), + child: Row( + children: [ + SizedBox(width: _accentStripWidth + _cellHorizontalPadding), + SizedBox( + width: _walletColumnWidth, + child: Text('Wallet', style: style), + ), + SizedBox(width: _columnGap), + Expanded(child: Text('Address', style: style)), + SizedBox(width: _cellHorizontalPadding), + ], + ), + ); + } +} + +class _WalletTableRow extends StatelessWidget { + const _WalletTableRow({required this.wallet, required this.index}); + + final WalletEntry wallet; + final int index; + + @override + Widget build(BuildContext context) { + final accent = _accentColor(wallet.address); + final address = _hexAddress(wallet.address); + final rowHeight = 5.h; + final walletStyle = Theme.of( + context, + ).textTheme.bodyLarge?.copyWith(color: Palette.ink); + final addressStyle = Theme.of( + context, + ).textTheme.bodyMedium?.copyWith(color: Palette.ink); + + return Container( + height: rowHeight, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(18), + color: accent.withValues(alpha: 0.10), + border: Border.all(color: accent.withValues(alpha: 0.28)), + ), + child: Row( + children: [ + Container( + width: _accentStripWidth, + height: rowHeight, + decoration: BoxDecoration( + color: accent, + borderRadius: const BorderRadius.horizontal( + left: Radius.circular(18), + ), + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: _cellHorizontalPadding), + child: Row( + children: [ + SizedBox( + width: _walletColumnWidth, + child: Row( + children: [ + Container( + width: 1.2.h, + height: 1.2.h, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: accent, + ), + ), + SizedBox(width: 1.w), + Text( + 'Wallet ${(index + 1).toString().padLeft(2, '0')}', + style: walletStyle, + ), + ], + ), + ), + SizedBox(width: _columnGap), + Expanded( + child: Text( + address, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: addressStyle, + ), + ), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/useragent/lib/screens/server_connection.dart b/useragent/lib/screens/server_connection.dart index 9f8e851..8a88f9f 100644 --- a/useragent/lib/screens/server_connection.dart +++ b/useragent/lib/screens/server_connection.dart @@ -1,59 +1,59 @@ -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:arbiter/router.gr.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -@RoutePage() -class ServerConnectionScreen extends HookConsumerWidget { - const ServerConnectionScreen({super.key, this.arbiterUrl}); - - final String? arbiterUrl; - - @override - Widget build(BuildContext context, WidgetRef ref) { - final connectionState = ref.watch(connectionManagerProvider); - - ref.listen(connectionManagerProvider, (_, next) { - if (next.value != null && context.mounted) { - context.router.replace(const VaultSetupRoute()); - } - }); - - final body = switch (connectionState) { - AsyncLoading() => const CircularProgressIndicator(), - AsyncError(:final error) => Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - 'Connection failed', - style: Theme.of(context).textTheme.headlineSmall, - textAlign: TextAlign.center, - ), - SizedBox(height: 1.5.h), - Text('$error', textAlign: TextAlign.center), - SizedBox(height: 2.h), - - TextButton( - onPressed: () { - context.router.replace(const ServerInfoSetupRoute()); - }, - child: const Text('Back to server setup'), - ), - ], - ), - _ => const CircularProgressIndicator(), - }; - - return Scaffold( - appBar: AppBar(title: const Text('Connecting')), - body: Center( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 8.w), - child: body, - ), - ), - ); - } -} +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:arbiter/router.gr.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +@RoutePage() +class ServerConnectionScreen extends HookConsumerWidget { + const ServerConnectionScreen({super.key, this.arbiterUrl}); + + final String? arbiterUrl; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final connectionState = ref.watch(connectionManagerProvider); + + ref.listen(connectionManagerProvider, (_, next) { + if (next.value != null && context.mounted) { + context.router.replace(const VaultSetupRoute()); + } + }); + + final body = switch (connectionState) { + AsyncLoading() => const CircularProgressIndicator(), + AsyncError(:final error) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Connection failed', + style: Theme.of(context).textTheme.headlineSmall, + textAlign: TextAlign.center, + ), + SizedBox(height: 1.5.h), + Text('$error', textAlign: TextAlign.center), + SizedBox(height: 2.h), + + TextButton( + onPressed: () { + context.router.replace(const ServerInfoSetupRoute()); + }, + child: const Text('Back to server setup'), + ), + ], + ), + _ => const CircularProgressIndicator(), + }; + + return Scaffold( + appBar: AppBar(title: const Text('Connecting')), + body: Center( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 8.w), + child: body, + ), + ), + ); + } +} diff --git a/useragent/lib/screens/server_info_setup.dart b/useragent/lib/screens/server_info_setup.dart index 99c319a..af7dd3f 100644 --- a/useragent/lib/screens/server_info_setup.dart +++ b/useragent/lib/screens/server_info_setup.dart @@ -1,294 +1,294 @@ -import 'package:arbiter/features/connection/arbiter_url.dart'; -import 'package:arbiter/features/connection/server_info_storage.dart'; -import 'package:arbiter/providers/connection/bootstrap_token.dart'; -import 'package:arbiter/providers/server_info.dart'; -import 'package:arbiter/router.gr.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -@RoutePage() -class ServerInfoSetupScreen extends HookConsumerWidget { - const ServerInfoSetupScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final storedServerInfo = ref.watch(serverInfoProvider); - final resolvedServerInfo = storedServerInfo.asData?.value; - final controller = useTextEditingController(); - final errorText = useState(null); - final isSaving = useState(false); - - useEffect(() { - final serverInfo = resolvedServerInfo; - if (serverInfo != null) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (context.mounted) { - context.router.replace(ServerConnectionRoute()); - } - }); - } - return null; - }, [context, resolvedServerInfo]); - - Future saveRemoteServerInfo() async { - errorText.value = null; - isSaving.value = true; - - try { - final arbiterUrl = ArbiterUrl.parse(controller.text.trim()); - - // set token before triggering reconnection by updating server info - if (arbiterUrl.bootstrapToken != null) { - ref - .read(bootstrapTokenProvider.notifier) - .set(arbiterUrl.bootstrapToken!); - } - - await ref - .read(serverInfoProvider.notifier) - .save( - address: arbiterUrl.host, - port: arbiterUrl.port, - caCert: arbiterUrl.caCert, - ); - - if (context.mounted) { - context.router.replace( - ServerConnectionRoute(arbiterUrl: controller.text.trim()), - ); - } - } on FormatException catch (error) { - errorText.value = error.message; - } catch (_) { - errorText.value = 'Failed to store connection settings.'; - } finally { - isSaving.value = false; - } - } - - if (storedServerInfo.isLoading) { - return const Scaffold(body: Center(child: CircularProgressIndicator())); - } - - if (storedServerInfo.hasError) { - return Scaffold( - appBar: AppBar(title: const Text('Server Info Setup')), - body: Center( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 6.w), - child: Text( - 'Failed to load stored server info.', - style: Theme.of(context).textTheme.bodyLarge, - textAlign: TextAlign.center, - ), - ), - ), - ); - } - - final serverInfo = resolvedServerInfo; - if (serverInfo != null) { - return _RedirectingView(serverInfo: serverInfo); - } - - return Scaffold( - appBar: AppBar(title: const Text('Server Info Setup')), - body: LayoutBuilder( - builder: (context, constraints) { - final useRowLayout = constraints.maxWidth > constraints.maxHeight; - final gap = 2.h; - final horizontalPadding = 6.w; - final verticalPadding = 3.h; - final options = [ - const _OptionCard( - title: 'Local', - subtitle: - 'Will start and connect to a local service in a future update.', - enabled: false, - child: SizedBox.shrink(), - ), - _OptionCard( - title: 'Remote', - subtitle: - 'Paste an Arbiter URL to store the server address, port, and CA fingerprint.', - child: _RemoteConnectionForm( - controller: controller, - errorText: errorText.value, - isSaving: isSaving.value, - onSave: saveRemoteServerInfo, - ), - ), - ]; - - return ListView( - padding: EdgeInsets.symmetric( - horizontal: horizontalPadding, - vertical: verticalPadding, - ), - children: [ - _SetupHeader(gap: gap), - SizedBox(height: gap), - useRowLayout - ? Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded(child: options[0]), - SizedBox(width: 3.w), - Expanded(child: options[1]), - ], - ) - : Column( - children: [ - options[0], - SizedBox(height: gap), - options[1], - ], - ), - ], - ); - }, - ), - ); - } -} - -class _SetupHeader extends StatelessWidget { - const _SetupHeader({required this.gap}); - - final double gap; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Choose how this user agent should reach Arbiter.', - style: Theme.of(context).textTheme.headlineSmall, - ), - SizedBox(height: gap * 0.5), - Text( - 'Remote accepts the shareable Arbiter URL emitted by the server.', - style: Theme.of(context).textTheme.bodyMedium, - ), - ], - ); - } -} - -class _RedirectingView extends StatelessWidget { - const _RedirectingView({required this.serverInfo}); - - final StoredServerInfo serverInfo; - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const CircularProgressIndicator(), - SizedBox(height: 2.h), - Text('Using saved server ${serverInfo.address}:${serverInfo.port}'), - ], - ), - ), - ); - } -} - -class _RemoteConnectionForm extends StatelessWidget { - const _RemoteConnectionForm({ - required this.controller, - required this.errorText, - required this.isSaving, - required this.onSave, - }); - - final TextEditingController controller; - final String? errorText; - final bool isSaving; - final VoidCallback onSave; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextField( - controller: controller, - decoration: const InputDecoration( - border: OutlineInputBorder(), - labelText: 'Arbiter URL', - hintText: 'arbiter://host:port?cert=...', - ), - minLines: 2, - maxLines: 4, - ), - if (errorText != null) ...[ - SizedBox(height: 1.5.h), - Text( - errorText!, - style: TextStyle(color: Theme.of(context).colorScheme.error), - ), - ], - SizedBox(height: 2.h), - Align( - alignment: Alignment.centerLeft, - child: FilledButton( - onPressed: isSaving ? null : onSave, - child: Text(isSaving ? 'Saving...' : 'Save connection'), - ), - ), - ], - ); - } -} - -class _OptionCard extends StatelessWidget { - const _OptionCard({ - required this.title, - required this.subtitle, - required this.child, - this.enabled = true, - }); - - final String title; - final String subtitle; - final Widget child; - final bool enabled; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return Card( - child: Padding( - padding: EdgeInsets.all(2.h), - child: Opacity( - opacity: enabled ? 1 : 0.55, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Text(title, style: theme.textTheme.titleLarge), - if (!enabled) ...[ - SizedBox(width: 2.w), - const Chip(label: Text('Coming soon')), - ], - ], - ), - SizedBox(height: 1.h), - Text(subtitle, style: theme.textTheme.bodyMedium), - if (enabled) ...[SizedBox(height: 2.h), child], - ], - ), - ), - ), - ); - } -} +import 'package:arbiter/features/connection/arbiter_url.dart'; +import 'package:arbiter/features/connection/server_info_storage.dart'; +import 'package:arbiter/providers/connection/bootstrap_token.dart'; +import 'package:arbiter/providers/server_info.dart'; +import 'package:arbiter/router.gr.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +@RoutePage() +class ServerInfoSetupScreen extends HookConsumerWidget { + const ServerInfoSetupScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final storedServerInfo = ref.watch(serverInfoProvider); + final resolvedServerInfo = storedServerInfo.asData?.value; + final controller = useTextEditingController(); + final errorText = useState(null); + final isSaving = useState(false); + + useEffect(() { + final serverInfo = resolvedServerInfo; + if (serverInfo != null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (context.mounted) { + context.router.replace(ServerConnectionRoute()); + } + }); + } + return null; + }, [context, resolvedServerInfo]); + + Future saveRemoteServerInfo() async { + errorText.value = null; + isSaving.value = true; + + try { + final arbiterUrl = ArbiterUrl.parse(controller.text.trim()); + + // set token before triggering reconnection by updating server info + if (arbiterUrl.bootstrapToken != null) { + ref + .read(bootstrapTokenProvider.notifier) + .set(arbiterUrl.bootstrapToken!); + } + + await ref + .read(serverInfoProvider.notifier) + .save( + address: arbiterUrl.host, + port: arbiterUrl.port, + caCert: arbiterUrl.caCert, + ); + + if (context.mounted) { + context.router.replace( + ServerConnectionRoute(arbiterUrl: controller.text.trim()), + ); + } + } on FormatException catch (error) { + errorText.value = error.message; + } catch (_) { + errorText.value = 'Failed to store connection settings.'; + } finally { + isSaving.value = false; + } + } + + if (storedServerInfo.isLoading) { + return const Scaffold(body: Center(child: CircularProgressIndicator())); + } + + if (storedServerInfo.hasError) { + return Scaffold( + appBar: AppBar(title: const Text('Server Info Setup')), + body: Center( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 6.w), + child: Text( + 'Failed to load stored server info.', + style: Theme.of(context).textTheme.bodyLarge, + textAlign: TextAlign.center, + ), + ), + ), + ); + } + + final serverInfo = resolvedServerInfo; + if (serverInfo != null) { + return _RedirectingView(serverInfo: serverInfo); + } + + return Scaffold( + appBar: AppBar(title: const Text('Server Info Setup')), + body: LayoutBuilder( + builder: (context, constraints) { + final useRowLayout = constraints.maxWidth > constraints.maxHeight; + final gap = 2.h; + final horizontalPadding = 6.w; + final verticalPadding = 3.h; + final options = [ + const _OptionCard( + title: 'Local', + subtitle: + 'Will start and connect to a local service in a future update.', + enabled: false, + child: SizedBox.shrink(), + ), + _OptionCard( + title: 'Remote', + subtitle: + 'Paste an Arbiter URL to store the server address, port, and CA fingerprint.', + child: _RemoteConnectionForm( + controller: controller, + errorText: errorText.value, + isSaving: isSaving.value, + onSave: saveRemoteServerInfo, + ), + ), + ]; + + return ListView( + padding: EdgeInsets.symmetric( + horizontal: horizontalPadding, + vertical: verticalPadding, + ), + children: [ + _SetupHeader(gap: gap), + SizedBox(height: gap), + useRowLayout + ? Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded(child: options[0]), + SizedBox(width: 3.w), + Expanded(child: options[1]), + ], + ) + : Column( + children: [ + options[0], + SizedBox(height: gap), + options[1], + ], + ), + ], + ); + }, + ), + ); + } +} + +class _SetupHeader extends StatelessWidget { + const _SetupHeader({required this.gap}); + + final double gap; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Choose how this user agent should reach Arbiter.', + style: Theme.of(context).textTheme.headlineSmall, + ), + SizedBox(height: gap * 0.5), + Text( + 'Remote accepts the shareable Arbiter URL emitted by the server.', + style: Theme.of(context).textTheme.bodyMedium, + ), + ], + ); + } +} + +class _RedirectingView extends StatelessWidget { + const _RedirectingView({required this.serverInfo}); + + final StoredServerInfo serverInfo; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const CircularProgressIndicator(), + SizedBox(height: 2.h), + Text('Using saved server ${serverInfo.address}:${serverInfo.port}'), + ], + ), + ), + ); + } +} + +class _RemoteConnectionForm extends StatelessWidget { + const _RemoteConnectionForm({ + required this.controller, + required this.errorText, + required this.isSaving, + required this.onSave, + }); + + final TextEditingController controller; + final String? errorText; + final bool isSaving; + final VoidCallback onSave; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextField( + controller: controller, + decoration: const InputDecoration( + border: OutlineInputBorder(), + labelText: 'Arbiter URL', + hintText: 'arbiter://host:port?cert=...', + ), + minLines: 2, + maxLines: 4, + ), + if (errorText != null) ...[ + SizedBox(height: 1.5.h), + Text( + errorText!, + style: TextStyle(color: Theme.of(context).colorScheme.error), + ), + ], + SizedBox(height: 2.h), + Align( + alignment: Alignment.centerLeft, + child: FilledButton( + onPressed: isSaving ? null : onSave, + child: Text(isSaving ? 'Saving...' : 'Save connection'), + ), + ), + ], + ); + } +} + +class _OptionCard extends StatelessWidget { + const _OptionCard({ + required this.title, + required this.subtitle, + required this.child, + this.enabled = true, + }); + + final String title; + final String subtitle; + final Widget child; + final bool enabled; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Card( + child: Padding( + padding: EdgeInsets.all(2.h), + child: Opacity( + opacity: enabled ? 1 : 0.55, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text(title, style: theme.textTheme.titleLarge), + if (!enabled) ...[ + SizedBox(width: 2.w), + const Chip(label: Text('Coming soon')), + ], + ], + ), + SizedBox(height: 1.h), + Text(subtitle, style: theme.textTheme.bodyMedium), + if (enabled) ...[SizedBox(height: 2.h), child], + ], + ), + ), + ), + ); + } +} diff --git a/useragent/lib/screens/vault_setup.dart b/useragent/lib/screens/vault_setup.dart index 8f306ba..bac55b0 100644 --- a/useragent/lib/screens/vault_setup.dart +++ b/useragent/lib/screens/vault_setup.dart @@ -1,410 +1,410 @@ -import 'package:arbiter/features/connection/vault.dart'; -import 'package:arbiter/proto/shared/vault.pbenum.dart'; -import 'package:arbiter/proto/user_agent/vault/bootstrap.pbenum.dart'; -import 'package:arbiter/proto/user_agent/vault/unseal.pbenum.dart'; -import 'package:arbiter/providers/connection/connection_manager.dart'; -import 'package:arbiter/providers/vault_state.dart'; -import 'package:arbiter/router.gr.dart'; -import 'package:arbiter/widgets/bottom_popup.dart'; -import 'package:auto_route/auto_route.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:sizer/sizer.dart'; - -@RoutePage() -class VaultSetupScreen extends HookConsumerWidget { - const VaultSetupScreen({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final vaultState = ref.watch(vaultStateProvider); - final bootstrapPasswordController = useTextEditingController(); - final bootstrapConfirmController = useTextEditingController(); - final unsealPasswordController = useTextEditingController(); - final errorText = useState(null); - final isSubmitting = useState(false); - - useEffect(() { - if (vaultState.asData?.value == VaultState.VAULT_STATE_UNSEALED) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (context.mounted) { - context.router.replace(const DashboardRouter()); - } - }); - } - - return null; - }, [context, vaultState.asData?.value]); - - Future refreshVaultState() async { - ref.invalidate(vaultStateProvider); - await ref.read(vaultStateProvider.future); - } - - Future submitBootstrap() async { - final password = bootstrapPasswordController.text; - final confirmation = bootstrapConfirmController.text; - - if (password.isEmpty || confirmation.isEmpty) { - errorText.value = 'Enter the password twice.'; - return; - } - - if (password != confirmation) { - errorText.value = 'Passwords do not match.'; - return; - } - - final confirmed = await showBottomPopup( - context: context, - builder: (popupContext) { - return _WarningPopup( - title: 'Bootstrap vault?', - body: - 'This password cannot be recovered. If you lose it, the vault cannot be unsealed.', - confirmLabel: 'Bootstrap', - onCancel: () => Navigator.of(popupContext).pop(false), - onConfirm: () => Navigator.of(popupContext).pop(true), - ); - }, - ); - - if (confirmed != true) { - return; - } - - errorText.value = null; - isSubmitting.value = true; - - try { - final connection = await ref.read(connectionManagerProvider.future); - if (connection == null) { - throw Exception('Not connected to the server.'); - } - - final result = await bootstrapVault(connection, password); - switch (result) { - case BootstrapResult.BOOTSTRAP_RESULT_SUCCESS: - bootstrapPasswordController.clear(); - bootstrapConfirmController.clear(); - await refreshVaultState(); - break; - case BootstrapResult.BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED: - errorText.value = - 'The vault was already bootstrapped. Refreshing vault state.'; - await refreshVaultState(); - break; - case BootstrapResult.BOOTSTRAP_RESULT_INVALID_KEY: - case BootstrapResult.BOOTSTRAP_RESULT_UNSPECIFIED: - errorText.value = 'Failed to bootstrap the vault.'; - break; - } - } catch (error) { - errorText.value = _formatVaultError(error); - } finally { - isSubmitting.value = false; - } - } - - Future submitUnseal() async { - final password = unsealPasswordController.text; - if (password.isEmpty) { - errorText.value = 'Enter the vault password.'; - return; - } - - errorText.value = null; - isSubmitting.value = true; - - try { - final connection = await ref.read(connectionManagerProvider.future); - if (connection == null) { - throw Exception('Not connected to the server.'); - } - - final result = await unsealVault(connection, password); - switch (result) { - case UnsealResult.UNSEAL_RESULT_SUCCESS: - unsealPasswordController.clear(); - await refreshVaultState(); - break; - case UnsealResult.UNSEAL_RESULT_INVALID_KEY: - errorText.value = 'Incorrect password.'; - break; - case UnsealResult.UNSEAL_RESULT_UNBOOTSTRAPPED: - errorText.value = - 'The vault is not bootstrapped yet. Refreshing vault state.'; - await refreshVaultState(); - break; - case UnsealResult.UNSEAL_RESULT_UNSPECIFIED: - errorText.value = 'Failed to unseal the vault.'; - break; - } - } catch (error) { - errorText.value = _formatVaultError(error); - } finally { - isSubmitting.value = false; - } - } - - final body = switch (vaultState) { - AsyncLoading() => const Center(child: CircularProgressIndicator()), - AsyncError(:final error) => _VaultCard( - title: 'Vault unavailable', - subtitle: _formatVaultError(error), - child: FilledButton( - onPressed: () => ref.invalidate(vaultStateProvider), - child: const Text('Retry'), - ), - ), - AsyncData(:final value) => switch (value) { - VaultState.VAULT_STATE_UNBOOTSTRAPPED => _VaultCard( - title: 'Create vault password', - subtitle: - 'Choose the password that will be required to unseal this vault.', - child: _PasswordForm( - errorText: errorText.value, - isSubmitting: isSubmitting.value, - submitLabel: 'Bootstrap vault', - onSubmit: submitBootstrap, - fields: [ - _PasswordFieldConfig( - controller: bootstrapPasswordController, - label: 'Password', - textInputAction: TextInputAction.next, - ), - _PasswordFieldConfig( - controller: bootstrapConfirmController, - label: 'Confirm password', - textInputAction: TextInputAction.done, - onSubmitted: (_) => submitBootstrap(), - ), - ], - ), - ), - VaultState.VAULT_STATE_SEALED => _VaultCard( - title: 'Unseal vault', - subtitle: 'Enter the vault password to continue.', - child: _PasswordForm( - errorText: errorText.value, - isSubmitting: isSubmitting.value, - submitLabel: 'Unseal vault', - onSubmit: submitUnseal, - fields: [ - _PasswordFieldConfig( - controller: unsealPasswordController, - label: 'Password', - textInputAction: TextInputAction.done, - onSubmitted: (_) => submitUnseal(), - ), - ], - ), - ), - VaultState.VAULT_STATE_UNSEALED => const Center( - child: CircularProgressIndicator(), - ), - VaultState.VAULT_STATE_ERROR => _VaultCard( - title: 'Vault state unavailable', - subtitle: 'Unable to determine the current vault state.', - child: FilledButton( - onPressed: () => ref.invalidate(vaultStateProvider), - child: const Text('Retry'), - ), - ), - VaultState.VAULT_STATE_UNSPECIFIED => _VaultCard( - title: 'Vault state unavailable', - subtitle: 'Unable to determine the current vault state.', - child: FilledButton( - onPressed: () => ref.invalidate(vaultStateProvider), - child: const Text('Retry'), - ), - ), - null => _VaultCard( - title: 'Vault state unavailable', - subtitle: 'Unable to determine the current vault state.', - child: FilledButton( - onPressed: () => ref.invalidate(vaultStateProvider), - child: const Text('Retry'), - ), - ), - _ => _VaultCard( - title: 'Vault state unavailable', - subtitle: 'Unable to determine the current vault state.', - child: FilledButton( - onPressed: () => ref.invalidate(vaultStateProvider), - child: const Text('Retry'), - ), - ), - }, - }; - - return Scaffold( - appBar: AppBar(title: const Text('Vault Setup')), - body: Center( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 6.w, vertical: 3.h), - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 520), - child: body, - ), - ), - ), - ); - } -} - -class _VaultCard extends StatelessWidget { - const _VaultCard({ - required this.title, - required this.subtitle, - required this.child, - }); - - final String title; - final String subtitle; - final Widget child; - - @override - Widget build(BuildContext context) { - return Card( - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(title, style: Theme.of(context).textTheme.headlineSmall), - const SizedBox(height: 12), - Text(subtitle, style: Theme.of(context).textTheme.bodyMedium), - const SizedBox(height: 24), - child, - ], - ), - ), - ); - } -} - -class _PasswordForm extends StatelessWidget { - const _PasswordForm({ - required this.fields, - required this.errorText, - required this.isSubmitting, - required this.submitLabel, - required this.onSubmit, - }); - - final List<_PasswordFieldConfig> fields; - final String? errorText; - final bool isSubmitting; - final String submitLabel; - final Future Function() onSubmit; - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - for (final field in fields) ...[ - TextField( - controller: field.controller, - obscureText: true, - enableSuggestions: false, - autocorrect: false, - textInputAction: field.textInputAction, - onSubmitted: field.onSubmitted, - decoration: InputDecoration( - border: const OutlineInputBorder(), - labelText: field.label, - ), - ), - const SizedBox(height: 16), - ], - if (errorText != null) ...[ - Text( - errorText!, - style: TextStyle(color: Theme.of(context).colorScheme.error), - ), - const SizedBox(height: 16), - ], - Align( - alignment: Alignment.centerLeft, - child: FilledButton( - onPressed: isSubmitting ? null : () => onSubmit(), - child: Text(isSubmitting ? 'Working...' : submitLabel), - ), - ), - ], - ); - } -} - -class _PasswordFieldConfig { - const _PasswordFieldConfig({ - required this.controller, - required this.label, - required this.textInputAction, - this.onSubmitted, - }); - - final TextEditingController controller; - final String label; - final TextInputAction textInputAction; - final ValueChanged? onSubmitted; -} - -class _WarningPopup extends StatelessWidget { - const _WarningPopup({ - required this.title, - required this.body, - required this.confirmLabel, - required this.onCancel, - required this.onConfirm, - }); - - final String title; - final String body; - final String confirmLabel; - final VoidCallback onCancel; - final VoidCallback onConfirm; - - @override - Widget build(BuildContext context) { - return Material( - color: Theme.of(context).colorScheme.surface, - borderRadius: BorderRadius.circular(24), - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(title, style: Theme.of(context).textTheme.titleLarge), - const SizedBox(height: 12), - Text(body, style: Theme.of(context).textTheme.bodyMedium), - const SizedBox(height: 24), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton(onPressed: onCancel, child: const Text('Cancel')), - const SizedBox(width: 12), - FilledButton(onPressed: onConfirm, child: Text(confirmLabel)), - ], - ), - ], - ), - ), - ); - } -} - -String _formatVaultError(Object error) { - final message = error.toString(); - - if (message.contains('GrpcError')) { - return 'The server rejected the vault request. Check the password and try again.'; - } - - return message.replaceFirst('Exception: ', ''); -} +import 'package:arbiter/features/connection/vault.dart'; +import 'package:arbiter/proto/shared/vault.pbenum.dart'; +import 'package:arbiter/proto/user_agent/vault/bootstrap.pbenum.dart'; +import 'package:arbiter/proto/user_agent/vault/unseal.pbenum.dart'; +import 'package:arbiter/providers/connection/connection_manager.dart'; +import 'package:arbiter/providers/vault_state.dart'; +import 'package:arbiter/router.gr.dart'; +import 'package:arbiter/widgets/bottom_popup.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:sizer/sizer.dart'; + +@RoutePage() +class VaultSetupScreen extends HookConsumerWidget { + const VaultSetupScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final vaultState = ref.watch(vaultStateProvider); + final bootstrapPasswordController = useTextEditingController(); + final bootstrapConfirmController = useTextEditingController(); + final unsealPasswordController = useTextEditingController(); + final errorText = useState(null); + final isSubmitting = useState(false); + + useEffect(() { + if (vaultState.asData?.value == VaultState.VAULT_STATE_UNSEALED) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (context.mounted) { + context.router.replace(const DashboardRouter()); + } + }); + } + + return null; + }, [context, vaultState.asData?.value]); + + Future refreshVaultState() async { + ref.invalidate(vaultStateProvider); + await ref.read(vaultStateProvider.future); + } + + Future submitBootstrap() async { + final password = bootstrapPasswordController.text; + final confirmation = bootstrapConfirmController.text; + + if (password.isEmpty || confirmation.isEmpty) { + errorText.value = 'Enter the password twice.'; + return; + } + + if (password != confirmation) { + errorText.value = 'Passwords do not match.'; + return; + } + + final confirmed = await showBottomPopup( + context: context, + builder: (popupContext) { + return _WarningPopup( + title: 'Bootstrap vault?', + body: + 'This password cannot be recovered. If you lose it, the vault cannot be unsealed.', + confirmLabel: 'Bootstrap', + onCancel: () => Navigator.of(popupContext).pop(false), + onConfirm: () => Navigator.of(popupContext).pop(true), + ); + }, + ); + + if (confirmed != true) { + return; + } + + errorText.value = null; + isSubmitting.value = true; + + try { + final connection = await ref.read(connectionManagerProvider.future); + if (connection == null) { + throw Exception('Not connected to the server.'); + } + + final result = await bootstrapVault(connection, password); + switch (result) { + case BootstrapResult.BOOTSTRAP_RESULT_SUCCESS: + bootstrapPasswordController.clear(); + bootstrapConfirmController.clear(); + await refreshVaultState(); + break; + case BootstrapResult.BOOTSTRAP_RESULT_ALREADY_BOOTSTRAPPED: + errorText.value = + 'The vault was already bootstrapped. Refreshing vault state.'; + await refreshVaultState(); + break; + case BootstrapResult.BOOTSTRAP_RESULT_INVALID_KEY: + case BootstrapResult.BOOTSTRAP_RESULT_UNSPECIFIED: + errorText.value = 'Failed to bootstrap the vault.'; + break; + } + } catch (error) { + errorText.value = _formatVaultError(error); + } finally { + isSubmitting.value = false; + } + } + + Future submitUnseal() async { + final password = unsealPasswordController.text; + if (password.isEmpty) { + errorText.value = 'Enter the vault password.'; + return; + } + + errorText.value = null; + isSubmitting.value = true; + + try { + final connection = await ref.read(connectionManagerProvider.future); + if (connection == null) { + throw Exception('Not connected to the server.'); + } + + final result = await unsealVault(connection, password); + switch (result) { + case UnsealResult.UNSEAL_RESULT_SUCCESS: + unsealPasswordController.clear(); + await refreshVaultState(); + break; + case UnsealResult.UNSEAL_RESULT_INVALID_KEY: + errorText.value = 'Incorrect password.'; + break; + case UnsealResult.UNSEAL_RESULT_UNBOOTSTRAPPED: + errorText.value = + 'The vault is not bootstrapped yet. Refreshing vault state.'; + await refreshVaultState(); + break; + case UnsealResult.UNSEAL_RESULT_UNSPECIFIED: + errorText.value = 'Failed to unseal the vault.'; + break; + } + } catch (error) { + errorText.value = _formatVaultError(error); + } finally { + isSubmitting.value = false; + } + } + + final body = switch (vaultState) { + AsyncLoading() => const Center(child: CircularProgressIndicator()), + AsyncError(:final error) => _VaultCard( + title: 'Vault unavailable', + subtitle: _formatVaultError(error), + child: FilledButton( + onPressed: () => ref.invalidate(vaultStateProvider), + child: const Text('Retry'), + ), + ), + AsyncData(:final value) => switch (value) { + VaultState.VAULT_STATE_UNBOOTSTRAPPED => _VaultCard( + title: 'Create vault password', + subtitle: + 'Choose the password that will be required to unseal this vault.', + child: _PasswordForm( + errorText: errorText.value, + isSubmitting: isSubmitting.value, + submitLabel: 'Bootstrap vault', + onSubmit: submitBootstrap, + fields: [ + _PasswordFieldConfig( + controller: bootstrapPasswordController, + label: 'Password', + textInputAction: TextInputAction.next, + ), + _PasswordFieldConfig( + controller: bootstrapConfirmController, + label: 'Confirm password', + textInputAction: TextInputAction.done, + onSubmitted: (_) => submitBootstrap(), + ), + ], + ), + ), + VaultState.VAULT_STATE_SEALED => _VaultCard( + title: 'Unseal vault', + subtitle: 'Enter the vault password to continue.', + child: _PasswordForm( + errorText: errorText.value, + isSubmitting: isSubmitting.value, + submitLabel: 'Unseal vault', + onSubmit: submitUnseal, + fields: [ + _PasswordFieldConfig( + controller: unsealPasswordController, + label: 'Password', + textInputAction: TextInputAction.done, + onSubmitted: (_) => submitUnseal(), + ), + ], + ), + ), + VaultState.VAULT_STATE_UNSEALED => const Center( + child: CircularProgressIndicator(), + ), + VaultState.VAULT_STATE_ERROR => _VaultCard( + title: 'Vault state unavailable', + subtitle: 'Unable to determine the current vault state.', + child: FilledButton( + onPressed: () => ref.invalidate(vaultStateProvider), + child: const Text('Retry'), + ), + ), + VaultState.VAULT_STATE_UNSPECIFIED => _VaultCard( + title: 'Vault state unavailable', + subtitle: 'Unable to determine the current vault state.', + child: FilledButton( + onPressed: () => ref.invalidate(vaultStateProvider), + child: const Text('Retry'), + ), + ), + null => _VaultCard( + title: 'Vault state unavailable', + subtitle: 'Unable to determine the current vault state.', + child: FilledButton( + onPressed: () => ref.invalidate(vaultStateProvider), + child: const Text('Retry'), + ), + ), + _ => _VaultCard( + title: 'Vault state unavailable', + subtitle: 'Unable to determine the current vault state.', + child: FilledButton( + onPressed: () => ref.invalidate(vaultStateProvider), + child: const Text('Retry'), + ), + ), + }, + }; + + return Scaffold( + appBar: AppBar(title: const Text('Vault Setup')), + body: Center( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 6.w, vertical: 3.h), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 520), + child: body, + ), + ), + ), + ); + } +} + +class _VaultCard extends StatelessWidget { + const _VaultCard({ + required this.title, + required this.subtitle, + required this.child, + }); + + final String title; + final String subtitle; + final Widget child; + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, style: Theme.of(context).textTheme.headlineSmall), + const SizedBox(height: 12), + Text(subtitle, style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 24), + child, + ], + ), + ), + ); + } +} + +class _PasswordForm extends StatelessWidget { + const _PasswordForm({ + required this.fields, + required this.errorText, + required this.isSubmitting, + required this.submitLabel, + required this.onSubmit, + }); + + final List<_PasswordFieldConfig> fields; + final String? errorText; + final bool isSubmitting; + final String submitLabel; + final Future Function() onSubmit; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + for (final field in fields) ...[ + TextField( + controller: field.controller, + obscureText: true, + enableSuggestions: false, + autocorrect: false, + textInputAction: field.textInputAction, + onSubmitted: field.onSubmitted, + decoration: InputDecoration( + border: const OutlineInputBorder(), + labelText: field.label, + ), + ), + const SizedBox(height: 16), + ], + if (errorText != null) ...[ + Text( + errorText!, + style: TextStyle(color: Theme.of(context).colorScheme.error), + ), + const SizedBox(height: 16), + ], + Align( + alignment: Alignment.centerLeft, + child: FilledButton( + onPressed: isSubmitting ? null : () => onSubmit(), + child: Text(isSubmitting ? 'Working...' : submitLabel), + ), + ), + ], + ); + } +} + +class _PasswordFieldConfig { + const _PasswordFieldConfig({ + required this.controller, + required this.label, + required this.textInputAction, + this.onSubmitted, + }); + + final TextEditingController controller; + final String label; + final TextInputAction textInputAction; + final ValueChanged? onSubmitted; +} + +class _WarningPopup extends StatelessWidget { + const _WarningPopup({ + required this.title, + required this.body, + required this.confirmLabel, + required this.onCancel, + required this.onConfirm, + }); + + final String title; + final String body; + final String confirmLabel; + final VoidCallback onCancel; + final VoidCallback onConfirm; + + @override + Widget build(BuildContext context) { + return Material( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(24), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, style: Theme.of(context).textTheme.titleLarge), + const SizedBox(height: 12), + Text(body, style: Theme.of(context).textTheme.bodyMedium), + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton(onPressed: onCancel, child: const Text('Cancel')), + const SizedBox(width: 12), + FilledButton(onPressed: onConfirm, child: Text(confirmLabel)), + ], + ), + ], + ), + ), + ); + } +} + +String _formatVaultError(Object error) { + final message = error.toString(); + + if (message.contains('GrpcError')) { + return 'The server rejected the vault request. Check the password and try again.'; + } + + return message.replaceFirst('Exception: ', ''); +} diff --git a/useragent/lib/src/rust/api.dart b/useragent/lib/src/rust/api.dart index 8648c0e..1002dae 100644 --- a/useragent/lib/src/rust/api.dart +++ b/useragent/lib/src/rust/api.dart @@ -1,30 +1,30 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. - -// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import - -import 'frb_generated.dart'; -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; - -Future formatChallenge({ - required List random, - required PlatformInt64 timestamp, -}) => RustLib.instance.api.crateApiFormatChallenge( - random: random, - timestamp: timestamp, -); - -// Rust type: RustOpaqueMoi> -abstract class MldsaKey implements RustOpaqueInterface { - static Future fromBytes({required List bytes}) => - RustLib.instance.api.crateApiMldsaKeyFromBytes(bytes: bytes); - - static Future generate() => - RustLib.instance.api.crateApiMldsaKeyGenerate(); - - Future getPublicKey(); - - Future sign({required List message}); - - Future toBytes(); -} +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.12.0. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import 'frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +Future formatChallenge({ + required List random, + required PlatformInt64 timestamp, +}) => RustLib.instance.api.crateApiFormatChallenge( + random: random, + timestamp: timestamp, +); + +// Rust type: RustOpaqueMoi> +abstract class MldsaKey implements RustOpaqueInterface { + static Future fromBytes({required List bytes}) => + RustLib.instance.api.crateApiMldsaKeyFromBytes(bytes: bytes); + + static Future generate() => + RustLib.instance.api.crateApiMldsaKeyGenerate(); + + Future getPublicKey(); + + Future sign({required List message}); + + Future toBytes(); +} diff --git a/useragent/lib/src/rust/frb_generated.dart b/useragent/lib/src/rust/frb_generated.dart index fa57ada..b924839 100644 --- a/useragent/lib/src/rust/frb_generated.dart +++ b/useragent/lib/src/rust/frb_generated.dart @@ -1,630 +1,630 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. - -// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field - -import 'api.dart'; -import 'dart:async'; -import 'dart:convert'; -import 'frb_generated.dart'; -import 'frb_generated.io.dart' - if (dart.library.js_interop) 'frb_generated.web.dart'; -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; - -/// Main entrypoint of the Rust API -class RustLib extends BaseEntrypoint { - @internal - static final instance = RustLib._(); - - RustLib._(); - - /// Initialize flutter_rust_bridge - static Future init({ - RustLibApi? api, - BaseHandler? handler, - ExternalLibrary? externalLibrary, - bool forceSameCodegenVersion = true, - }) async { - await instance.initImpl( - api: api, - handler: handler, - externalLibrary: externalLibrary, - forceSameCodegenVersion: forceSameCodegenVersion, - ); - } - - /// Initialize flutter_rust_bridge in mock mode. - /// No libraries for FFI are loaded. - static void initMock({required RustLibApi api}) { - instance.initMockImpl(api: api); - } - - /// Dispose flutter_rust_bridge - /// - /// The call to this function is optional, since flutter_rust_bridge (and everything else) - /// is automatically disposed when the app stops. - static void dispose() => instance.disposeImpl(); - - @override - ApiImplConstructor get apiImplConstructor => - RustLibApiImpl.new; - - @override - WireConstructor get wireConstructor => - RustLibWire.fromExternalLibrary; - - @override - Future executeRustInitializers() async {} - - @override - ExternalLibraryLoaderConfig get defaultExternalLibraryLoaderConfig => - kDefaultExternalLibraryLoaderConfig; - - @override - String get codegenVersion => '2.12.0'; - - @override - int get rustContentHash => 1247923898; - - static const kDefaultExternalLibraryLoaderConfig = - ExternalLibraryLoaderConfig( - stem: 'rust_lib_arbiter', - ioDirectory: 'rust/target/release/', - webPrefix: 'pkg/', - wasmBindgenName: 'wasm_bindgen', - ); -} - -abstract class RustLibApi extends BaseApi { - Future crateApiMldsaKeyFromBytes({required List bytes}); - - Future crateApiMldsaKeyGenerate(); - - Future crateApiMldsaKeyGetPublicKey({required MldsaKey that}); - - Future crateApiMldsaKeySign({ - required MldsaKey that, - required List message, - }); - - Future crateApiMldsaKeyToBytes({required MldsaKey that}); - - Future crateApiFormatChallenge({ - required List random, - required PlatformInt64 timestamp, - }); - - RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_MldsaKey; - - RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_MldsaKey; - - CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MldsaKeyPtr; -} - -class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { - RustLibApiImpl({ - required super.handler, - required super.wire, - required super.generalizedFrbRustBinding, - required super.portManager, - }); - - @override - Future crateApiMldsaKeyFromBytes({required List bytes}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_8_loose(bytes, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 1, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMldsaKeyFromBytesConstMeta, - argValues: [bytes], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMldsaKeyFromBytesConstMeta => const TaskConstMeta( - debugName: "MldsaKey_from_bytes", - argNames: ["bytes"], - ); - - @override - Future crateApiMldsaKeyGenerate() { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 2, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey, - decodeErrorData: null, - ), - constMeta: kCrateApiMldsaKeyGenerateConstMeta, - argValues: [], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMldsaKeyGenerateConstMeta => - const TaskConstMeta(debugName: "MldsaKey_generate", argNames: []); - - @override - Future crateApiMldsaKeyGetPublicKey({required MldsaKey that}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - that, - serializer, - ); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 3, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: null, - ), - constMeta: kCrateApiMldsaKeyGetPublicKeyConstMeta, - argValues: [that], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMldsaKeyGetPublicKeyConstMeta => - const TaskConstMeta( - debugName: "MldsaKey_get_public_key", - argNames: ["that"], - ); - - @override - Future crateApiMldsaKeySign({ - required MldsaKey that, - required List message, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - that, - serializer, - ); - sse_encode_list_prim_u_8_loose(message, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 4, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_AnyhowException, - ), - constMeta: kCrateApiMldsaKeySignConstMeta, - argValues: [that, message], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMldsaKeySignConstMeta => const TaskConstMeta( - debugName: "MldsaKey_sign", - argNames: ["that", "message"], - ); - - @override - Future crateApiMldsaKeyToBytes({required MldsaKey that}) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - that, - serializer, - ); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 5, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: null, - ), - constMeta: kCrateApiMldsaKeyToBytesConstMeta, - argValues: [that], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiMldsaKeyToBytesConstMeta => - const TaskConstMeta(debugName: "MldsaKey_to_bytes", argNames: ["that"]); - - @override - Future crateApiFormatChallenge({ - required List random, - required PlatformInt64 timestamp, - }) { - return handler.executeNormal( - NormalTask( - callFfi: (port_) { - final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_list_prim_u_8_loose(random, serializer); - sse_encode_i_64(timestamp, serializer); - pdeCallFfi( - generalizedFrbRustBinding, - serializer, - funcId: 6, - port: port_, - ); - }, - codec: SseCodec( - decodeSuccessData: sse_decode_list_prim_u_8_strict, - decodeErrorData: sse_decode_String, - ), - constMeta: kCrateApiFormatChallengeConstMeta, - argValues: [random, timestamp], - apiImpl: this, - ), - ); - } - - TaskConstMeta get kCrateApiFormatChallengeConstMeta => const TaskConstMeta( - debugName: "format_challenge", - argNames: ["random", "timestamp"], - ); - - RustArcIncrementStrongCountFnType - get rust_arc_increment_strong_count_MldsaKey => wire - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey; - - RustArcDecrementStrongCountFnType - get rust_arc_decrement_strong_count_MldsaKey => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey; - - @protected - AnyhowException dco_decode_AnyhowException(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return AnyhowException(raw as String); - } - - @protected - MldsaKey - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - dynamic raw, - ) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return MldsaKeyImpl.frbInternalDcoDecode(raw as List); - } - - @protected - MldsaKey - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - dynamic raw, - ) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return MldsaKeyImpl.frbInternalDcoDecode(raw as List); - } - - @protected - MldsaKey - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - dynamic raw, - ) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return MldsaKeyImpl.frbInternalDcoDecode(raw as List); - } - - @protected - String dco_decode_String(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as String; - } - - @protected - PlatformInt64 dco_decode_i_64(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return dcoDecodeI64(raw); - } - - @protected - List dco_decode_list_prim_u_8_loose(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as List; - } - - @protected - Uint8List dco_decode_list_prim_u_8_strict(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as Uint8List; - } - - @protected - int dco_decode_u_8(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return raw as int; - } - - @protected - void dco_decode_unit(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return; - } - - @protected - BigInt dco_decode_usize(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return dcoDecodeU64(raw); - } - - @protected - AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var inner = sse_decode_String(deserializer); - return AnyhowException(inner); - } - - @protected - MldsaKey - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - SseDeserializer deserializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - return MldsaKeyImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), - sse_decode_i_32(deserializer), - ); - } - - @protected - MldsaKey - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - SseDeserializer deserializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - return MldsaKeyImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), - sse_decode_i_32(deserializer), - ); - } - - @protected - MldsaKey - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - SseDeserializer deserializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - return MldsaKeyImpl.frbInternalSseDecode( - sse_decode_usize(deserializer), - sse_decode_i_32(deserializer), - ); - } - - @protected - String sse_decode_String(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var inner = sse_decode_list_prim_u_8_strict(deserializer); - return utf8.decoder.convert(inner); - } - - @protected - PlatformInt64 sse_decode_i_64(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getPlatformInt64(); - } - - @protected - List sse_decode_list_prim_u_8_loose(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var len_ = sse_decode_i_32(deserializer); - return deserializer.buffer.getUint8List(len_); - } - - @protected - Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var len_ = sse_decode_i_32(deserializer); - return deserializer.buffer.getUint8List(len_); - } - - @protected - int sse_decode_u_8(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getUint8(); - } - - @protected - void sse_decode_unit(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - } - - @protected - BigInt sse_decode_usize(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getBigUint64(); - } - - @protected - int sse_decode_i_32(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getInt32(); - } - - @protected - bool sse_decode_bool(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - return deserializer.buffer.getUint8() != 0; - } - - @protected - void sse_encode_AnyhowException( - AnyhowException self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_String(self.message, serializer); - } - - @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - MldsaKey self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as MldsaKeyImpl).frbInternalSseEncode(move: true), - serializer, - ); - } - - @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - MldsaKey self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as MldsaKeyImpl).frbInternalSseEncode(move: false), - serializer, - ); - } - - @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - MldsaKey self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_usize( - (self as MldsaKeyImpl).frbInternalSseEncode(move: null), - serializer, - ); - } - - @protected - void sse_encode_String(String self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_list_prim_u_8_strict(utf8.encoder.convert(self), serializer); - } - - @protected - void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - serializer.buffer.putPlatformInt64(self); - } - - @protected - void sse_encode_list_prim_u_8_loose( - List self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_i_32(self.length, serializer); - serializer.buffer.putUint8List( - self is Uint8List ? self : Uint8List.fromList(self), - ); - } - - @protected - void sse_encode_list_prim_u_8_strict( - Uint8List self, - SseSerializer serializer, - ) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_i_32(self.length, serializer); - serializer.buffer.putUint8List(self); - } - - @protected - void sse_encode_u_8(int self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - serializer.buffer.putUint8(self); - } - - @protected - void sse_encode_unit(void self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - } - - @protected - void sse_encode_usize(BigInt self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - serializer.buffer.putBigUint64(self); - } - - @protected - void sse_encode_i_32(int self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - serializer.buffer.putInt32(self); - } - - @protected - void sse_encode_bool(bool self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - serializer.buffer.putUint8(self ? 1 : 0); - } -} - -@sealed -class MldsaKeyImpl extends RustOpaque implements MldsaKey { - // Not to be used by end users - MldsaKeyImpl.frbInternalDcoDecode(List wire) - : super.frbInternalDcoDecode(wire, _kStaticData); - - // Not to be used by end users - MldsaKeyImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) - : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); - - static final _kStaticData = RustArcStaticData( - rustArcIncrementStrongCount: - RustLib.instance.api.rust_arc_increment_strong_count_MldsaKey, - rustArcDecrementStrongCount: - RustLib.instance.api.rust_arc_decrement_strong_count_MldsaKey, - rustArcDecrementStrongCountPtr: - RustLib.instance.api.rust_arc_decrement_strong_count_MldsaKeyPtr, - ); - - Future getPublicKey() => - RustLib.instance.api.crateApiMldsaKeyGetPublicKey(that: this); - - Future sign({required List message}) => - RustLib.instance.api.crateApiMldsaKeySign(that: this, message: message); - - Future toBytes() => - RustLib.instance.api.crateApiMldsaKeyToBytes(that: this); -} +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.12.0. + +// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field + +import 'api.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'frb_generated.dart'; +import 'frb_generated.io.dart' + if (dart.library.js_interop) 'frb_generated.web.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +/// Main entrypoint of the Rust API +class RustLib extends BaseEntrypoint { + @internal + static final instance = RustLib._(); + + RustLib._(); + + /// Initialize flutter_rust_bridge + static Future init({ + RustLibApi? api, + BaseHandler? handler, + ExternalLibrary? externalLibrary, + bool forceSameCodegenVersion = true, + }) async { + await instance.initImpl( + api: api, + handler: handler, + externalLibrary: externalLibrary, + forceSameCodegenVersion: forceSameCodegenVersion, + ); + } + + /// Initialize flutter_rust_bridge in mock mode. + /// No libraries for FFI are loaded. + static void initMock({required RustLibApi api}) { + instance.initMockImpl(api: api); + } + + /// Dispose flutter_rust_bridge + /// + /// The call to this function is optional, since flutter_rust_bridge (and everything else) + /// is automatically disposed when the app stops. + static void dispose() => instance.disposeImpl(); + + @override + ApiImplConstructor get apiImplConstructor => + RustLibApiImpl.new; + + @override + WireConstructor get wireConstructor => + RustLibWire.fromExternalLibrary; + + @override + Future executeRustInitializers() async {} + + @override + ExternalLibraryLoaderConfig get defaultExternalLibraryLoaderConfig => + kDefaultExternalLibraryLoaderConfig; + + @override + String get codegenVersion => '2.12.0'; + + @override + int get rustContentHash => 1247923898; + + static const kDefaultExternalLibraryLoaderConfig = + ExternalLibraryLoaderConfig( + stem: 'rust_lib_arbiter', + ioDirectory: 'rust/target/release/', + webPrefix: 'pkg/', + wasmBindgenName: 'wasm_bindgen', + ); +} + +abstract class RustLibApi extends BaseApi { + Future crateApiMldsaKeyFromBytes({required List bytes}); + + Future crateApiMldsaKeyGenerate(); + + Future crateApiMldsaKeyGetPublicKey({required MldsaKey that}); + + Future crateApiMldsaKeySign({ + required MldsaKey that, + required List message, + }); + + Future crateApiMldsaKeyToBytes({required MldsaKey that}); + + Future crateApiFormatChallenge({ + required List random, + required PlatformInt64 timestamp, + }); + + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_MldsaKey; + + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_MldsaKey; + + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_MldsaKeyPtr; +} + +class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { + RustLibApiImpl({ + required super.handler, + required super.wire, + required super.generalizedFrbRustBinding, + required super.portManager, + }); + + @override + Future crateApiMldsaKeyFromBytes({required List bytes}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(bytes, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 1, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMldsaKeyFromBytesConstMeta, + argValues: [bytes], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiMldsaKeyFromBytesConstMeta => const TaskConstMeta( + debugName: "MldsaKey_from_bytes", + argNames: ["bytes"], + ); + + @override + Future crateApiMldsaKeyGenerate() { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 2, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey, + decodeErrorData: null, + ), + constMeta: kCrateApiMldsaKeyGenerateConstMeta, + argValues: [], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiMldsaKeyGenerateConstMeta => + const TaskConstMeta(debugName: "MldsaKey_generate", argNames: []); + + @override + Future crateApiMldsaKeyGetPublicKey({required MldsaKey that}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + that, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 3, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: null, + ), + constMeta: kCrateApiMldsaKeyGetPublicKeyConstMeta, + argValues: [that], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiMldsaKeyGetPublicKeyConstMeta => + const TaskConstMeta( + debugName: "MldsaKey_get_public_key", + argNames: ["that"], + ); + + @override + Future crateApiMldsaKeySign({ + required MldsaKey that, + required List message, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + that, + serializer, + ); + sse_encode_list_prim_u_8_loose(message, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 4, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiMldsaKeySignConstMeta, + argValues: [that, message], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiMldsaKeySignConstMeta => const TaskConstMeta( + debugName: "MldsaKey_sign", + argNames: ["that", "message"], + ); + + @override + Future crateApiMldsaKeyToBytes({required MldsaKey that}) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + that, + serializer, + ); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 5, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: null, + ), + constMeta: kCrateApiMldsaKeyToBytesConstMeta, + argValues: [that], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiMldsaKeyToBytesConstMeta => + const TaskConstMeta(debugName: "MldsaKey_to_bytes", argNames: ["that"]); + + @override + Future crateApiFormatChallenge({ + required List random, + required PlatformInt64 timestamp, + }) { + return handler.executeNormal( + NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_list_prim_u_8_loose(random, serializer); + sse_encode_i_64(timestamp, serializer); + pdeCallFfi( + generalizedFrbRustBinding, + serializer, + funcId: 6, + port: port_, + ); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_list_prim_u_8_strict, + decodeErrorData: sse_decode_String, + ), + constMeta: kCrateApiFormatChallengeConstMeta, + argValues: [random, timestamp], + apiImpl: this, + ), + ); + } + + TaskConstMeta get kCrateApiFormatChallengeConstMeta => const TaskConstMeta( + debugName: "format_challenge", + argNames: ["random", "timestamp"], + ); + + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_MldsaKey => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey; + + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_MldsaKey => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey; + + @protected + AnyhowException dco_decode_AnyhowException(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return AnyhowException(raw as String); + } + + @protected + MldsaKey + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return MldsaKeyImpl.frbInternalDcoDecode(raw as List); + } + + @protected + MldsaKey + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return MldsaKeyImpl.frbInternalDcoDecode(raw as List); + } + + @protected + MldsaKey + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return MldsaKeyImpl.frbInternalDcoDecode(raw as List); + } + + @protected + String dco_decode_String(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as String; + } + + @protected + PlatformInt64 dco_decode_i_64(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dcoDecodeI64(raw); + } + + @protected + List dco_decode_list_prim_u_8_loose(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as List; + } + + @protected + Uint8List dco_decode_list_prim_u_8_strict(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as Uint8List; + } + + @protected + int dco_decode_u_8(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as int; + } + + @protected + void dco_decode_unit(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return; + } + + @protected + BigInt dco_decode_usize(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return dcoDecodeU64(raw); + } + + @protected + AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var inner = sse_decode_String(deserializer); + return AnyhowException(inner); + } + + @protected + MldsaKey + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + return MldsaKeyImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); + } + + @protected + MldsaKey + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + return MldsaKeyImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); + } + + @protected + MldsaKey + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + return MldsaKeyImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); + } + + @protected + String sse_decode_String(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var inner = sse_decode_list_prim_u_8_strict(deserializer); + return utf8.decoder.convert(inner); + } + + @protected + PlatformInt64 sse_decode_i_64(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getPlatformInt64(); + } + + @protected + List sse_decode_list_prim_u_8_loose(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var len_ = sse_decode_i_32(deserializer); + return deserializer.buffer.getUint8List(len_); + } + + @protected + Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var len_ = sse_decode_i_32(deserializer); + return deserializer.buffer.getUint8List(len_); + } + + @protected + int sse_decode_u_8(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getUint8(); + } + + @protected + void sse_decode_unit(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + } + + @protected + BigInt sse_decode_usize(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getBigUint64(); + } + + @protected + int sse_decode_i_32(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getInt32(); + } + + @protected + bool sse_decode_bool(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return deserializer.buffer.getUint8() != 0; + } + + @protected + void sse_encode_AnyhowException( + AnyhowException self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.message, serializer); + } + + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + MldsaKey self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as MldsaKeyImpl).frbInternalSseEncode(move: true), + serializer, + ); + } + + @protected + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + MldsaKey self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as MldsaKeyImpl).frbInternalSseEncode(move: false), + serializer, + ); + } + + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + MldsaKey self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as MldsaKeyImpl).frbInternalSseEncode(move: null), + serializer, + ); + } + + @protected + void sse_encode_String(String self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_list_prim_u_8_strict(utf8.encoder.convert(self), serializer); + } + + @protected + void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putPlatformInt64(self); + } + + @protected + void sse_encode_list_prim_u_8_loose( + List self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + serializer.buffer.putUint8List( + self is Uint8List ? self : Uint8List.fromList(self), + ); + } + + @protected + void sse_encode_list_prim_u_8_strict( + Uint8List self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + serializer.buffer.putUint8List(self); + } + + @protected + void sse_encode_u_8(int self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putUint8(self); + } + + @protected + void sse_encode_unit(void self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + } + + @protected + void sse_encode_usize(BigInt self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putBigUint64(self); + } + + @protected + void sse_encode_i_32(int self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putInt32(self); + } + + @protected + void sse_encode_bool(bool self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + serializer.buffer.putUint8(self ? 1 : 0); + } +} + +@sealed +class MldsaKeyImpl extends RustOpaque implements MldsaKey { + // Not to be used by end users + MldsaKeyImpl.frbInternalDcoDecode(List wire) + : super.frbInternalDcoDecode(wire, _kStaticData); + + // Not to be used by end users + MldsaKeyImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + + static final _kStaticData = RustArcStaticData( + rustArcIncrementStrongCount: + RustLib.instance.api.rust_arc_increment_strong_count_MldsaKey, + rustArcDecrementStrongCount: + RustLib.instance.api.rust_arc_decrement_strong_count_MldsaKey, + rustArcDecrementStrongCountPtr: + RustLib.instance.api.rust_arc_decrement_strong_count_MldsaKeyPtr, + ); + + Future getPublicKey() => + RustLib.instance.api.crateApiMldsaKeyGetPublicKey(that: this); + + Future sign({required List message}) => + RustLib.instance.api.crateApiMldsaKeySign(that: this, message: message); + + Future toBytes() => + RustLib.instance.api.crateApiMldsaKeyToBytes(that: this); +} diff --git a/useragent/lib/src/rust/frb_generated.io.dart b/useragent/lib/src/rust/frb_generated.io.dart index 3780c4e..0a829ac 100644 --- a/useragent/lib/src/rust/frb_generated.io.dart +++ b/useragent/lib/src/rust/frb_generated.io.dart @@ -1,220 +1,220 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. - -// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field - -import 'api.dart'; -import 'dart:async'; -import 'dart:convert'; -import 'dart:ffi' as ffi; -import 'frb_generated.dart'; -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart'; - -abstract class RustLibApiImplPlatform extends BaseApiImpl { - RustLibApiImplPlatform({ - required super.handler, - required super.wire, - required super.generalizedFrbRustBinding, - required super.portManager, - }); - - CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_MldsaKeyPtr => wire - ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKeyPtr; - - @protected - AnyhowException dco_decode_AnyhowException(dynamic raw); - - @protected - MldsaKey - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - dynamic raw, - ); - - @protected - MldsaKey - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - dynamic raw, - ); - - @protected - MldsaKey - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - dynamic raw, - ); - - @protected - String dco_decode_String(dynamic raw); - - @protected - PlatformInt64 dco_decode_i_64(dynamic raw); - - @protected - List dco_decode_list_prim_u_8_loose(dynamic raw); - - @protected - Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); - - @protected - int dco_decode_u_8(dynamic raw); - - @protected - void dco_decode_unit(dynamic raw); - - @protected - BigInt dco_decode_usize(dynamic raw); - - @protected - AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); - - @protected - MldsaKey - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - SseDeserializer deserializer, - ); - - @protected - MldsaKey - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - SseDeserializer deserializer, - ); - - @protected - MldsaKey - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - SseDeserializer deserializer, - ); - - @protected - String sse_decode_String(SseDeserializer deserializer); - - @protected - PlatformInt64 sse_decode_i_64(SseDeserializer deserializer); - - @protected - List sse_decode_list_prim_u_8_loose(SseDeserializer deserializer); - - @protected - Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); - - @protected - int sse_decode_u_8(SseDeserializer deserializer); - - @protected - void sse_decode_unit(SseDeserializer deserializer); - - @protected - BigInt sse_decode_usize(SseDeserializer deserializer); - - @protected - int sse_decode_i_32(SseDeserializer deserializer); - - @protected - bool sse_decode_bool(SseDeserializer deserializer); - - @protected - void sse_encode_AnyhowException( - AnyhowException self, - SseSerializer serializer, - ); - - @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - MldsaKey self, - SseSerializer serializer, - ); - - @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - MldsaKey self, - SseSerializer serializer, - ); - - @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - MldsaKey self, - SseSerializer serializer, - ); - - @protected - void sse_encode_String(String self, SseSerializer serializer); - - @protected - void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer); - - @protected - void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer); - - @protected - void sse_encode_list_prim_u_8_strict( - Uint8List self, - SseSerializer serializer, - ); - - @protected - void sse_encode_u_8(int self, SseSerializer serializer); - - @protected - void sse_encode_unit(void self, SseSerializer serializer); - - @protected - void sse_encode_usize(BigInt self, SseSerializer serializer); - - @protected - void sse_encode_i_32(int self, SseSerializer serializer); - - @protected - void sse_encode_bool(bool self, SseSerializer serializer); -} - -// Section: wire_class - -class RustLibWire implements BaseWire { - factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) => - RustLibWire(lib.ffiDynamicLibrary); - - /// Holds the symbol lookup function. - final ffi.Pointer Function(String symbolName) - _lookup; - - /// The symbols are looked up in [dynamicLibrary]. - RustLibWire(ffi.DynamicLibrary dynamicLibrary) - : _lookup = dynamicLibrary.lookup; - - void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - ffi.Pointer ptr, - ) { - return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - ptr, - ); - } - - late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKeyPtr = - _lookup)>>( - 'frbgen_arbiter_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey', - ); - late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey = - _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKeyPtr - .asFunction)>(); - - void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - ffi.Pointer ptr, - ) { - return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - ptr, - ); - } - - late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKeyPtr = - _lookup)>>( - 'frbgen_arbiter_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey', - ); - late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey = - _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKeyPtr - .asFunction)>(); -} +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.12.0. + +// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field + +import 'api.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'dart:ffi' as ffi; +import 'frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart'; + +abstract class RustLibApiImplPlatform extends BaseApiImpl { + RustLibApiImplPlatform({ + required super.handler, + required super.wire, + required super.generalizedFrbRustBinding, + required super.portManager, + }); + + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_MldsaKeyPtr => wire + ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKeyPtr; + + @protected + AnyhowException dco_decode_AnyhowException(dynamic raw); + + @protected + MldsaKey + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + dynamic raw, + ); + + @protected + MldsaKey + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + dynamic raw, + ); + + @protected + MldsaKey + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + dynamic raw, + ); + + @protected + String dco_decode_String(dynamic raw); + + @protected + PlatformInt64 dco_decode_i_64(dynamic raw); + + @protected + List dco_decode_list_prim_u_8_loose(dynamic raw); + + @protected + Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); + + @protected + int dco_decode_u_8(dynamic raw); + + @protected + void dco_decode_unit(dynamic raw); + + @protected + BigInt dco_decode_usize(dynamic raw); + + @protected + AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); + + @protected + MldsaKey + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + SseDeserializer deserializer, + ); + + @protected + MldsaKey + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + SseDeserializer deserializer, + ); + + @protected + MldsaKey + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + SseDeserializer deserializer, + ); + + @protected + String sse_decode_String(SseDeserializer deserializer); + + @protected + PlatformInt64 sse_decode_i_64(SseDeserializer deserializer); + + @protected + List sse_decode_list_prim_u_8_loose(SseDeserializer deserializer); + + @protected + Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); + + @protected + int sse_decode_u_8(SseDeserializer deserializer); + + @protected + void sse_decode_unit(SseDeserializer deserializer); + + @protected + BigInt sse_decode_usize(SseDeserializer deserializer); + + @protected + int sse_decode_i_32(SseDeserializer deserializer); + + @protected + bool sse_decode_bool(SseDeserializer deserializer); + + @protected + void sse_encode_AnyhowException( + AnyhowException self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + MldsaKey self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + MldsaKey self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + MldsaKey self, + SseSerializer serializer, + ); + + @protected + void sse_encode_String(String self, SseSerializer serializer); + + @protected + void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer); + + @protected + void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer); + + @protected + void sse_encode_list_prim_u_8_strict( + Uint8List self, + SseSerializer serializer, + ); + + @protected + void sse_encode_u_8(int self, SseSerializer serializer); + + @protected + void sse_encode_unit(void self, SseSerializer serializer); + + @protected + void sse_encode_usize(BigInt self, SseSerializer serializer); + + @protected + void sse_encode_i_32(int self, SseSerializer serializer); + + @protected + void sse_encode_bool(bool self, SseSerializer serializer); +} + +// Section: wire_class + +class RustLibWire implements BaseWire { + factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) => + RustLibWire(lib.ffiDynamicLibrary); + + /// Holds the symbol lookup function. + final ffi.Pointer Function(String symbolName) + _lookup; + + /// The symbols are looked up in [dynamicLibrary]. + RustLibWire(ffi.DynamicLibrary dynamicLibrary) + : _lookup = dynamicLibrary.lookup; + + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + ffi.Pointer ptr, + ) { + return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + ptr, + ); + } + + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKeyPtr = + _lookup)>>( + 'frbgen_arbiter_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey', + ); + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey = + _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKeyPtr + .asFunction)>(); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + ffi.Pointer ptr, + ) { + return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + ptr, + ); + } + + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKeyPtr = + _lookup)>>( + 'frbgen_arbiter_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey', + ); + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey = + _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKeyPtr + .asFunction)>(); +} diff --git a/useragent/lib/src/rust/frb_generated.web.dart b/useragent/lib/src/rust/frb_generated.web.dart index e8a41cb..76cc759 100644 --- a/useragent/lib/src/rust/frb_generated.web.dart +++ b/useragent/lib/src/rust/frb_generated.web.dart @@ -1,212 +1,212 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. - -// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field - -// Static analysis wrongly picks the IO variant, thus ignore this -// ignore_for_file: argument_type_not_assignable - -import 'api.dart'; -import 'dart:async'; -import 'dart:convert'; -import 'frb_generated.dart'; -import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart'; - -abstract class RustLibApiImplPlatform extends BaseApiImpl { - RustLibApiImplPlatform({ - required super.handler, - required super.wire, - required super.generalizedFrbRustBinding, - required super.portManager, - }); - - CrossPlatformFinalizerArg - get rust_arc_decrement_strong_count_MldsaKeyPtr => wire - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey; - - @protected - AnyhowException dco_decode_AnyhowException(dynamic raw); - - @protected - MldsaKey - dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - dynamic raw, - ); - - @protected - MldsaKey - dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - dynamic raw, - ); - - @protected - MldsaKey - dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - dynamic raw, - ); - - @protected - String dco_decode_String(dynamic raw); - - @protected - PlatformInt64 dco_decode_i_64(dynamic raw); - - @protected - List dco_decode_list_prim_u_8_loose(dynamic raw); - - @protected - Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); - - @protected - int dco_decode_u_8(dynamic raw); - - @protected - void dco_decode_unit(dynamic raw); - - @protected - BigInt dco_decode_usize(dynamic raw); - - @protected - AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); - - @protected - MldsaKey - sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - SseDeserializer deserializer, - ); - - @protected - MldsaKey - sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - SseDeserializer deserializer, - ); - - @protected - MldsaKey - sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - SseDeserializer deserializer, - ); - - @protected - String sse_decode_String(SseDeserializer deserializer); - - @protected - PlatformInt64 sse_decode_i_64(SseDeserializer deserializer); - - @protected - List sse_decode_list_prim_u_8_loose(SseDeserializer deserializer); - - @protected - Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); - - @protected - int sse_decode_u_8(SseDeserializer deserializer); - - @protected - void sse_decode_unit(SseDeserializer deserializer); - - @protected - BigInt sse_decode_usize(SseDeserializer deserializer); - - @protected - int sse_decode_i_32(SseDeserializer deserializer); - - @protected - bool sse_decode_bool(SseDeserializer deserializer); - - @protected - void sse_encode_AnyhowException( - AnyhowException self, - SseSerializer serializer, - ); - - @protected - void - sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - MldsaKey self, - SseSerializer serializer, - ); - - @protected - void - sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - MldsaKey self, - SseSerializer serializer, - ); - - @protected - void - sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - MldsaKey self, - SseSerializer serializer, - ); - - @protected - void sse_encode_String(String self, SseSerializer serializer); - - @protected - void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer); - - @protected - void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer); - - @protected - void sse_encode_list_prim_u_8_strict( - Uint8List self, - SseSerializer serializer, - ); - - @protected - void sse_encode_u_8(int self, SseSerializer serializer); - - @protected - void sse_encode_unit(void self, SseSerializer serializer); - - @protected - void sse_encode_usize(BigInt self, SseSerializer serializer); - - @protected - void sse_encode_i_32(int self, SseSerializer serializer); - - @protected - void sse_encode_bool(bool self, SseSerializer serializer); -} - -// Section: wire_class - -class RustLibWire implements BaseWire { - RustLibWire.fromExternalLibrary(ExternalLibrary lib); - - void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - int ptr, - ) => wasmModule - .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - ptr, - ); - - void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - int ptr, - ) => wasmModule - .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - ptr, - ); -} - -@JS('wasm_bindgen') -external RustLibWasmModule get wasmModule; - -@JS() -@anonymous -extension type RustLibWasmModule._(JSObject _) implements JSObject { - external void - rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - int ptr, - ); - - external void - rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - int ptr, - ); -} +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.12.0. + +// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field + +// Static analysis wrongly picks the IO variant, thus ignore this +// ignore_for_file: argument_type_not_assignable + +import 'api.dart'; +import 'dart:async'; +import 'dart:convert'; +import 'frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart'; + +abstract class RustLibApiImplPlatform extends BaseApiImpl { + RustLibApiImplPlatform({ + required super.handler, + required super.wire, + required super.generalizedFrbRustBinding, + required super.portManager, + }); + + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_MldsaKeyPtr => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey; + + @protected + AnyhowException dco_decode_AnyhowException(dynamic raw); + + @protected + MldsaKey + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + dynamic raw, + ); + + @protected + MldsaKey + dco_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + dynamic raw, + ); + + @protected + MldsaKey + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + dynamic raw, + ); + + @protected + String dco_decode_String(dynamic raw); + + @protected + PlatformInt64 dco_decode_i_64(dynamic raw); + + @protected + List dco_decode_list_prim_u_8_loose(dynamic raw); + + @protected + Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); + + @protected + int dco_decode_u_8(dynamic raw); + + @protected + void dco_decode_unit(dynamic raw); + + @protected + BigInt dco_decode_usize(dynamic raw); + + @protected + AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer); + + @protected + MldsaKey + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + SseDeserializer deserializer, + ); + + @protected + MldsaKey + sse_decode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + SseDeserializer deserializer, + ); + + @protected + MldsaKey + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + SseDeserializer deserializer, + ); + + @protected + String sse_decode_String(SseDeserializer deserializer); + + @protected + PlatformInt64 sse_decode_i_64(SseDeserializer deserializer); + + @protected + List sse_decode_list_prim_u_8_loose(SseDeserializer deserializer); + + @protected + Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); + + @protected + int sse_decode_u_8(SseDeserializer deserializer); + + @protected + void sse_decode_unit(SseDeserializer deserializer); + + @protected + BigInt sse_decode_usize(SseDeserializer deserializer); + + @protected + int sse_decode_i_32(SseDeserializer deserializer); + + @protected + bool sse_decode_bool(SseDeserializer deserializer); + + @protected + void sse_encode_AnyhowException( + AnyhowException self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + MldsaKey self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + MldsaKey self, + SseSerializer serializer, + ); + + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + MldsaKey self, + SseSerializer serializer, + ); + + @protected + void sse_encode_String(String self, SseSerializer serializer); + + @protected + void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer); + + @protected + void sse_encode_list_prim_u_8_loose(List self, SseSerializer serializer); + + @protected + void sse_encode_list_prim_u_8_strict( + Uint8List self, + SseSerializer serializer, + ); + + @protected + void sse_encode_u_8(int self, SseSerializer serializer); + + @protected + void sse_encode_unit(void self, SseSerializer serializer); + + @protected + void sse_encode_usize(BigInt self, SseSerializer serializer); + + @protected + void sse_encode_i_32(int self, SseSerializer serializer); + + @protected + void sse_encode_bool(bool self, SseSerializer serializer); +} + +// Section: wire_class + +class RustLibWire implements BaseWire { + RustLibWire.fromExternalLibrary(ExternalLibrary lib); + + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + int ptr, + ) => wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + ptr, + ); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + int ptr, + ) => wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + ptr, + ); +} + +@JS('wasm_bindgen') +external RustLibWasmModule get wasmModule; + +@JS() +@anonymous +extension type RustLibWasmModule._(JSObject _) implements JSObject { + external void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + int ptr, + ); + + external void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + int ptr, + ); +} diff --git a/useragent/lib/theme/palette.dart b/useragent/lib/theme/palette.dart index be95981..14d9d42 100644 --- a/useragent/lib/theme/palette.dart +++ b/useragent/lib/theme/palette.dart @@ -1,12 +1,12 @@ -import 'package:flutter/material.dart'; - -class Palette { - static const ink = Color(0xFF15263C); - static const coral = Color(0xFFE26254); - static const cream = Color(0xFFFFFAF4); - static const line = Color(0x1A15263C); - static const token = Color(0xFF5C6BC0); - static const cardBorder = Color(0x1A17324A); - static const introGradientStart = Color(0xFFF7F9FC); - static const introGradientEnd = Color(0xFFFDF5EA); -} +import 'package:flutter/material.dart'; + +class Palette { + static const ink = Color(0xFF15263C); + static const coral = Color(0xFFE26254); + static const cream = Color(0xFFFFFAF4); + static const line = Color(0x1A15263C); + static const token = Color(0xFF5C6BC0); + static const cardBorder = Color(0x1A17324A); + static const introGradientStart = Color(0xFFF7F9FC); + static const introGradientEnd = Color(0xFFFDF5EA); +} diff --git a/useragent/lib/widgets/bottom_popup.dart b/useragent/lib/widgets/bottom_popup.dart index 3e95db0..e9b83c5 100644 --- a/useragent/lib/widgets/bottom_popup.dart +++ b/useragent/lib/widgets/bottom_popup.dart @@ -1,93 +1,93 @@ -import 'package:flutter/material.dart'; - -Future showBottomPopup({ - required BuildContext context, - required WidgetBuilder builder, - bool barrierDismissible = true, -}) { - return showGeneralDialog( - context: context, - barrierDismissible: barrierDismissible, - barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, - barrierColor: Colors.transparent, - transitionDuration: const Duration(milliseconds: 320), - pageBuilder: (dialogContext, animation, secondaryAnimation) { - return _BottomPopupRoute( - animation: animation, - builder: builder, - barrierDismissible: barrierDismissible, - ); - }, - ); -} - -class _BottomPopupRoute extends StatelessWidget { - const _BottomPopupRoute({ - required this.animation, - required this.builder, - required this.barrierDismissible, - }); - - final Animation animation; - final WidgetBuilder builder; - final bool barrierDismissible; - - @override - Widget build(BuildContext context) { - final barrierAnimation = CurvedAnimation( - parent: animation, - curve: const Interval(0, 0.3125, curve: Curves.easeOut), - ); - final popupAnimation = CurvedAnimation( - parent: animation, - curve: const Interval(0.3125, 1, curve: Curves.easeOutCubic), - ); - - return Material( - type: MaterialType.transparency, - child: Stack( - children: [ - Positioned.fill( - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: barrierDismissible - ? () => Navigator.of(context).pop() - : null, - child: AnimatedBuilder( - animation: barrierAnimation, - builder: (context, child) { - return ColoredBox( - color: Colors.black.withValues( - alpha: 0.35 * barrierAnimation.value, - ), - ); - }, - ), - ), - ), - SafeArea( - child: Align( - alignment: Alignment.bottomCenter, - child: Padding( - padding: const EdgeInsets.all(16), - child: FadeTransition( - opacity: popupAnimation, - child: SlideTransition( - position: Tween( - begin: const Offset(0, 0.08), - end: Offset.zero, - ).animate(popupAnimation), - child: GestureDetector( - onTap: () {}, - child: Builder(builder: builder), - ), - ), - ), - ), - ), - ), - ], - ), - ); - } -} +import 'package:flutter/material.dart'; + +Future showBottomPopup({ + required BuildContext context, + required WidgetBuilder builder, + bool barrierDismissible = true, +}) { + return showGeneralDialog( + context: context, + barrierDismissible: barrierDismissible, + barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, + barrierColor: Colors.transparent, + transitionDuration: const Duration(milliseconds: 320), + pageBuilder: (dialogContext, animation, secondaryAnimation) { + return _BottomPopupRoute( + animation: animation, + builder: builder, + barrierDismissible: barrierDismissible, + ); + }, + ); +} + +class _BottomPopupRoute extends StatelessWidget { + const _BottomPopupRoute({ + required this.animation, + required this.builder, + required this.barrierDismissible, + }); + + final Animation animation; + final WidgetBuilder builder; + final bool barrierDismissible; + + @override + Widget build(BuildContext context) { + final barrierAnimation = CurvedAnimation( + parent: animation, + curve: const Interval(0, 0.3125, curve: Curves.easeOut), + ); + final popupAnimation = CurvedAnimation( + parent: animation, + curve: const Interval(0.3125, 1, curve: Curves.easeOutCubic), + ); + + return Material( + type: MaterialType.transparency, + child: Stack( + children: [ + Positioned.fill( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: barrierDismissible + ? () => Navigator.of(context).pop() + : null, + child: AnimatedBuilder( + animation: barrierAnimation, + builder: (context, child) { + return ColoredBox( + color: Colors.black.withValues( + alpha: 0.35 * barrierAnimation.value, + ), + ); + }, + ), + ), + ), + SafeArea( + child: Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.all(16), + child: FadeTransition( + opacity: popupAnimation, + child: SlideTransition( + position: Tween( + begin: const Offset(0, 0.08), + end: Offset.zero, + ).animate(popupAnimation), + child: GestureDetector( + onTap: () {}, + child: Builder(builder: builder), + ), + ), + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/useragent/lib/widgets/cream_frame.dart b/useragent/lib/widgets/cream_frame.dart index a4e19f7..0d21ba4 100644 --- a/useragent/lib/widgets/cream_frame.dart +++ b/useragent/lib/widgets/cream_frame.dart @@ -1,32 +1,32 @@ -import 'package:arbiter/theme/palette.dart'; -import 'package:flutter/material.dart'; - -/// A card-shaped frame with the cream background, rounded corners, and a -/// subtle border. Use [padding] for interior spacing and [margin] for exterior -/// spacing. -class CreamFrame extends StatelessWidget { - const CreamFrame({ - super.key, - required this.child, - this.padding = EdgeInsets.zero, - this.margin, - }); - - final Widget child; - final EdgeInsetsGeometry padding; - final EdgeInsetsGeometry? margin; - - @override - Widget build(BuildContext context) { - return Container( - margin: margin, - padding: padding, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), - color: Palette.cream, - border: Border.all(color: Palette.line), - ), - child: child, - ); - } -} +import 'package:arbiter/theme/palette.dart'; +import 'package:flutter/material.dart'; + +/// A card-shaped frame with the cream background, rounded corners, and a +/// subtle border. Use [padding] for interior spacing and [margin] for exterior +/// spacing. +class CreamFrame extends StatelessWidget { + const CreamFrame({ + super.key, + required this.child, + this.padding = EdgeInsets.zero, + this.margin, + }); + + final Widget child; + final EdgeInsetsGeometry padding; + final EdgeInsetsGeometry? margin; + + @override + Widget build(BuildContext context) { + return Container( + margin: margin, + padding: padding, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + color: Palette.cream, + border: Border.all(color: Palette.line), + ), + child: child, + ); + } +} diff --git a/useragent/lib/widgets/page_header.dart b/useragent/lib/widgets/page_header.dart index 798bf2a..c2a1ab1 100644 --- a/useragent/lib/widgets/page_header.dart +++ b/useragent/lib/widgets/page_header.dart @@ -1,63 +1,63 @@ -import 'package:arbiter/theme/palette.dart'; -import 'package:flutter/material.dart'; -import 'package:sizer/sizer.dart'; - -class PageHeader extends StatelessWidget { - const PageHeader({ - super.key, - required this.title, - this.isBusy = false, - this.busyLabel = 'Syncing', - this.actions = const [], - this.padding, - this.backgroundColor, - this.borderColor, - }); - - final String title; - final bool isBusy; - final String busyLabel; - final List actions; - final EdgeInsetsGeometry? padding; - final Color? backgroundColor; - final Color? borderColor; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - return Container( - padding: - padding ?? EdgeInsets.symmetric(horizontal: 1.6.w, vertical: 1.2.h), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(18), - color: backgroundColor ?? Palette.cream, - border: Border.all(color: borderColor ?? Palette.line), - ), - child: Row( - children: [ - Expanded( - child: Text( - title, - style: theme.textTheme.titleMedium?.copyWith( - color: Palette.ink, - fontWeight: FontWeight.w800, - ), - ), - ), - if (isBusy) ...[ - Text( - busyLabel, - style: theme.textTheme.bodySmall?.copyWith( - color: Palette.ink.withValues(alpha: 0.62), - fontWeight: FontWeight.w700, - ), - ), - SizedBox(width: 1.w), - ], - ...actions, - ], - ), - ); - } -} +import 'package:arbiter/theme/palette.dart'; +import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; + +class PageHeader extends StatelessWidget { + const PageHeader({ + super.key, + required this.title, + this.isBusy = false, + this.busyLabel = 'Syncing', + this.actions = const [], + this.padding, + this.backgroundColor, + this.borderColor, + }); + + final String title; + final bool isBusy; + final String busyLabel; + final List actions; + final EdgeInsetsGeometry? padding; + final Color? backgroundColor; + final Color? borderColor; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Container( + padding: + padding ?? EdgeInsets.symmetric(horizontal: 1.6.w, vertical: 1.2.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(18), + color: backgroundColor ?? Palette.cream, + border: Border.all(color: borderColor ?? Palette.line), + ), + child: Row( + children: [ + Expanded( + child: Text( + title, + style: theme.textTheme.titleMedium?.copyWith( + color: Palette.ink, + fontWeight: FontWeight.w800, + ), + ), + ), + if (isBusy) ...[ + Text( + busyLabel, + style: theme.textTheme.bodySmall?.copyWith( + color: Palette.ink.withValues(alpha: 0.62), + fontWeight: FontWeight.w700, + ), + ), + SizedBox(width: 1.w), + ], + ...actions, + ], + ), + ); + } +} diff --git a/useragent/lib/widgets/state_panel.dart b/useragent/lib/widgets/state_panel.dart index ca00b06..9f8f445 100644 --- a/useragent/lib/widgets/state_panel.dart +++ b/useragent/lib/widgets/state_panel.dart @@ -1,69 +1,69 @@ -import 'package:arbiter/widgets/cream_frame.dart'; -import 'package:arbiter/theme/palette.dart'; -import 'package:flutter/material.dart'; -import 'package:sizer/sizer.dart'; - -class StatePanel extends StatelessWidget { - const StatePanel({ - super.key, - required this.icon, - required this.title, - required this.body, - this.actionLabel, - this.onAction, - this.busy = false, - }); - - final IconData icon; - final String title; - final String body; - final String? actionLabel; - final Future Function()? onAction; - final bool busy; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - return CreamFrame( - padding: EdgeInsets.all(2.8.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (busy) - SizedBox( - width: 2.8.h, - height: 2.8.h, - child: const CircularProgressIndicator(strokeWidth: 2.5), - ) - else - Icon(icon, size: 34, color: Palette.coral), - SizedBox(height: 1.8.h), - Text( - title, - style: theme.textTheme.headlineSmall?.copyWith( - color: Palette.ink, - fontWeight: FontWeight.w800, - ), - ), - SizedBox(height: 1.h), - Text( - body, - style: theme.textTheme.bodyLarge?.copyWith( - color: Palette.ink.withValues(alpha: 0.72), - height: 1.5, - ), - ), - if (actionLabel != null && onAction != null) ...[ - SizedBox(height: 2.h), - OutlinedButton.icon( - onPressed: () => onAction!(), - icon: const Icon(Icons.refresh), - label: Text(actionLabel!), - ), - ], - ], - ), - ); - } -} +import 'package:arbiter/widgets/cream_frame.dart'; +import 'package:arbiter/theme/palette.dart'; +import 'package:flutter/material.dart'; +import 'package:sizer/sizer.dart'; + +class StatePanel extends StatelessWidget { + const StatePanel({ + super.key, + required this.icon, + required this.title, + required this.body, + this.actionLabel, + this.onAction, + this.busy = false, + }); + + final IconData icon; + final String title; + final String body; + final String? actionLabel; + final Future Function()? onAction; + final bool busy; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return CreamFrame( + padding: EdgeInsets.all(2.8.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (busy) + SizedBox( + width: 2.8.h, + height: 2.8.h, + child: const CircularProgressIndicator(strokeWidth: 2.5), + ) + else + Icon(icon, size: 34, color: Palette.coral), + SizedBox(height: 1.8.h), + Text( + title, + style: theme.textTheme.headlineSmall?.copyWith( + color: Palette.ink, + fontWeight: FontWeight.w800, + ), + ), + SizedBox(height: 1.h), + Text( + body, + style: theme.textTheme.bodyLarge?.copyWith( + color: Palette.ink.withValues(alpha: 0.72), + height: 1.5, + ), + ), + if (actionLabel != null && onAction != null) ...[ + SizedBox(height: 2.h), + OutlinedButton.icon( + onPressed: () => onAction!(), + icon: const Icon(Icons.refresh), + label: Text(actionLabel!), + ), + ], + ], + ), + ); + } +} diff --git a/useragent/macos/.gitignore b/useragent/macos/.gitignore index 746adbb..d4e0569 100644 --- a/useragent/macos/.gitignore +++ b/useragent/macos/.gitignore @@ -1,7 +1,7 @@ -# Flutter-related -**/Flutter/ephemeral/ -**/Pods/ - -# Xcode-related -**/dgph -**/xcuserdata/ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/useragent/macos/Flutter/Flutter-Debug.xcconfig b/useragent/macos/Flutter/Flutter-Debug.xcconfig index 4b81f9b..63eaa61 100644 --- a/useragent/macos/Flutter/Flutter-Debug.xcconfig +++ b/useragent/macos/Flutter/Flutter-Debug.xcconfig @@ -1,2 +1,2 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/useragent/macos/Flutter/Flutter-Release.xcconfig b/useragent/macos/Flutter/Flutter-Release.xcconfig index 5caa9d1..88d14e0 100644 --- a/useragent/macos/Flutter/Flutter-Release.xcconfig +++ b/useragent/macos/Flutter/Flutter-Release.xcconfig @@ -1,2 +1,2 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/useragent/macos/Flutter/GeneratedPluginRegistrant.swift b/useragent/macos/Flutter/GeneratedPluginRegistrant.swift index 476bca2..e142e4d 100644 --- a/useragent/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/useragent/macos/Flutter/GeneratedPluginRegistrant.swift @@ -1,20 +1,20 @@ -// -// Generated file. Do not edit. -// - -import FlutterMacOS -import Foundation - -import biometric_signature -import cryptography_flutter -import flutter_secure_storage_darwin -import rive_native -import share_plus - -func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - BiometricSignaturePlugin.register(with: registry.registrar(forPlugin: "BiometricSignaturePlugin")) - CryptographyFlutterPlugin.register(with: registry.registrar(forPlugin: "CryptographyFlutterPlugin")) - FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin")) - RiveNativePlugin.register(with: registry.registrar(forPlugin: "RiveNativePlugin")) - SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) -} +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import biometric_signature +import cryptography_flutter +import flutter_secure_storage_darwin +import rive_native +import share_plus + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + BiometricSignaturePlugin.register(with: registry.registrar(forPlugin: "BiometricSignaturePlugin")) + CryptographyFlutterPlugin.register(with: registry.registrar(forPlugin: "CryptographyFlutterPlugin")) + FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin")) + RiveNativePlugin.register(with: registry.registrar(forPlugin: "RiveNativePlugin")) + SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) +} diff --git a/useragent/macos/Podfile b/useragent/macos/Podfile index 25eb537..f2053b3 100644 --- a/useragent/macos/Podfile +++ b/useragent/macos/Podfile @@ -1,42 +1,42 @@ -platform :osx, '26.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end +platform :osx, '26.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/useragent/macos/Podfile.lock b/useragent/macos/Podfile.lock index 26d37b4..13afa9c 100644 --- a/useragent/macos/Podfile.lock +++ b/useragent/macos/Podfile.lock @@ -1,53 +1,53 @@ -PODS: - - biometric_signature (11.0.1): - - FlutterMacOS - - cryptography_flutter (0.0.1): - - FlutterMacOS - - flutter_secure_storage_darwin (10.0.0): - - Flutter - - FlutterMacOS - - FlutterMacOS (1.0.0) - - rive_native (0.0.1): - - FlutterMacOS - - rust_lib_arbiter (0.0.1): - - FlutterMacOS - - share_plus (0.0.1): - - FlutterMacOS - -DEPENDENCIES: - - biometric_signature (from `Flutter/ephemeral/.symlinks/plugins/biometric_signature/macos`) - - cryptography_flutter (from `Flutter/ephemeral/.symlinks/plugins/cryptography_flutter/macos`) - - flutter_secure_storage_darwin (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_darwin/darwin`) - - FlutterMacOS (from `Flutter/ephemeral`) - - rive_native (from `Flutter/ephemeral/.symlinks/plugins/rive_native/macos`) - - rust_lib_arbiter (from `Flutter/ephemeral/.symlinks/plugins/rust_lib_arbiter/macos`) - - share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`) - -EXTERNAL SOURCES: - biometric_signature: - :path: Flutter/ephemeral/.symlinks/plugins/biometric_signature/macos - cryptography_flutter: - :path: Flutter/ephemeral/.symlinks/plugins/cryptography_flutter/macos - flutter_secure_storage_darwin: - :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_darwin/darwin - FlutterMacOS: - :path: Flutter/ephemeral - rive_native: - :path: Flutter/ephemeral/.symlinks/plugins/rive_native/macos - rust_lib_arbiter: - :path: Flutter/ephemeral/.symlinks/plugins/rust_lib_arbiter/macos - share_plus: - :path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos - -SPEC CHECKSUMS: - biometric_signature: bae0597fffbc51252959e78b56a2f5afb8d4e1f5 - cryptography_flutter: be2b3e0e31603521b6a1c2bea232a88a2488a91c - flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23 - FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 - rive_native: 1c53d33e44c2b54424810effea4590671dd220c7 - rust_lib_arbiter: 78dcf27cf17e741c6f4f0b12b64a40980746698a - share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc - -PODFILE CHECKSUM: 224cb1c0d6f5312abfc2477bcb5c7f1fca2574fb - -COCOAPODS: 1.16.2 +PODS: + - biometric_signature (11.0.1): + - FlutterMacOS + - cryptography_flutter (0.0.1): + - FlutterMacOS + - flutter_secure_storage_darwin (10.0.0): + - Flutter + - FlutterMacOS + - FlutterMacOS (1.0.0) + - rive_native (0.0.1): + - FlutterMacOS + - rust_lib_arbiter (0.0.1): + - FlutterMacOS + - share_plus (0.0.1): + - FlutterMacOS + +DEPENDENCIES: + - biometric_signature (from `Flutter/ephemeral/.symlinks/plugins/biometric_signature/macos`) + - cryptography_flutter (from `Flutter/ephemeral/.symlinks/plugins/cryptography_flutter/macos`) + - flutter_secure_storage_darwin (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_darwin/darwin`) + - FlutterMacOS (from `Flutter/ephemeral`) + - rive_native (from `Flutter/ephemeral/.symlinks/plugins/rive_native/macos`) + - rust_lib_arbiter (from `Flutter/ephemeral/.symlinks/plugins/rust_lib_arbiter/macos`) + - share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`) + +EXTERNAL SOURCES: + biometric_signature: + :path: Flutter/ephemeral/.symlinks/plugins/biometric_signature/macos + cryptography_flutter: + :path: Flutter/ephemeral/.symlinks/plugins/cryptography_flutter/macos + flutter_secure_storage_darwin: + :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_darwin/darwin + FlutterMacOS: + :path: Flutter/ephemeral + rive_native: + :path: Flutter/ephemeral/.symlinks/plugins/rive_native/macos + rust_lib_arbiter: + :path: Flutter/ephemeral/.symlinks/plugins/rust_lib_arbiter/macos + share_plus: + :path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos + +SPEC CHECKSUMS: + biometric_signature: bae0597fffbc51252959e78b56a2f5afb8d4e1f5 + cryptography_flutter: be2b3e0e31603521b6a1c2bea232a88a2488a91c + flutter_secure_storage_darwin: acdb3f316ed05a3e68f856e0353b133eec373a23 + FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 + rive_native: 1c53d33e44c2b54424810effea4590671dd220c7 + rust_lib_arbiter: 78dcf27cf17e741c6f4f0b12b64a40980746698a + share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc + +PODFILE CHECKSUM: 224cb1c0d6f5312abfc2477bcb5c7f1fca2574fb + +COCOAPODS: 1.16.2 diff --git a/useragent/macos/Runner.xcodeproj/project.pbxproj b/useragent/macos/Runner.xcodeproj/project.pbxproj index 02de01c..f908ad3 100644 --- a/useragent/macos/Runner.xcodeproj/project.pbxproj +++ b/useragent/macos/Runner.xcodeproj/project.pbxproj @@ -1,836 +1,836 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXAggregateTarget section */ - 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; - buildPhases = ( - 33CC111E2044C6BF0003C045 /* ShellScript */, - ); - dependencies = ( - ); - name = "Flutter Assemble"; - productName = FLX; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - 89374438F7FC24C1E409AC55 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84BA779FA182F4B90ADDD656 /* Pods_RunnerTests.framework */; }; - 9812E904D4443BD8157BA2CD /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFE2551831D6F491FC95F4C0 /* Pods_Runner.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC10EC2044A3C60003C045; - remoteInfo = Runner; - }; - 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC111A2044C6BA0003C045; - remoteInfo = FLX; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 33CC110E2044A8840003C045 /* Bundle Framework */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Bundle Framework"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* useragent.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = useragent.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; - 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; - 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; - 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; - 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 5385F9987FF8E7FD3BA4E87E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 84BA779FA182F4B90ADDD656 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - 989E0AE288EA0AECFF244CAB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - ADF8B0EB51CA38AE67931C44 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - DC537F8D4AE9B12FB802E110 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - F06E58390BD453D6E42AD67C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - F9C83BBEBB84A7F9ACC93B93 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - FFE2551831D6F491FC95F4C0 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 331C80D2294CF70F00263BE5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 89374438F7FC24C1E409AC55 /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EA2044A3C60003C045 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 9812E904D4443BD8157BA2CD /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C80D6294CF71000263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C80D7294CF71000263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 33BA886A226E78AF003329D5 /* Configs */ = { - isa = PBXGroup; - children = ( - 33E5194F232828860026EE4D /* AppInfo.xcconfig */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, - ); - path = Configs; - sourceTree = ""; - }; - 33CC10E42044A3C60003C045 = { - isa = PBXGroup; - children = ( - 33FAB671232836740065AC1E /* Runner */, - 33CEB47122A05771004F2AC0 /* Flutter */, - 331C80D6294CF71000263BE5 /* RunnerTests */, - 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, - C5764DB16A5CAE65539863D1 /* Pods */, - ); - sourceTree = ""; - }; - 33CC10EE2044A3C60003C045 /* Products */ = { - isa = PBXGroup; - children = ( - 33CC10ED2044A3C60003C045 /* useragent.app */, - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 33CC11242044D66E0003C045 /* Resources */ = { - isa = PBXGroup; - children = ( - 33CC10F22044A3C60003C045 /* Assets.xcassets */, - 33CC10F42044A3C60003C045 /* MainMenu.xib */, - 33CC10F72044A3C60003C045 /* Info.plist */, - ); - name = Resources; - path = ..; - sourceTree = ""; - }; - 33CEB47122A05771004F2AC0 /* Flutter */ = { - isa = PBXGroup; - children = ( - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, - ); - path = Flutter; - sourceTree = ""; - }; - 33FAB671232836740065AC1E /* Runner */ = { - isa = PBXGroup; - children = ( - 33CC10F02044A3C60003C045 /* AppDelegate.swift */, - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, - 33E51913231747F40026EE4D /* DebugProfile.entitlements */, - 33E51914231749380026EE4D /* Release.entitlements */, - 33CC11242044D66E0003C045 /* Resources */, - 33BA886A226E78AF003329D5 /* Configs */, - ); - path = Runner; - sourceTree = ""; - }; - C5764DB16A5CAE65539863D1 /* Pods */ = { - isa = PBXGroup; - children = ( - 989E0AE288EA0AECFF244CAB /* Pods-Runner.debug.xcconfig */, - F06E58390BD453D6E42AD67C /* Pods-Runner.release.xcconfig */, - F9C83BBEBB84A7F9ACC93B93 /* Pods-Runner.profile.xcconfig */, - DC537F8D4AE9B12FB802E110 /* Pods-RunnerTests.debug.xcconfig */, - 5385F9987FF8E7FD3BA4E87E /* Pods-RunnerTests.release.xcconfig */, - ADF8B0EB51CA38AE67931C44 /* Pods-RunnerTests.profile.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - FFE2551831D6F491FC95F4C0 /* Pods_Runner.framework */, - 84BA779FA182F4B90ADDD656 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C80D4294CF70F00263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 72217D999FDDB4A0040A839E /* [CP] Check Pods Manifest.lock */, - 331C80D1294CF70F00263BE5 /* Sources */, - 331C80D2294CF70F00263BE5 /* Frameworks */, - 331C80D3294CF70F00263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C80DA294CF71000263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 33CC10EC2044A3C60003C045 /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 4909404BD2C11CE7688B3B73 /* [CP] Check Pods Manifest.lock */, - 33CC10E92044A3C60003C045 /* Sources */, - 33CC10EA2044A3C60003C045 /* Frameworks */, - 33CC10EB2044A3C60003C045 /* Resources */, - 33CC110E2044A8840003C045 /* Bundle Framework */, - 3399D490228B24CF009A79C7 /* ShellScript */, - 2AF2BC4AB258588AFC797EA4 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 33CC11202044C79F0003C045 /* PBXTargetDependency */, - ); - name = Runner; - productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* useragent.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 33CC10E52044A3C60003C045 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C80D4294CF70F00263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 33CC10EC2044A3C60003C045; - }; - 33CC10EC2044A3C60003C045 = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 1; - }; - }; - }; - 33CC111A2044C6BA0003C045 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Manual; - }; - }; - }; - buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 33CC10E42044A3C60003C045; - productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 33CC10EC2044A3C60003C045 /* Runner */, - 331C80D4294CF70F00263BE5 /* RunnerTests */, - 33CC111A2044C6BA0003C045 /* Flutter Assemble */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C80D3294CF70F00263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EB2044A3C60003C045 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 2AF2BC4AB258588AFC797EA4 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 3399D490228B24CF009A79C7 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; - }; - 33CC111E2044C6BF0003C045 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - Flutter/ephemeral/FlutterInputs.xcfilelist, - ); - inputPaths = ( - Flutter/ephemeral/tripwire, - ); - outputFileListPaths = ( - Flutter/ephemeral/FlutterOutputs.xcfilelist, - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; - }; - 4909404BD2C11CE7688B3B73 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 72217D999FDDB4A0040A839E /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C80D1294CF70F00263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10E92044A3C60003C045 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC10EC2044A3C60003C045 /* Runner */; - targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; - }; - 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; - targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 33CC10F52044A3C60003C045 /* Base */, - ); - name = MainMenu.xib; - path = Runner; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 331C80DB294CF71000263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = DC537F8D4AE9B12FB802E110 /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.useragent.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/useragent.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/useragent"; - }; - name = Debug; - }; - 331C80DC294CF71000263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5385F9987FF8E7FD3BA4E87E /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.useragent.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/useragent.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/useragent"; - }; - name = Release; - }; - 331C80DD294CF71000263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = ADF8B0EB51CA38AE67931C44 /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.useragent.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/useragent.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/useragent"; - }; - name = Profile; - }; - 338D0CE9231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - STRING_CATALOG_GENERATE_SYMBOLS = YES; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Profile; - }; - 338D0CEA231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 8L884L537J; - ENABLE_APP_SANDBOX = YES; - ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; - ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; - INFOPLIST_FILE = Runner/Info.plist; - INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 26.0; - PRODUCT_BUNDLE_IDENTIFIER = org.markettakers.arbiter; - PROVISIONING_PROFILE_SPECIFIER = ""; - RUNTIME_EXCEPTION_ALLOW_JIT = YES; - SWIFT_VERSION = 5.0; - }; - name = Profile; - }; - 338D0CEB231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - MACOSX_DEPLOYMENT_TARGET = 11.0; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Profile; - }; - 33CC10F92044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - STRING_CATALOG_GENERATE_SYMBOLS = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 33CC10FA2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - STRING_CATALOG_GENERATE_SYMBOLS = YES; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Release; - }; - 33CC10FC2044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 8L884L537J; - ENABLE_APP_SANDBOX = YES; - ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; - ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; - INFOPLIST_FILE = Runner/Info.plist; - INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 26.0; - PRODUCT_BUNDLE_IDENTIFIER = org.markettakers.arbiter; - PROVISIONING_PROFILE_SPECIFIER = ""; - RUNTIME_EXCEPTION_ALLOW_JIT = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 33CC10FD2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 8L884L537J; - ENABLE_APP_SANDBOX = YES; - ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; - ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; - INFOPLIST_FILE = Runner/Info.plist; - INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - MACOSX_DEPLOYMENT_TARGET = 26.0; - PRODUCT_BUNDLE_IDENTIFIER = org.markettakers.arbiter; - PROVISIONING_PROFILE_SPECIFIER = ""; - RUNTIME_EXCEPTION_ALLOW_JIT = YES; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 33CC111C2044C6BA0003C045 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - MACOSX_DEPLOYMENT_TARGET = 11.0; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 33CC111D2044C6BA0003C045 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - MACOSX_DEPLOYMENT_TARGET = 11.0; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C80DB294CF71000263BE5 /* Debug */, - 331C80DC294CF71000263BE5 /* Release */, - 331C80DD294CF71000263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10F92044A3C60003C045 /* Debug */, - 33CC10FA2044A3C60003C045 /* Release */, - 338D0CE9231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10FC2044A3C60003C045 /* Debug */, - 33CC10FD2044A3C60003C045 /* Release */, - 338D0CEA231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC111C2044C6BA0003C045 /* Debug */, - 33CC111D2044C6BA0003C045 /* Release */, - 338D0CEB231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 33CC10E52044A3C60003C045 /* Project object */; -} +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 89374438F7FC24C1E409AC55 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84BA779FA182F4B90ADDD656 /* Pods_RunnerTests.framework */; }; + 9812E904D4443BD8157BA2CD /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFE2551831D6F491FC95F4C0 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* useragent.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = useragent.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 5385F9987FF8E7FD3BA4E87E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 84BA779FA182F4B90ADDD656 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + 989E0AE288EA0AECFF244CAB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + ADF8B0EB51CA38AE67931C44 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + DC537F8D4AE9B12FB802E110 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + F06E58390BD453D6E42AD67C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + F9C83BBEBB84A7F9ACC93B93 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + FFE2551831D6F491FC95F4C0 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 89374438F7FC24C1E409AC55 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9812E904D4443BD8157BA2CD /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + C5764DB16A5CAE65539863D1 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* useragent.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + C5764DB16A5CAE65539863D1 /* Pods */ = { + isa = PBXGroup; + children = ( + 989E0AE288EA0AECFF244CAB /* Pods-Runner.debug.xcconfig */, + F06E58390BD453D6E42AD67C /* Pods-Runner.release.xcconfig */, + F9C83BBEBB84A7F9ACC93B93 /* Pods-Runner.profile.xcconfig */, + DC537F8D4AE9B12FB802E110 /* Pods-RunnerTests.debug.xcconfig */, + 5385F9987FF8E7FD3BA4E87E /* Pods-RunnerTests.release.xcconfig */, + ADF8B0EB51CA38AE67931C44 /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + FFE2551831D6F491FC95F4C0 /* Pods_Runner.framework */, + 84BA779FA182F4B90ADDD656 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 72217D999FDDB4A0040A839E /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 4909404BD2C11CE7688B3B73 /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + 2AF2BC4AB258588AFC797EA4 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* useragent.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2AF2BC4AB258588AFC797EA4 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 4909404BD2C11CE7688B3B73 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 72217D999FDDB4A0040A839E /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DC537F8D4AE9B12FB802E110 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.useragent.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/useragent.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/useragent"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5385F9987FF8E7FD3BA4E87E /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.useragent.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/useragent.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/useragent"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = ADF8B0EB51CA38AE67931C44 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.useragent.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/useragent.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/useragent"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 8L884L537J; + ENABLE_APP_SANDBOX = YES; + ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; + ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 26.0; + PRODUCT_BUNDLE_IDENTIFIER = org.markettakers.arbiter; + PROVISIONING_PROFILE_SPECIFIER = ""; + RUNTIME_EXCEPTION_ALLOW_JIT = YES; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + MACOSX_DEPLOYMENT_TARGET = 11.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 8L884L537J; + ENABLE_APP_SANDBOX = YES; + ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; + ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 26.0; + PRODUCT_BUNDLE_IDENTIFIER = org.markettakers.arbiter; + PROVISIONING_PROFILE_SPECIFIER = ""; + RUNTIME_EXCEPTION_ALLOW_JIT = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = 8L884L537J; + ENABLE_APP_SANDBOX = YES; + ENABLE_INCOMING_NETWORK_CONNECTIONS = YES; + ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES; + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.productivity"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 26.0; + PRODUCT_BUNDLE_IDENTIFIER = org.markettakers.arbiter; + PROVISIONING_PROFILE_SPECIFIER = ""; + RUNTIME_EXCEPTION_ALLOW_JIT = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + MACOSX_DEPLOYMENT_TARGET = 11.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + MACOSX_DEPLOYMENT_TARGET = 11.0; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/useragent/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/useragent/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist index 18d9810..fc6bf80 100644 --- a/useragent/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ b/useragent/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -1,8 +1,8 @@ - - - - - IDEDidComputeMac32BitWarning - - - + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/useragent/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/useragent/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 23178e3..11e0eaa 100644 --- a/useragent/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/useragent/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,99 +1,99 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/useragent/macos/Runner.xcworkspace/contents.xcworkspacedata b/useragent/macos/Runner.xcworkspace/contents.xcworkspacedata index 21a3cc1..17ccc03 100644 --- a/useragent/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/useragent/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -1,10 +1,10 @@ - - - - - - - + + + + + + + diff --git a/useragent/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/useragent/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist index 18d9810..fc6bf80 100644 --- a/useragent/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ b/useragent/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -1,8 +1,8 @@ - - - - - IDEDidComputeMac32BitWarning - - - + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/useragent/macos/Runner/AppDelegate.swift b/useragent/macos/Runner/AppDelegate.swift index b3c1761..c5c474d 100644 --- a/useragent/macos/Runner/AppDelegate.swift +++ b/useragent/macos/Runner/AppDelegate.swift @@ -1,13 +1,13 @@ -import Cocoa -import FlutterMacOS - -@main -class AppDelegate: FlutterAppDelegate { - override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } - - override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { - return true - } -} +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } +} diff --git a/useragent/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/useragent/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f..8d4e7cb 100644 --- a/useragent/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/useragent/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ -{ - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/useragent/macos/Runner/Base.lproj/MainMenu.xib b/useragent/macos/Runner/Base.lproj/MainMenu.xib index 80e867a..4632c69 100644 --- a/useragent/macos/Runner/Base.lproj/MainMenu.xib +++ b/useragent/macos/Runner/Base.lproj/MainMenu.xib @@ -1,343 +1,343 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/useragent/macos/Runner/Configs/AppInfo.xcconfig b/useragent/macos/Runner/Configs/AppInfo.xcconfig index e7d9966..ffb216d 100644 --- a/useragent/macos/Runner/Configs/AppInfo.xcconfig +++ b/useragent/macos/Runner/Configs/AppInfo.xcconfig @@ -1,14 +1,14 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = useragent - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.example.useragent - -// The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2026 com.example. All rights reserved. +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = useragent + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.useragent + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2026 com.example. All rights reserved. diff --git a/useragent/macos/Runner/Configs/Debug.xcconfig b/useragent/macos/Runner/Configs/Debug.xcconfig index 36b0fd9..b398823 100644 --- a/useragent/macos/Runner/Configs/Debug.xcconfig +++ b/useragent/macos/Runner/Configs/Debug.xcconfig @@ -1,2 +1,2 @@ -#include "../../Flutter/Flutter-Debug.xcconfig" -#include "Warnings.xcconfig" +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/useragent/macos/Runner/Configs/Release.xcconfig b/useragent/macos/Runner/Configs/Release.xcconfig index dff4f49..d93e5dc 100644 --- a/useragent/macos/Runner/Configs/Release.xcconfig +++ b/useragent/macos/Runner/Configs/Release.xcconfig @@ -1,2 +1,2 @@ -#include "../../Flutter/Flutter-Release.xcconfig" -#include "Warnings.xcconfig" +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/useragent/macos/Runner/Configs/Warnings.xcconfig b/useragent/macos/Runner/Configs/Warnings.xcconfig index 42bcbf4..fb4d7d3 100644 --- a/useragent/macos/Runner/Configs/Warnings.xcconfig +++ b/useragent/macos/Runner/Configs/Warnings.xcconfig @@ -1,13 +1,13 @@ -WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings -GCC_WARN_UNDECLARED_SELECTOR = YES -CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES -CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES -CLANG_WARN_PRAGMA_PACK = YES -CLANG_WARN_STRICT_PROTOTYPES = YES -CLANG_WARN_COMMA = YES -GCC_WARN_STRICT_SELECTOR_MATCH = YES -CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES -CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES -GCC_WARN_SHADOW = YES -CLANG_WARN_UNREACHABLE_CODE = YES +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/useragent/macos/Runner/DebugProfile.entitlements b/useragent/macos/Runner/DebugProfile.entitlements index fbad023..ff1666f 100644 --- a/useragent/macos/Runner/DebugProfile.entitlements +++ b/useragent/macos/Runner/DebugProfile.entitlements @@ -1,8 +1,8 @@ - - - - - keychain-access-groups - - - + + + + + keychain-access-groups + + + diff --git a/useragent/macos/Runner/Info.plist b/useragent/macos/Runner/Info.plist index 4789daa..3733c1a 100644 --- a/useragent/macos/Runner/Info.plist +++ b/useragent/macos/Runner/Info.plist @@ -1,32 +1,32 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - $(PRODUCT_COPYRIGHT) - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - - + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/useragent/macos/Runner/MainFlutterWindow.swift b/useragent/macos/Runner/MainFlutterWindow.swift index 3cc05eb..ab30cba 100644 --- a/useragent/macos/Runner/MainFlutterWindow.swift +++ b/useragent/macos/Runner/MainFlutterWindow.swift @@ -1,15 +1,15 @@ -import Cocoa -import FlutterMacOS - -class MainFlutterWindow: NSWindow { - override func awakeFromNib() { - let flutterViewController = FlutterViewController() - let windowFrame = self.frame - self.contentViewController = flutterViewController - self.setFrame(windowFrame, display: true) - - RegisterGeneratedPlugins(registry: flutterViewController) - - super.awakeFromNib() - } -} +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/useragent/macos/Runner/Release.entitlements b/useragent/macos/Runner/Release.entitlements index fbad023..ff1666f 100644 --- a/useragent/macos/Runner/Release.entitlements +++ b/useragent/macos/Runner/Release.entitlements @@ -1,8 +1,8 @@ - - - - - keychain-access-groups - - - + + + + + keychain-access-groups + + + diff --git a/useragent/macos/RunnerTests/RunnerTests.swift b/useragent/macos/RunnerTests/RunnerTests.swift index 61f3bd1..21fe1ab 100644 --- a/useragent/macos/RunnerTests/RunnerTests.swift +++ b/useragent/macos/RunnerTests/RunnerTests.swift @@ -1,12 +1,12 @@ -import Cocoa -import FlutterMacOS -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/useragent/mise.toml b/useragent/mise.toml index 540e6c5..0575cf2 100644 --- a/useragent/mise.toml +++ b/useragent/mise.toml @@ -1,4 +1,4 @@ -[tasks.codegen] -run = ''' - flutter_rust_bridge_codegen generate -''' +[tasks.codegen] +run = ''' + flutter_rust_bridge_codegen generate +''' diff --git a/useragent/pubspec.lock b/useragent/pubspec.lock index ba8a18d..d27b502 100644 --- a/useragent/pubspec.lock +++ b/useragent/pubspec.lock @@ -1,1289 +1,1289 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: c209688d9f5a5f26b2fb47a188131a6fb9e876ae9e47af3737c0b4f58a93470d - url: "https://pub.dev" - source: hosted - version: "91.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: f51c8499b35f9b26820cfe914828a6a98a94efd5cc78b37bb7d03debae3a1d08 - url: "https://pub.dev" - source: hosted - version: "8.4.1" - analyzer_buffer: - dependency: transitive - description: - name: analyzer_buffer - sha256: aba2f75e63b3135fd1efaa8b6abefe1aa6e41b6bd9806221620fa48f98156033 - url: "https://pub.dev" - source: hosted - version: "0.1.11" - ansicolor: - dependency: transitive - description: - name: ansicolor - sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" - url: "https://pub.dev" - source: hosted - version: "2.0.3" - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: transitive - description: - name: async - sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 - url: "https://pub.dev" - source: hosted - version: "2.13.1" - auto_route: - dependency: "direct main" - description: - name: auto_route - sha256: e9acfeb3df33d188fce4ad0239ef4238f333b7aa4d95ec52af3c2b9360dcd969 - url: "https://pub.dev" - source: hosted - version: "11.1.0" - auto_route_generator: - dependency: "direct dev" - description: - name: auto_route_generator - sha256: "04300eaf5821962aae8b5cd94f67013fd2fd326dc3be212d3ec1ae7470f09834" - url: "https://pub.dev" - source: hosted - version: "10.4.0" - biometric_signature: - dependency: "direct main" - description: - name: biometric_signature - sha256: "86a37a8b514eb3b56980ab6cc9df48ffc3c551147bdf8e3bf2afb2265a7f89e8" - url: "https://pub.dev" - source: hosted - version: "11.0.1" - bloc: - dependency: transitive - description: - name: bloc - sha256: a48653a82055a900b88cd35f92429f068c5a8057ae9b136d197b3d56c57efb81 - url: "https://pub.dev" - source: hosted - version: "9.2.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - build: - dependency: transitive - description: - name: build - sha256: aadd943f4f8cc946882c954c187e6115a84c98c81ad1d9c6cbf0895a8c85da9c - url: "https://pub.dev" - source: hosted - version: "4.0.5" - build_cli_annotations: - dependency: transitive - description: - name: build_cli_annotations - sha256: e563c2e01de8974566a1998410d3f6f03521788160a02503b0b1f1a46c7b3d95 - url: "https://pub.dev" - source: hosted - version: "2.1.1" - build_config: - dependency: transitive - description: - name: build_config - sha256: "4070d2a59f8eec34c97c86ceb44403834899075f66e8a9d59706f8e7834f6f71" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - build_daemon: - dependency: transitive - description: - name: build_daemon - sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 - url: "https://pub.dev" - source: hosted - version: "4.1.1" - build_runner: - dependency: "direct dev" - description: - name: build_runner - sha256: "521daf8d189deb79ba474e43a696b41c49fb3987818dbacf3308f1e03673a75e" - url: "https://pub.dev" - source: hosted - version: "2.13.1" - built_collection: - dependency: transitive - description: - name: built_collection - sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://pub.dev" - source: hosted - version: "5.1.1" - built_value: - dependency: transitive - description: - name: built_value - sha256: "0730c18c770d05636a8f945c32a4d7d81cb6e0f0148c8db4ad12e7748f7e49af" - url: "https://pub.dev" - source: hosted - version: "8.12.5" - characters: - dependency: transitive - description: - name: characters - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" - url: "https://pub.dev" - source: hosted - version: "2.0.4" - cli_config: - dependency: transitive - description: - name: cli_config - sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec - url: "https://pub.dev" - source: hosted - version: "0.2.0" - clock: - dependency: transitive - description: - name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" - source: hosted - version: "1.1.2" - code_assets: - dependency: transitive - description: - name: code_assets - sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - code_builder: - dependency: transitive - description: - name: code_builder - sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d" - url: "https://pub.dev" - source: hosted - version: "4.11.1" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - convert: - dependency: transitive - description: - name: convert - sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.dev" - source: hosted - version: "3.1.2" - coverage: - dependency: transitive - description: - name: coverage - sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" - url: "https://pub.dev" - source: hosted - version: "1.15.0" - cross_file: - dependency: transitive - description: - name: cross_file - sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" - url: "https://pub.dev" - source: hosted - version: "0.3.5+2" - crypto: - dependency: transitive - description: - name: crypto - sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf - url: "https://pub.dev" - source: hosted - version: "3.0.7" - cryptography: - dependency: transitive - description: - name: cryptography - sha256: "3eda3029d34ec9095a27a198ac9785630fe525c0eb6a49f3d575272f8e792ef0" - url: "https://pub.dev" - source: hosted - version: "2.9.0" - cryptography_flutter: - dependency: "direct main" - description: - name: cryptography_flutter - sha256: d1c7e7a31a072d63b27ce0537b89868f9bda9188f2b1651ae728a295762921d4 - url: "https://pub.dev" - source: hosted - version: "2.3.4" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" - url: "https://pub.dev" - source: hosted - version: "1.0.9" - dart_style: - dependency: transitive - description: - name: dart_style - sha256: a9c30492da18ff84efe2422ba2d319a89942d93e58eb0b73d32abe822ef54b7b - url: "https://pub.dev" - source: hosted - version: "3.1.3" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - ffi: - dependency: transitive - description: - name: ffi - sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - fixnum: - dependency: "direct main" - description: - name: fixnum - sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.dev" - source: hosted - version: "1.1.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_adaptive_scaffold: - dependency: "direct main" - description: - path: "." - ref: HEAD - resolved-ref: b2e3615901a7ab837cb7fc35efbfcf8b55f27638 - url: "https://github.com/hdbg/flutter_adaptive_scaffold.git" - source: git - version: "1.0.0+1" - flutter_bloc: - dependency: transitive - description: - name: flutter_bloc - sha256: cf51747952201a455a1c840f8171d273be009b932c75093020f9af64f2123e38 - url: "https://pub.dev" - source: hosted - version: "9.1.1" - flutter_driver: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - flutter_form_builder: - dependency: "direct main" - description: - name: flutter_form_builder - sha256: "1233251b4bc1d5deb245745d2a89dcebf4cdd382e1ec3f21f1c6703b700e574f" - url: "https://pub.dev" - source: hosted - version: "10.3.0+2" - flutter_hooks: - dependency: "direct main" - description: - name: flutter_hooks - sha256: "8ae1f090e5f4ef5cfa6670ce1ab5dddadd33f3533a7f9ba19d9f958aa2a89f42" - url: "https://pub.dev" - source: hosted - version: "0.21.3+1" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_riverpod: - dependency: transitive - description: - name: flutter_riverpod - sha256: "38ec6c303e2c83ee84512f5fc2a82ae311531021938e63d7137eccc107bf3c02" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - flutter_rust_bridge: - dependency: "direct main" - description: - name: flutter_rust_bridge - sha256: e87d6b9ee934dcd24a128ccb2bd91905d2d5fe5c06245d6a8f5477d4907a437a - url: "https://pub.dev" - source: hosted - version: "2.12.0" - flutter_secure_storage: - dependency: "direct main" - description: - name: flutter_secure_storage - sha256: da922f2aab2d733db7e011a6bcc4a825b844892d4edd6df83ff156b09a9b2e40 - url: "https://pub.dev" - source: hosted - version: "10.0.0" - flutter_secure_storage_darwin: - dependency: transitive - description: - name: flutter_secure_storage_darwin - sha256: "8878c25136a79def1668c75985e8e193d9d7d095453ec28730da0315dc69aee3" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - flutter_secure_storage_linux: - dependency: transitive - description: - name: flutter_secure_storage_linux - sha256: "2b5c76dce569ab752d55a1cee6a2242bcc11fdba927078fb88c503f150767cda" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - flutter_secure_storage_platform_interface: - dependency: transitive - description: - name: flutter_secure_storage_platform_interface - sha256: "8ceea1223bee3c6ac1a22dabd8feefc550e4729b3675de4b5900f55afcb435d6" - url: "https://pub.dev" - source: hosted - version: "2.0.1" - flutter_secure_storage_web: - dependency: transitive - description: - name: flutter_secure_storage_web - sha256: "6a1137df62b84b54261dca582c1c09ea72f4f9a4b2fcee21b025964132d5d0c3" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - flutter_secure_storage_windows: - dependency: transitive - description: - name: flutter_secure_storage_windows - sha256: "3b7c8e068875dfd46719ff57c90d8c459c87f2302ed6b00ff006b3c9fcad1613" - url: "https://pub.dev" - source: hosted - version: "4.1.0" - flutter_spinkit: - dependency: transitive - description: - name: flutter_spinkit - sha256: "77850df57c00dc218bfe96071d576a8babec24cf58b2ed121c83cca4a2fdce7f" - url: "https://pub.dev" - source: hosted - version: "5.2.2" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - freezed: - dependency: "direct dev" - description: - name: freezed - sha256: "13065f10e135263a4f5a4391b79a8efc5fb8106f8dd555a9e49b750b45393d77" - url: "https://pub.dev" - source: hosted - version: "3.2.3" - freezed_annotation: - dependency: "direct main" - description: - name: freezed_annotation - sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - fuchsia_remote_debug_protocol: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - glob: - dependency: transitive - description: - name: glob - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" - source: hosted - version: "2.1.3" - google_identity_services_web: - dependency: transitive - description: - name: google_identity_services_web - sha256: "5d187c46dc59e02646e10fe82665fc3884a9b71bc1c90c2b8b749316d33ee454" - url: "https://pub.dev" - source: hosted - version: "0.3.3+1" - googleapis_auth: - dependency: transitive - description: - name: googleapis_auth - sha256: b81fe352cc4a330b3710d2b7ad258d9bcef6f909bb759b306bf42973a7d046db - url: "https://pub.dev" - source: hosted - version: "2.0.0" - graphs: - dependency: transitive - description: - name: graphs - sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - group_button: - dependency: transitive - description: - name: group_button - sha256: "0610fcf28ed122bfb4b410fce161a390f7f2531d55d1d65c5375982001415940" - url: "https://pub.dev" - source: hosted - version: "5.3.4" - grpc: - dependency: "direct main" - description: - name: grpc - sha256: "86be3a7d39ad865b214a7370021ac80e68939238b507730de6d97fc662cb2723" - url: "https://pub.dev" - source: hosted - version: "5.1.0" - hooks: - dependency: transitive - description: - name: hooks - sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388 - url: "https://pub.dev" - source: hosted - version: "1.0.2" - hooks_riverpod: - dependency: "direct main" - description: - name: hooks_riverpod - sha256: b880efcd17757af0aa242e5dceac2fb781a014c22a32435a5daa8f17e9d5d8a9 - url: "https://pub.dev" - source: hosted - version: "3.1.0" - hotreloader: - dependency: transitive - description: - name: hotreloader - sha256: bc167a1163807b03bada490bfe2df25b0d744df359227880220a5cbd04e5734b - url: "https://pub.dev" - source: hosted - version: "4.3.0" - http: - dependency: transitive - description: - name: http - sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.dev" - source: hosted - version: "1.6.0" - http2: - dependency: transitive - description: - name: http2 - sha256: "382d3aefc5bd6dc68c6b892d7664f29b5beb3251611ae946a98d35158a82bbfa" - url: "https://pub.dev" - source: hosted - version: "2.3.1" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.dev" - source: hosted - version: "3.2.2" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - integration_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - intl: - dependency: transitive - description: - name: intl - sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.dev" - source: hosted - version: "0.20.2" - io: - dependency: transitive - description: - name: io - sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.dev" - source: hosted - version: "1.0.5" - js: - dependency: transitive - description: - name: js - sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" - url: "https://pub.dev" - source: hosted - version: "0.7.2" - json_annotation: - dependency: "direct main" - description: - name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.dev" - source: hosted - version: "4.9.0" - json_serializable: - dependency: "direct dev" - description: - name: json_serializable - sha256: c5b2ee75210a0f263c6c7b9eeea80553dbae96ea1bf57f02484e806a3ffdffa3 - url: "https://pub.dev" - source: hosted - version: "6.11.2" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" - source: hosted - version: "11.0.2" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" - source: hosted - version: "3.0.10" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - lean_builder: - dependency: transitive - description: - name: lean_builder - sha256: "6af3cfbf34400eb14b89fe20111e5981e7083362f00ea10b9ed2a6e833250d76" - url: "https://pub.dev" - source: hosted - version: "0.1.6" - lints: - dependency: transitive - description: - name: lints - sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" - source: hosted - version: "0.12.17" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" - url: "https://pub.dev" - source: hosted - version: "1.17.0" - mime: - dependency: transitive - description: - name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - mockito: - dependency: transitive - description: - name: mockito - sha256: eff30d002f0c8bf073b6f929df4483b543133fcafce056870163587b03f1d422 - url: "https://pub.dev" - source: hosted - version: "5.6.4" - mtcore: - dependency: "direct main" - description: - name: mtcore - sha256: "3e7ee6e0685ddc1615cece3cdce242204030aeeb4ca4bcf4586e3f1ba7d88954" - url: "https://git.markettakers.org/api/packages/MarketTakers/pub/" - source: hosted - version: "1.0.6" - native_toolchain_c: - dependency: transitive - description: - name: native_toolchain_c - sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" - url: "https://pub.dev" - source: hosted - version: "0.17.6" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - node_preamble: - dependency: transitive - description: - name: node_preamble - sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" - url: "https://pub.dev" - source: hosted - version: "2.0.2" - objective_c: - dependency: transitive - description: - name: objective_c - sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" - url: "https://pub.dev" - source: hosted - version: "9.3.0" - package_config: - dependency: transitive - description: - name: package_config - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.dev" - source: hosted - version: "2.2.0" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: "149441ca6e4f38193b2e004c0ca6376a3d11f51fa5a77552d8bd4d2b0c0912ba" - url: "https://pub.dev" - source: hosted - version: "2.2.23" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" - url: "https://pub.dev" - source: hosted - version: "2.6.0" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - percent_indicator: - dependency: transitive - description: - name: percent_indicator - sha256: "157d29133bbc6ecb11f923d36e7960a96a3f28837549a20b65e5135729f0f9fd" - url: "https://pub.dev" - source: hosted - version: "4.2.5" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - pool: - dependency: transitive - description: - name: pool - sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" - url: "https://pub.dev" - source: hosted - version: "1.5.2" - process: - dependency: transitive - description: - name: process - sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744 - url: "https://pub.dev" - source: hosted - version: "5.0.5" - protobuf: - dependency: "direct main" - description: - name: protobuf - sha256: "75ec242d22e950bdcc79ee38dd520ce4ee0bc491d7fadc4ea47694604d22bf06" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - provider: - dependency: transitive - description: - name: provider - sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" - url: "https://pub.dev" - source: hosted - version: "6.1.5+1" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" - url: "https://pub.dev" - source: hosted - version: "1.5.0" - rive: - dependency: transitive - description: - name: rive - sha256: "2d7f0b0dd6c8368c3e5a47d0a38ee68306896920aa665b5bf59e7c589a6d35a2" - url: "https://pub.dev" - source: hosted - version: "0.14.4" - rive_native: - dependency: transitive - description: - name: rive_native - sha256: fad6aac822340fa14a2cbcdc8cd064da4b4c74d22a5f6c827a59538d67f200e4 - url: "https://pub.dev" - source: hosted - version: "0.1.4" - riverpod: - dependency: "direct main" - description: - name: riverpod - sha256: "16ff608d21e8ea64364f2b7c049c94a02ab81668f78845862b6e88b71dd4935a" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - riverpod_analyzer_utils: - dependency: transitive - description: - name: riverpod_analyzer_utils - sha256: "947b05d04c52a546a2ac6b19ef2a54b08520ff6bdf9f23d67957a4c8df1c3bc0" - url: "https://pub.dev" - source: hosted - version: "1.0.0-dev.8" - riverpod_annotation: - dependency: "direct main" - description: - name: riverpod_annotation - sha256: cc1474bc2df55ec3c1da1989d139dcef22cd5e2bd78da382e867a69a8eca2e46 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - riverpod_generator: - dependency: "direct dev" - description: - name: riverpod_generator - sha256: e43b1537229cc8f487f09b0c20d15dba840acbadcf5fc6dad7ad5e8ab75950dc - url: "https://pub.dev" - source: hosted - version: "4.0.0+1" - rust_lib_arbiter: - dependency: "direct main" - description: - path: rust_builder - relative: true - source: path - version: "0.0.1" - share_plus: - dependency: transitive - description: - name: share_plus - sha256: "14c8860d4de93d3a7e53af51bff479598c4e999605290756bbbe45cf65b37840" - url: "https://pub.dev" - source: hosted - version: "12.0.1" - share_plus_platform_interface: - dependency: transitive - description: - name: share_plus_platform_interface - sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - shelf: - dependency: transitive - description: - name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 - url: "https://pub.dev" - source: hosted - version: "1.4.2" - shelf_packages_handler: - dependency: transitive - description: - name: shelf_packages_handler - sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 - url: "https://pub.dev" - source: hosted - version: "1.1.3" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - sizer: - dependency: "direct main" - description: - name: sizer - sha256: "9963c89e4d30d7c2108de3eafc0a7e6a4a8009799376ea6be5ef0a9ad87cfbad" - url: "https://pub.dev" - source: hosted - version: "3.1.3" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - source_gen: - dependency: transitive - description: - name: source_gen - sha256: "732792cfd197d2161a65bb029606a46e0a18ff30ef9e141a7a82172b05ea8ecd" - url: "https://pub.dev" - source: hosted - version: "4.2.2" - source_helper: - dependency: transitive - description: - name: source_helper - sha256: "6a3c6cc82073a8797f8c4dc4572146114a39652851c157db37e964d9c7038723" - url: "https://pub.dev" - source: hosted - version: "1.3.8" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b - url: "https://pub.dev" - source: hosted - version: "2.1.2" - source_maps: - dependency: transitive - description: - name: source_maps - sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" - url: "https://pub.dev" - source: hosted - version: "0.10.13" - source_span: - dependency: transitive - description: - name: source_span - sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" - url: "https://pub.dev" - source: hosted - version: "1.10.2" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" - source: hosted - version: "1.12.1" - state_notifier: - dependency: transitive - description: - name: state_notifier - sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb - url: "https://pub.dev" - source: hosted - version: "1.0.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - stream_transform: - dependency: transitive - description: - name: stream_transform - sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 - url: "https://pub.dev" - source: hosted - version: "2.1.1" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - sync_http: - dependency: transitive - description: - name: sync_http - sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.dev" - source: hosted - version: "0.3.1" - talker: - dependency: "direct main" - description: - name: talker - sha256: c364edc0fbd6c648e1a78e6edd89cccd64df2150ca96d899ecd486b76c185042 - url: "https://pub.dev" - source: hosted - version: "5.1.16" - talker_flutter: - dependency: transitive - description: - name: talker_flutter - sha256: "54cbbf852101721664faf4a05639fd2fdefdc37178327990abea00390690d4bc" - url: "https://pub.dev" - source: hosted - version: "5.1.16" - talker_logger: - dependency: transitive - description: - name: talker_logger - sha256: cea1b8283a28c2118a0b197057fc5beb5b0672c75e40a48725e5e452c0278ff3 - url: "https://pub.dev" - source: hosted - version: "5.1.16" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test: - dependency: transitive - description: - name: test - sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7" - url: "https://pub.dev" - source: hosted - version: "1.26.3" - test_api: - dependency: transitive - description: - name: test_api - sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 - url: "https://pub.dev" - source: hosted - version: "0.7.7" - test_core: - dependency: transitive - description: - name: test_core - sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0" - url: "https://pub.dev" - source: hosted - version: "0.6.12" - timeago: - dependency: "direct main" - description: - name: timeago - sha256: b05159406a97e1cbb2b9ee4faa9fb096fe0e2dfcd8b08fcd2a00553450d3422e - url: "https://pub.dev" - source: hosted - version: "3.7.1" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a - url: "https://pub.dev" - source: hosted - version: "3.2.2" - url_launcher_platform_interface: - dependency: transitive - description: - name: url_launcher_platform_interface - sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - url_launcher_web: - dependency: transitive - description: - name: url_launcher_web - sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f - url: "https://pub.dev" - source: hosted - version: "2.4.2" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" - url: "https://pub.dev" - source: hosted - version: "3.1.5" - uuid: - dependency: transitive - description: - name: uuid - sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" - url: "https://pub.dev" - source: hosted - version: "4.5.3" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b - url: "https://pub.dev" - source: hosted - version: "2.2.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" - url: "https://pub.dev" - source: hosted - version: "15.0.2" - watcher: - dependency: transitive - description: - name: watcher - sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a" - url: "https://pub.dev" - source: hosted - version: "1.1.4" - web: - dependency: transitive - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - web_socket: - dependency: transitive - description: - name: web_socket - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" - url: "https://pub.dev" - source: hosted - version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 - url: "https://pub.dev" - source: hosted - version: "3.0.3" - webdriver: - dependency: transitive - description: - name: webdriver - sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" - url: "https://pub.dev" - source: hosted - version: "3.1.0" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" - url: "https://pub.dev" - source: hosted - version: "1.2.1" - win32: - dependency: transitive - description: - name: win32 - sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e - url: "https://pub.dev" - source: hosted - version: "5.15.0" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - xxh3: - dependency: transitive - description: - name: xxh3 - sha256: "399a0438f5d426785723c99da6b16e136f4953fb1e9db0bf270bd41dd4619916" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - yaml: - dependency: transitive - description: - name: yaml - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" - source: hosted - version: "3.1.3" -sdks: - dart: ">=3.10.8 <4.0.0" - flutter: ">=3.38.4" +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: c209688d9f5a5f26b2fb47a188131a6fb9e876ae9e47af3737c0b4f58a93470d + url: "https://pub.dev" + source: hosted + version: "91.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: f51c8499b35f9b26820cfe914828a6a98a94efd5cc78b37bb7d03debae3a1d08 + url: "https://pub.dev" + source: hosted + version: "8.4.1" + analyzer_buffer: + dependency: transitive + description: + name: analyzer_buffer + sha256: aba2f75e63b3135fd1efaa8b6abefe1aa6e41b6bd9806221620fa48f98156033 + url: "https://pub.dev" + source: hosted + version: "0.1.11" + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f" + url: "https://pub.dev" + source: hosted + version: "2.0.3" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 + url: "https://pub.dev" + source: hosted + version: "2.13.1" + auto_route: + dependency: "direct main" + description: + name: auto_route + sha256: e9acfeb3df33d188fce4ad0239ef4238f333b7aa4d95ec52af3c2b9360dcd969 + url: "https://pub.dev" + source: hosted + version: "11.1.0" + auto_route_generator: + dependency: "direct dev" + description: + name: auto_route_generator + sha256: "04300eaf5821962aae8b5cd94f67013fd2fd326dc3be212d3ec1ae7470f09834" + url: "https://pub.dev" + source: hosted + version: "10.4.0" + biometric_signature: + dependency: "direct main" + description: + name: biometric_signature + sha256: "86a37a8b514eb3b56980ab6cc9df48ffc3c551147bdf8e3bf2afb2265a7f89e8" + url: "https://pub.dev" + source: hosted + version: "11.0.1" + bloc: + dependency: transitive + description: + name: bloc + sha256: a48653a82055a900b88cd35f92429f068c5a8057ae9b136d197b3d56c57efb81 + url: "https://pub.dev" + source: hosted + version: "9.2.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + build: + dependency: transitive + description: + name: build + sha256: aadd943f4f8cc946882c954c187e6115a84c98c81ad1d9c6cbf0895a8c85da9c + url: "https://pub.dev" + source: hosted + version: "4.0.5" + build_cli_annotations: + dependency: transitive + description: + name: build_cli_annotations + sha256: e563c2e01de8974566a1998410d3f6f03521788160a02503b0b1f1a46c7b3d95 + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: "4070d2a59f8eec34c97c86ceb44403834899075f66e8a9d59706f8e7834f6f71" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 + url: "https://pub.dev" + source: hosted + version: "4.1.1" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "521daf8d189deb79ba474e43a696b41c49fb3987818dbacf3308f1e03673a75e" + url: "https://pub.dev" + source: hosted + version: "2.13.1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "0730c18c770d05636a8f945c32a4d7d81cb6e0f0148c8db4ad12e7748f7e49af" + url: "https://pub.dev" + source: hosted + version: "8.12.5" + characters: + dependency: transitive + description: + name: characters + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + url: "https://pub.dev" + source: hosted + version: "2.0.4" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d" + url: "https://pub.dev" + source: hosted + version: "4.11.1" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" + url: "https://pub.dev" + source: hosted + version: "0.3.5+2" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + cryptography: + dependency: transitive + description: + name: cryptography + sha256: "3eda3029d34ec9095a27a198ac9785630fe525c0eb6a49f3d575272f8e792ef0" + url: "https://pub.dev" + source: hosted + version: "2.9.0" + cryptography_flutter: + dependency: "direct main" + description: + name: cryptography_flutter + sha256: d1c7e7a31a072d63b27ce0537b89868f9bda9188f2b1651ae728a295762921d4 + url: "https://pub.dev" + source: hosted + version: "2.3.4" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" + url: "https://pub.dev" + source: hosted + version: "1.0.9" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: a9c30492da18ff84efe2422ba2d319a89942d93e58eb0b73d32abe822ef54b7b + url: "https://pub.dev" + source: hosted + version: "3.1.3" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: "direct main" + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_adaptive_scaffold: + dependency: "direct main" + description: + path: "." + ref: HEAD + resolved-ref: b2e3615901a7ab837cb7fc35efbfcf8b55f27638 + url: "https://github.com/hdbg/flutter_adaptive_scaffold.git" + source: git + version: "1.0.0+1" + flutter_bloc: + dependency: transitive + description: + name: flutter_bloc + sha256: cf51747952201a455a1c840f8171d273be009b932c75093020f9af64f2123e38 + url: "https://pub.dev" + source: hosted + version: "9.1.1" + flutter_driver: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_form_builder: + dependency: "direct main" + description: + name: flutter_form_builder + sha256: "1233251b4bc1d5deb245745d2a89dcebf4cdd382e1ec3f21f1c6703b700e574f" + url: "https://pub.dev" + source: hosted + version: "10.3.0+2" + flutter_hooks: + dependency: "direct main" + description: + name: flutter_hooks + sha256: "8ae1f090e5f4ef5cfa6670ce1ab5dddadd33f3533a7f9ba19d9f958aa2a89f42" + url: "https://pub.dev" + source: hosted + version: "0.21.3+1" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_riverpod: + dependency: transitive + description: + name: flutter_riverpod + sha256: "38ec6c303e2c83ee84512f5fc2a82ae311531021938e63d7137eccc107bf3c02" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + flutter_rust_bridge: + dependency: "direct main" + description: + name: flutter_rust_bridge + sha256: e87d6b9ee934dcd24a128ccb2bd91905d2d5fe5c06245d6a8f5477d4907a437a + url: "https://pub.dev" + source: hosted + version: "2.12.0" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + sha256: da922f2aab2d733db7e011a6bcc4a825b844892d4edd6df83ff156b09a9b2e40 + url: "https://pub.dev" + source: hosted + version: "10.0.0" + flutter_secure_storage_darwin: + dependency: transitive + description: + name: flutter_secure_storage_darwin + sha256: "8878c25136a79def1668c75985e8e193d9d7d095453ec28730da0315dc69aee3" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: "2b5c76dce569ab752d55a1cee6a2242bcc11fdba927078fb88c503f150767cda" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: "8ceea1223bee3c6ac1a22dabd8feefc550e4729b3675de4b5900f55afcb435d6" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: "6a1137df62b84b54261dca582c1c09ea72f4f9a4b2fcee21b025964132d5d0c3" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: "3b7c8e068875dfd46719ff57c90d8c459c87f2302ed6b00ff006b3c9fcad1613" + url: "https://pub.dev" + source: hosted + version: "4.1.0" + flutter_spinkit: + dependency: transitive + description: + name: flutter_spinkit + sha256: "77850df57c00dc218bfe96071d576a8babec24cf58b2ed121c83cca4a2fdce7f" + url: "https://pub.dev" + source: hosted + version: "5.2.2" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + freezed: + dependency: "direct dev" + description: + name: freezed + sha256: "13065f10e135263a4f5a4391b79a8efc5fb8106f8dd555a9e49b750b45393d77" + url: "https://pub.dev" + source: hosted + version: "3.2.3" + freezed_annotation: + dependency: "direct main" + description: + name: freezed_annotation + sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + fuchsia_remote_debug_protocol: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + google_identity_services_web: + dependency: transitive + description: + name: google_identity_services_web + sha256: "5d187c46dc59e02646e10fe82665fc3884a9b71bc1c90c2b8b749316d33ee454" + url: "https://pub.dev" + source: hosted + version: "0.3.3+1" + googleapis_auth: + dependency: transitive + description: + name: googleapis_auth + sha256: b81fe352cc4a330b3710d2b7ad258d9bcef6f909bb759b306bf42973a7d046db + url: "https://pub.dev" + source: hosted + version: "2.0.0" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + group_button: + dependency: transitive + description: + name: group_button + sha256: "0610fcf28ed122bfb4b410fce161a390f7f2531d55d1d65c5375982001415940" + url: "https://pub.dev" + source: hosted + version: "5.3.4" + grpc: + dependency: "direct main" + description: + name: grpc + sha256: "86be3a7d39ad865b214a7370021ac80e68939238b507730de6d97fc662cb2723" + url: "https://pub.dev" + source: hosted + version: "5.1.0" + hooks: + dependency: transitive + description: + name: hooks + sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388 + url: "https://pub.dev" + source: hosted + version: "1.0.2" + hooks_riverpod: + dependency: "direct main" + description: + name: hooks_riverpod + sha256: b880efcd17757af0aa242e5dceac2fb781a014c22a32435a5daa8f17e9d5d8a9 + url: "https://pub.dev" + source: hosted + version: "3.1.0" + hotreloader: + dependency: transitive + description: + name: hotreloader + sha256: bc167a1163807b03bada490bfe2df25b0d744df359227880220a5cbd04e5734b + url: "https://pub.dev" + source: hosted + version: "4.3.0" + http: + dependency: transitive + description: + name: http + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" + url: "https://pub.dev" + source: hosted + version: "1.6.0" + http2: + dependency: transitive + description: + name: http2 + sha256: "382d3aefc5bd6dc68c6b892d7664f29b5beb3251611ae946a98d35158a82bbfa" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + integration_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + intl: + dependency: transitive + description: + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://pub.dev" + source: hosted + version: "0.20.2" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + js: + dependency: transitive + description: + name: js + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + url: "https://pub.dev" + source: hosted + version: "0.7.2" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: c5b2ee75210a0f263c6c7b9eeea80553dbae96ea1bf57f02484e806a3ffdffa3 + url: "https://pub.dev" + source: hosted + version: "6.11.2" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.dev" + source: hosted + version: "11.0.2" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" + source: hosted + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + lean_builder: + dependency: transitive + description: + name: lean_builder + sha256: "6af3cfbf34400eb14b89fe20111e5981e7083362f00ea10b9ed2a6e833250d76" + url: "https://pub.dev" + source: hosted + version: "0.1.6" + lints: + dependency: transitive + description: + name: lints + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" + source: hosted + version: "0.12.17" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mockito: + dependency: transitive + description: + name: mockito + sha256: eff30d002f0c8bf073b6f929df4483b543133fcafce056870163587b03f1d422 + url: "https://pub.dev" + source: hosted + version: "5.6.4" + mtcore: + dependency: "direct main" + description: + name: mtcore + sha256: "3e7ee6e0685ddc1615cece3cdce242204030aeeb4ca4bcf4586e3f1ba7d88954" + url: "https://git.markettakers.org/api/packages/MarketTakers/pub/" + source: hosted + version: "1.0.6" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" + url: "https://pub.dev" + source: hosted + version: "0.17.6" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" + url: "https://pub.dev" + source: hosted + version: "9.3.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "149441ca6e4f38193b2e004c0ca6376a3d11f51fa5a77552d8bd4d2b0c0912ba" + url: "https://pub.dev" + source: hosted + version: "2.2.23" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + percent_indicator: + dependency: transitive + description: + name: percent_indicator + sha256: "157d29133bbc6ecb11f923d36e7960a96a3f28837549a20b65e5135729f0f9fd" + url: "https://pub.dev" + source: hosted + version: "4.2.5" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pool: + dependency: transitive + description: + name: pool + sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" + url: "https://pub.dev" + source: hosted + version: "1.5.2" + process: + dependency: transitive + description: + name: process + sha256: c6248e4526673988586e8c00bb22a49210c258dc91df5227d5da9748ecf79744 + url: "https://pub.dev" + source: hosted + version: "5.0.5" + protobuf: + dependency: "direct main" + description: + name: protobuf + sha256: "75ec242d22e950bdcc79ee38dd520ce4ee0bc491d7fadc4ea47694604d22bf06" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + provider: + dependency: transitive + description: + name: provider + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" + url: "https://pub.dev" + source: hosted + version: "6.1.5+1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + rive: + dependency: transitive + description: + name: rive + sha256: "2d7f0b0dd6c8368c3e5a47d0a38ee68306896920aa665b5bf59e7c589a6d35a2" + url: "https://pub.dev" + source: hosted + version: "0.14.4" + rive_native: + dependency: transitive + description: + name: rive_native + sha256: fad6aac822340fa14a2cbcdc8cd064da4b4c74d22a5f6c827a59538d67f200e4 + url: "https://pub.dev" + source: hosted + version: "0.1.4" + riverpod: + dependency: "direct main" + description: + name: riverpod + sha256: "16ff608d21e8ea64364f2b7c049c94a02ab81668f78845862b6e88b71dd4935a" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + riverpod_analyzer_utils: + dependency: transitive + description: + name: riverpod_analyzer_utils + sha256: "947b05d04c52a546a2ac6b19ef2a54b08520ff6bdf9f23d67957a4c8df1c3bc0" + url: "https://pub.dev" + source: hosted + version: "1.0.0-dev.8" + riverpod_annotation: + dependency: "direct main" + description: + name: riverpod_annotation + sha256: cc1474bc2df55ec3c1da1989d139dcef22cd5e2bd78da382e867a69a8eca2e46 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + riverpod_generator: + dependency: "direct dev" + description: + name: riverpod_generator + sha256: e43b1537229cc8f487f09b0c20d15dba840acbadcf5fc6dad7ad5e8ab75950dc + url: "https://pub.dev" + source: hosted + version: "4.0.0+1" + rust_lib_arbiter: + dependency: "direct main" + description: + path: rust_builder + relative: true + source: path + version: "0.0.1" + share_plus: + dependency: transitive + description: + name: share_plus + sha256: "14c8860d4de93d3a7e53af51bff479598c4e999605290756bbbe45cf65b37840" + url: "https://pub.dev" + source: hosted + version: "12.0.1" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + sizer: + dependency: "direct main" + description: + name: sizer + sha256: "9963c89e4d30d7c2108de3eafc0a7e6a4a8009799376ea6be5ef0a9ad87cfbad" + url: "https://pub.dev" + source: hosted + version: "3.1.3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "732792cfd197d2161a65bb029606a46e0a18ff30ef9e141a7a82172b05ea8ecd" + url: "https://pub.dev" + source: hosted + version: "4.2.2" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6a3c6cc82073a8797f8c4dc4572146114a39652851c157db37e964d9c7038723" + url: "https://pub.dev" + source: hosted + version: "1.3.8" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" + source_span: + dependency: transitive + description: + name: source_span + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" + source: hosted + version: "1.10.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + state_notifier: + dependency: transitive + description: + name: state_notifier + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb + url: "https://pub.dev" + source: hosted + version: "1.0.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + talker: + dependency: "direct main" + description: + name: talker + sha256: c364edc0fbd6c648e1a78e6edd89cccd64df2150ca96d899ecd486b76c185042 + url: "https://pub.dev" + source: hosted + version: "5.1.16" + talker_flutter: + dependency: transitive + description: + name: talker_flutter + sha256: "54cbbf852101721664faf4a05639fd2fdefdc37178327990abea00390690d4bc" + url: "https://pub.dev" + source: hosted + version: "5.1.16" + talker_logger: + dependency: transitive + description: + name: talker_logger + sha256: cea1b8283a28c2118a0b197057fc5beb5b0672c75e40a48725e5e452c0278ff3 + url: "https://pub.dev" + source: hosted + version: "5.1.16" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test: + dependency: transitive + description: + name: test + sha256: "75906bf273541b676716d1ca7627a17e4c4070a3a16272b7a3dc7da3b9f3f6b7" + url: "https://pub.dev" + source: hosted + version: "1.26.3" + test_api: + dependency: transitive + description: + name: test_api + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 + url: "https://pub.dev" + source: hosted + version: "0.7.7" + test_core: + dependency: transitive + description: + name: test_core + sha256: "0cc24b5ff94b38d2ae73e1eb43cc302b77964fbf67abad1e296025b78deb53d0" + url: "https://pub.dev" + source: hosted + version: "0.6.12" + timeago: + dependency: "direct main" + description: + name: timeago + sha256: b05159406a97e1cbb2b9ee4faa9fb096fe0e2dfcd8b08fcd2a00553450d3422e + url: "https://pub.dev" + source: hosted + version: "3.7.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a + url: "https://pub.dev" + source: hosted + version: "3.2.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f + url: "https://pub.dev" + source: hosted + version: "2.4.2" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + uuid: + dependency: transitive + description: + name: uuid + sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" + url: "https://pub.dev" + source: hosted + version: "4.5.3" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + url: "https://pub.dev" + source: hosted + version: "15.0.2" + watcher: + dependency: transitive + description: + name: watcher + sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a" + url: "https://pub.dev" + source: hosted + version: "1.1.4" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webdriver: + dependency: transitive + description: + name: webdriver + sha256: "2f3a14ca026957870cfd9c635b83507e0e51d8091568e90129fbf805aba7cade" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + win32: + dependency: transitive + description: + name: win32 + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + url: "https://pub.dev" + source: hosted + version: "5.15.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + xxh3: + dependency: transitive + description: + name: xxh3 + sha256: "399a0438f5d426785723c99da6b16e136f4953fb1e9db0bf270bd41dd4619916" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.10.8 <4.0.0" + flutter: ">=3.38.4" diff --git a/useragent/pubspec.yaml b/useragent/pubspec.yaml index eb26c37..b9b834c 100644 --- a/useragent/pubspec.yaml +++ b/useragent/pubspec.yaml @@ -1,54 +1,54 @@ -name: arbiter -description: "Useragent for Arbiter project" -publish_to: 'none' -version: 1.0.0+1 - -environment: - sdk: ^3.10.8 - -dependencies: - flutter: - sdk: flutter - - cupertino_icons: ^1.0.8 - flutter_adaptive_scaffold: - git: https://github.com/hdbg/flutter_adaptive_scaffold.git - talker: ^5.1.15 - riverpod: ^3.1.0 - hooks_riverpod: ^3.1.0 - sizer: ^3.1.3 - biometric_signature: ^11.0.1 - mtcore: - hosted: https://git.markettakers.org/api/packages/MarketTakers/pub/ - version: ^1.0.6 - flutter_secure_storage: ^10.0.0 - cryptography_flutter: ^2.3.4 - riverpod_annotation: ^4.0.0 - grpc: ^5.1.0 - fixnum: ^1.1.1 - flutter_hooks: ^0.21.3+1 - auto_route: ^11.1.0 - protobuf: ^6.0.0 - freezed_annotation: ^3.1.0 - json_annotation: ^4.9.0 - timeago: ^3.7.1 - flutter_form_builder: ^10.3.0+2 - rust_lib_arbiter: - path: rust_builder - flutter_rust_bridge: 2.12.0 - -dev_dependencies: - flutter_test: - sdk: flutter - - flutter_lints: ^6.0.0 - riverpod_generator: ^4.0.0+1 - build_runner: ^2.12.2 - auto_route_generator: ^10.4.0 - freezed: ^3.2.3 - json_serializable: ^6.11.2 - integration_test: - sdk: flutter - -flutter: - uses-material-design: true +name: arbiter +description: "Useragent for Arbiter project" +publish_to: 'none' +version: 1.0.0+1 + +environment: + sdk: ^3.10.8 + +dependencies: + flutter: + sdk: flutter + + cupertino_icons: ^1.0.8 + flutter_adaptive_scaffold: + git: https://github.com/hdbg/flutter_adaptive_scaffold.git + talker: ^5.1.15 + riverpod: ^3.1.0 + hooks_riverpod: ^3.1.0 + sizer: ^3.1.3 + biometric_signature: ^11.0.1 + mtcore: + hosted: https://git.markettakers.org/api/packages/MarketTakers/pub/ + version: ^1.0.6 + flutter_secure_storage: ^10.0.0 + cryptography_flutter: ^2.3.4 + riverpod_annotation: ^4.0.0 + grpc: ^5.1.0 + fixnum: ^1.1.1 + flutter_hooks: ^0.21.3+1 + auto_route: ^11.1.0 + protobuf: ^6.0.0 + freezed_annotation: ^3.1.0 + json_annotation: ^4.9.0 + timeago: ^3.7.1 + flutter_form_builder: ^10.3.0+2 + rust_lib_arbiter: + path: rust_builder + flutter_rust_bridge: 2.12.0 + +dev_dependencies: + flutter_test: + sdk: flutter + + flutter_lints: ^6.0.0 + riverpod_generator: ^4.0.0+1 + build_runner: ^2.12.2 + auto_route_generator: ^10.4.0 + freezed: ^3.2.3 + json_serializable: ^6.11.2 + integration_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/useragent/rust/.gitignore b/useragent/rust/.gitignore index ea8c4bf..0b42d2d 100644 --- a/useragent/rust/.gitignore +++ b/useragent/rust/.gitignore @@ -1 +1 @@ -/target +/target diff --git a/useragent/rust/Cargo.lock b/useragent/rust/Cargo.lock index 5442523..0c37fb7 100644 --- a/useragent/rust/Cargo.lock +++ b/useragent/rust/Cargo.lock @@ -1,5218 +1,5218 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "ab_glyph" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" - -[[package]] -name = "accesskit" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5351dcebb14b579ccab05f288596b2ae097005be7ee50a7c3d4ca9d0d5a66f6a" -dependencies = [ - "uuid", -] - -[[package]] -name = "accesskit_atspi_common" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "842fd8203e6dfcf531d24f5bac792088edfba7d6b35844fead191603fb32a260" -dependencies = [ - "accesskit", - "accesskit_consumer", - "atspi-common", - "phf", - "serde", - "zvariant", -] - -[[package]] -name = "accesskit_consumer" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53cf47daed85312e763fbf85ceca136e0d7abc68e0a7e12abe11f48172bc3b10" -dependencies = [ - "accesskit", - "hashbrown 0.16.1", -] - -[[package]] -name = "accesskit_macos" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534bc3fdc89a64a1db3c46b33c198fde2b7c3c7d094e5809c8c8bf2970c18243" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown 0.16.1", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "accesskit_unix" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e549dd7c6562b6a2ea807b44726e6241707db054a817dc4c7e2b8d3b39bfac" -dependencies = [ - "accesskit", - "accesskit_atspi_common", - "async-channel", - "async-executor", - "async-task", - "atspi", - "futures-lite", - "futures-util", - "serde", - "zbus", -] - -[[package]] -name = "accesskit_windows" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff7009f1a532e917d66970a1e80c965140c6cfbbabbdde3d64e5431e6c78e21" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown 0.16.1", - "static_assertions", - "windows", - "windows-core", -] - -[[package]] -name = "accesskit_winit" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fe9a94394896352cc4660ca2288bd4ef883d83238853c038b44070c8f134313" -dependencies = [ - "accesskit", - "accesskit_macos", - "accesskit_unix", - "accesskit_windows", - "raw-window-handle", - "winit", -] - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "getrandom 0.3.4", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "allo-isolate" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449e356a4864c017286dbbec0e12767ea07efba29e3b7d984194c2a7ff3c4550" -dependencies = [ - "anyhow", - "atomic", - "backtrace", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "android-activity" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" -dependencies = [ - "android-properties", - "bitflags 2.11.0", - "cc", - "jni", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-sys", - "num_enum", - "thiserror 2.0.18", -] - -[[package]] -name = "android-properties" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" - -[[package]] -name = "android_log-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" - -[[package]] -name = "android_logger" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" -dependencies = [ - "android_log-sys", - "env_filter", - "log", -] - -[[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.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" - -[[package]] -name = "arbiter-crypto" -version = "0.1.0" -dependencies = [ - "chrono", - "memsafe", - "ml-dsa", - "rand", - "x-wing", -] - -[[package]] -name = "arboard" -version = "3.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" -dependencies = [ - "clipboard-win", - "image", - "log", - "objc2 0.6.4", - "objc2-app-kit 0.3.2", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-foundation 0.3.2", - "parking_lot", - "percent-encoding", - "windows-sys 0.60.2", - "x11rb", -] - -[[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 = "as-raw-xcb-connection" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" - -[[package]] -name = "ash" -version = "0.38.0+1.3.281" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" -dependencies = [ - "libloading", -] - -[[package]] -name = "async-broadcast" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-channel" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-executor" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "pin-project-lite", - "slab", -] - -[[package]] -name = "async-io" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" -dependencies = [ - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix 1.1.4", - "slab", - "windows-sys 0.61.2", -] - -[[package]] -name = "async-lock" -version = "3.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-process" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" -dependencies = [ - "async-channel", - "async-io", - "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix 1.1.4", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "async-signal" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" -dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix 1.1.4", - "signal-hook-registry", - "slab", - "windows-sys 0.61.2", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - -[[package]] -name = "async-trait" -version = "0.1.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atomic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "atspi" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77886257be21c9cd89a4ae7e64860c6f0eefca799bb79127913052bd0eefb3d" -dependencies = [ - "atspi-common", - "atspi-proxies", -] - -[[package]] -name = "atspi-common" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c5617155740c98003016429ad13fe43ce7a77b007479350a9f8bf95a29f63d" -dependencies = [ - "enumflags2", - "serde", - "static_assertions", - "zbus", - "zbus-lockstep", - "zbus-lockstep-macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "atspi-proxies" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2230e48787ed3eb4088996eab66a32ca20c0b67bbd4fd6cdfe79f04f1f04c9fc" -dependencies = [ - "atspi-common", - "serde", - "zbus", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide 0.7.1", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64ct" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" - -[[package]] -name = "bit-set" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ddef2995421ab6a5c779542c81ee77c115206f4ad9d5a8e05f4ff49716a3dd" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" - -[[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-buffer" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2 0.5.2", -] - -[[package]] -name = "block2" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" -dependencies = [ - "objc2 0.6.4", -] - -[[package]] -name = "blocking" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" -dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", -] - -[[package]] -name = "build-target" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "bytemuck" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "byteorder-lite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" - -[[package]] -name = "bytes" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" - -[[package]] -name = "calloop" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" -dependencies = [ - "bitflags 2.11.0", - "log", - "polling", - "rustix 0.38.44", - "slab", - "thiserror 1.0.69", -] - -[[package]] -name = "calloop" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" -dependencies = [ - "bitflags 2.11.0", - "polling", - "rustix 1.1.4", - "slab", - "tracing", -] - -[[package]] -name = "calloop-wayland-source" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" -dependencies = [ - "calloop 0.13.0", - "rustix 0.38.44", - "wayland-backend", - "wayland-client", -] - -[[package]] -name = "calloop-wayland-source" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" -dependencies = [ - "calloop 0.14.4", - "rustix 1.1.4", - "wayland-backend", - "wayland-client", -] - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "jobserver", - "libc", -] - -[[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 = "cgl" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" -dependencies = [ - "libc", -] - -[[package]] -name = "chacha20" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "rand_core", -] - -[[package]] -name = "chrono" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "clipboard-win" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" -dependencies = [ - "error-code", -] - -[[package]] -name = "cmov" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" - -[[package]] -name = "codespan-reporting" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" -dependencies = [ - "serde", - "termcolor", - "unicode-width", -] - -[[package]] -name = "color" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18ef4657441fb193b65f34dc39b3781f0dfec23d3bd94d0eeb4e88cde421edb" -dependencies = [ - "bytemuck", -] - -[[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_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 = "const-oid" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" - -[[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" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -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 = "core-graphics" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" -dependencies = [ - "cfg-if", -] - -[[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.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-common" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" -dependencies = [ - "hybrid-array", - "rand_core", -] - -[[package]] -name = "ctutils" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" -dependencies = [ - "cmov", -] - -[[package]] -name = "cursor-icon" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" - -[[package]] -name = "curve25519-dalek" -version = "5.0.0-pre.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335f1947f241137a14106b6f5acc5918a5ede29c9d71d3f2cb1678d5075d9fc3" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "curve25519-dalek-derive", - "fiat-crypto", - "rustc_version", - "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", -] - -[[package]] -name = "dart-sys" -version = "4.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57967e4b200d767d091b961d6ab42cc7d0cc14fe9e052e75d0d3cf9eb732d895" -dependencies = [ - "cc", -] - -[[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 = "delegate-attr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51aac4c99b2e6775164b412ea33ae8441b2fde2dbf05a20bc0052a63d08c475b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "der" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b" -dependencies = [ - "const-oid", - "zeroize", -] - -[[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 0.1.6", -] - -[[package]] -name = "digest" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" -dependencies = [ - "block-buffer 0.12.0", - "crypto-common 0.2.1", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dispatch2" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" -dependencies = [ - "bitflags 2.11.0", - "objc2 0.6.4", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dlib" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" -dependencies = [ - "libloading", -] - -[[package]] -name = "document-features" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" -dependencies = [ - "litrs", -] - -[[package]] -name = "downcast-rs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" - -[[package]] -name = "dpi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" - -[[package]] -name = "ecolor" -version = "0.34.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "137c0ce4ce4152ff7e223a7ce22ee1057cdff61fce0a45c32459c3ccec64868d" -dependencies = [ - "bytemuck", - "emath", -] - -[[package]] -name = "eframe" -version = "0.34.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6e995b8e434d65aefd12c4519221be3e8f38efd77804ef39ca10553f4ad7063" -dependencies = [ - "ahash", - "bytemuck", - "document-features", - "egui", - "egui-wgpu", - "egui-winit", - "egui_glow", - "glutin", - "glutin-winit", - "image", - "js-sys", - "log", - "objc2 0.6.4", - "objc2-app-kit 0.3.2", - "objc2-foundation 0.3.2", - "parking_lot", - "percent-encoding", - "pollster", - "profiling", - "raw-window-handle", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "web-time", - "wgpu", - "windows-sys 0.61.2", - "winit", -] - -[[package]] -name = "egui" -version = "0.34.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34aaf627da598dfadd64b0fee6101d22e9c451d1e5348157312720b7f459f0f" -dependencies = [ - "accesskit", - "ahash", - "bitflags 2.11.0", - "emath", - "epaint", - "log", - "nohash-hasher", - "profiling", - "smallvec", - "unicode-segmentation", -] - -[[package]] -name = "egui-wgpu" -version = "0.34.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71033ff78b041c9c363450f4498ff95468ef3ecbcc71a62f67036a6207d98fa4" -dependencies = [ - "ahash", - "bytemuck", - "document-features", - "egui", - "epaint", - "log", - "profiling", - "thiserror 2.0.18", - "type-map", - "web-time", - "wgpu", - "winit", -] - -[[package]] -name = "egui-winit" -version = "0.34.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a2881b2bf1a305e413e644af63f836737a33d85077705ff808e88f902ff742" -dependencies = [ - "accesskit_winit", - "arboard", - "bytemuck", - "egui", - "log", - "objc2 0.6.4", - "objc2-foundation 0.3.2", - "objc2-ui-kit 0.3.2", - "profiling", - "raw-window-handle", - "smithay-clipboard", - "web-time", - "webbrowser", - "winit", -] - -[[package]] -name = "egui_glow" -version = "0.34.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b28d39ab6c0cac238190e6cb1e8c9047d02cb470ab942a7a3302e4cb3a8e74" -dependencies = [ - "bytemuck", - "egui", - "glow", - "log", - "memoffset", - "profiling", - "wasm-bindgen", - "web-sys", - "winit", -] - -[[package]] -name = "emath" -version = "0.34.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a05cd8bdf3b598488c627ca97c7fe8909448ffa26278dd3c7e535cdb554d721" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "endi" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" - -[[package]] -name = "enumflags2" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "env_filter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "epaint" -version = "0.34.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f3017dd67f147a697ee0c8484fb568fd9553e2a0c114be5020dbbc11962841" -dependencies = [ - "ahash", - "bytemuck", - "ecolor", - "emath", - "epaint_default_fonts", - "font-types", - "log", - "nohash-hasher", - "parking_lot", - "profiling", - "self_cell", - "skrifa", - "smallvec", - "vello_cpu", -] - -[[package]] -name = "epaint_default_fonts" -version = "0.34.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3b85a2bb775a3ab02d077a65cc31575c11b2584581913253cc11ce49f48bba" - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "error-code" -version = "3.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" - -[[package]] -name = "euclid" -version = "0.22.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" -dependencies = [ - "num-traits", -] - -[[package]] -name = "event-listener" -version = "5.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" -dependencies = [ - "event-listener", - "pin-project-lite", -] - -[[package]] -name = "fastrand" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" - -[[package]] -name = "fax" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" -dependencies = [ - "fax_derive", -] - -[[package]] -name = "fax_derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "fearless_simd" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb2907d1f08b2b316b9223ced5b0e89d87028ba8deae9764741dba8ff7f3903" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "fiat-crypto" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" - -[[package]] -name = "flate2" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" -dependencies = [ - "crc32fast", - "miniz_oxide 0.8.9", -] - -[[package]] -name = "flutter_rust_bridge" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0884853aae8a6517b5b58cf36f55da487f2fe110e1686938eb29b6640aae4a5" -dependencies = [ - "allo-isolate", - "android_logger", - "anyhow", - "build-target", - "bytemuck", - "byteorder", - "console_error_panic_hook", - "dart-sys", - "delegate-attr", - "flutter_rust_bridge_macros", - "futures", - "js-sys", - "lazy_static", - "log", - "oslog", - "portable-atomic", - "threadpool", - "tokio", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "flutter_rust_bridge_macros" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b5ce32f35f710ced8c5aa557f023f1a624e737b5460cee2b70fcd3a8df09e1b" -dependencies = [ - "hex", - "md-5", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foldhash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" - -[[package]] -name = "font-types" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9237c6d82152100c691fb77ea18037b402bcc7257d2c876a4ffac81bc22a1c" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" - -[[package]] -name = "futures-executor" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" - -[[package]] -name = "futures-lite" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "futures-macro" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" - -[[package]] -name = "futures-task" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" - -[[package]] -name = "futures-util" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "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 = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" -dependencies = [ - "rustix 1.1.4", - "windows-link", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi 5.3.0", - "wasip2", -] - -[[package]] -name = "getrandom" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" -dependencies = [ - "cfg-if", - "libc", - "r-efi 6.0.0", - "rand_core", - "wasip2", - "wasip3", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "gl_generator" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" -dependencies = [ - "khronos_api", - "log", - "xml-rs", -] - -[[package]] -name = "glow" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glutin" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" -dependencies = [ - "bitflags 2.11.0", - "cfg_aliases", - "cgl", - "dispatch2", - "glutin_egl_sys", - "glutin_glx_sys", - "glutin_wgl_sys", - "libloading", - "objc2 0.6.4", - "objc2-app-kit 0.3.2", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "once_cell", - "raw-window-handle", - "wayland-sys", - "windows-sys 0.52.0", - "x11-dl", -] - -[[package]] -name = "glutin-winit" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" -dependencies = [ - "cfg_aliases", - "glutin", - "raw-window-handle", - "winit", -] - -[[package]] -name = "glutin_egl_sys" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" -dependencies = [ - "gl_generator", - "windows-sys 0.52.0", -] - -[[package]] -name = "glutin_glx_sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" -dependencies = [ - "gl_generator", - "x11-dl", -] - -[[package]] -name = "glutin_wgl_sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" -dependencies = [ - "gl_generator", -] - -[[package]] -name = "gpu-allocator" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" -dependencies = [ - "ash", - "hashbrown 0.16.1", - "log", - "presser", - "thiserror 2.0.18", - "windows", -] - -[[package]] -name = "gpu-descriptor" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" -dependencies = [ - "bitflags 2.11.0", - "gpu-descriptor-types", - "hashbrown 0.15.5", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "num-traits", - "zerocopy", -] - -[[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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", -] - -[[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.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "hybrid-array" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" -dependencies = [ - "ctutils", - "typenum", - "zeroize", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "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 = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" -dependencies = [ - "displaydoc", - "potential_utf", - "utf8_iter", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" - -[[package]] -name = "icu_properties" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" - -[[package]] -name = "icu_provider" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "image" -version = "0.25.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" -dependencies = [ - "bytemuck", - "byteorder-lite", - "moxcms", - "num-traits", - "png", - "tiff", -] - -[[package]] -name = "indexmap" -version = "2.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" -dependencies = [ - "equivalent", - "hashbrown 0.16.1", - "serde", - "serde_core", -] - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "jni" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" -dependencies = [ - "cfg-if", - "combine", - "jni-macros", - "jni-sys 0.4.1", - "log", - "simd_cesu8", - "thiserror 2.0.18", - "walkdir", - "windows-link", -] - -[[package]] -name = "jni-macros" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "simd_cesu8", - "syn", -] - -[[package]] -name = "jni-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" -dependencies = [ - "jni-sys 0.4.1", -] - -[[package]] -name = "jni-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" -dependencies = [ - "jni-sys-macros", -] - -[[package]] -name = "jni-sys-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" -dependencies = [ - "cfg-if", - "futures-util", - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "keccak" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", -] - -[[package]] -name = "kem" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01737161ba802849cfd486b5bd209d38ba4943494c249a8126005170c7621edd" -dependencies = [ - "crypto-common 0.2.1", - "rand_core", -] - -[[package]] -name = "khronos-egl" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" -dependencies = [ - "libc", - "libloading", - "pkg-config", -] - -[[package]] -name = "khronos_api" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" - -[[package]] -name = "kurbo" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7564e90fe3c0d5771e1f0bc95322b21baaeaa0d9213fa6a0b61c99f8b17b3bfb" -dependencies = [ - "arrayvec", - "euclid", - "smallvec", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - -[[package]] -name = "libc" -version = "0.2.184" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" - -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link", -] - -[[package]] -name = "libm" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" - -[[package]] -name = "libredox" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" -dependencies = [ - "bitflags 2.11.0", - "libc", - "plain", - "redox_syscall 0.7.3", -] - -[[package]] -name = "linebender_resource_handle" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - -[[package]] -name = "litemap" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" - -[[package]] -name = "litrs" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[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.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" - -[[package]] -name = "memmap2" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" -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 = "memsafe" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f3e199d5e8adf073900f95b635f1192c394a442ed406c16dc7991b74501645" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "ml-dsa" -version = "0.1.0-rc.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5b2bb0ad6fa2b40396775bd56f51345171490fef993f46f91a876ecdbdaea55" -dependencies = [ - "const-oid", - "ctutils", - "hybrid-array", - "module-lattice", - "pkcs8", - "rand_core", - "sha3", - "signature", - "zeroize", -] - -[[package]] -name = "ml-kem" -version = "0.3.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04437cb1a66c0b78740927b76cc61f218344b9f6ef3dd430e283274a718ef0e9" -dependencies = [ - "hybrid-array", - "kem", - "module-lattice", - "rand_core", - "sha3", - "zeroize", -] - -[[package]] -name = "module-lattice" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164eb3faeaecbd14b0b2a917c1b4d0c035097a9c559b0bed85c2cdd032bc8faa" -dependencies = [ - "ctutils", - "hybrid-array", - "num-traits", - "zeroize", -] - -[[package]] -name = "moxcms" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" -dependencies = [ - "num-traits", - "pxfm", -] - -[[package]] -name = "naga" -version = "29.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2630921705b9b01dcdd0b6864b9562ca3c1951eecd0f0c4f5f04f61e412647" -dependencies = [ - "arrayvec", - "bit-set", - "bitflags 2.11.0", - "cfg-if", - "cfg_aliases", - "codespan-reporting", - "half", - "hashbrown 0.16.1", - "hexf-parse", - "indexmap", - "libm", - "log", - "num-traits", - "once_cell", - "rustc-hash 1.1.0", - "spirv", - "thiserror 2.0.18", - "unicode-ident", -] - -[[package]] -name = "ndk" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" -dependencies = [ - "bitflags 2.11.0", - "jni-sys 0.3.1", - "log", - "ndk-sys", - "num_enum", - "raw-window-handle", - "thiserror 1.0.69", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.6.0+11769913" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" -dependencies = [ - "jni-sys 0.3.1", -] - -[[package]] -name = "nohash-hasher" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" - -[[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.3", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" -dependencies = [ - "num_enum_derive", - "rustversion", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" -dependencies = [ - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" -dependencies = [ - "objc2-encode", -] - -[[package]] -name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.11.0", - "block2 0.5.1", - "libc", - "objc2 0.5.2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation 0.2.2", - "objc2-quartz-core 0.2.2", -] - -[[package]] -name = "objc2-app-kit" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" -dependencies = [ - "bitflags 2.11.0", - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-foundation 0.3.2", -] - -[[package]] -name = "objc2-cloud-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" -dependencies = [ - "bitflags 2.11.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-core-location", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-contacts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags 2.11.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-core-foundation" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" -dependencies = [ - "bitflags 2.11.0", - "dispatch2", - "objc2 0.6.4", -] - -[[package]] -name = "objc2-core-graphics" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" -dependencies = [ - "bitflags 2.11.0", - "dispatch2", - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-io-surface", -] - -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", -] - -[[package]] -name = "objc2-core-location" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-contacts", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-encode" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" - -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.11.0", - "block2 0.5.1", - "dispatch", - "libc", - "objc2 0.5.2", -] - -[[package]] -name = "objc2-foundation" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" -dependencies = [ - "bitflags 2.11.0", - "block2 0.6.2", - "objc2 0.6.4", - "objc2-core-foundation", -] - -[[package]] -name = "objc2-io-surface" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" -dependencies = [ - "bitflags 2.11.0", - "objc2 0.6.4", - "objc2-core-foundation", -] - -[[package]] -name = "objc2-link-presentation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-metal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.11.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-metal" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" -dependencies = [ - "bitflags 2.11.0", - "block2 0.6.2", - "objc2 0.6.4", - "objc2-foundation 0.3.2", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags 2.11.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" -dependencies = [ - "bitflags 2.11.0", - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-metal 0.3.2", -] - -[[package]] -name = "objc2-symbols" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" -dependencies = [ - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-ui-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" -dependencies = [ - "bitflags 2.11.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-cloud-kit", - "objc2-core-data", - "objc2-core-image", - "objc2-core-location", - "objc2-foundation 0.2.2", - "objc2-link-presentation", - "objc2-quartz-core 0.2.2", - "objc2-symbols", - "objc2-uniform-type-identifiers", - "objc2-user-notifications", -] - -[[package]] -name = "objc2-ui-kit" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" -dependencies = [ - "bitflags 2.11.0", - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-foundation 0.3.2", -] - -[[package]] -name = "objc2-uniform-type-identifiers" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-user-notifications" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" -dependencies = [ - "bitflags 2.11.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-core-location", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "orbclient" -version = "0.3.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59aed3b33578edcfa1bc96a321d590d31832b6ad55a26f0313362ce687e9abd6" -dependencies = [ - "libc", - "libredox", -] - -[[package]] -name = "ordered-float" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "oslog" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d2043d1f61d77cb2f4b1f7b7b2295f40507f5f8e9d1c8bf10a1ca5f97a3969" -dependencies = [ - "cc", - "dashmap", - "log", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" -dependencies = [ - "ttf-parser", -] - -[[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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.5.18", - "smallvec", - "windows-link", -] - -[[package]] -name = "peniko" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2b6aadb221872732e87d465213e9be5af2849b0e8cc5300a8ba98fffa2e00a" -dependencies = [ - "bytemuck", - "color", - "kurbo", - "linebender_resource_handle", - "smallvec", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "phf" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" -dependencies = [ - "phf_macros", - "phf_shared", - "serde", -] - -[[package]] -name = "phf_generator" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" -dependencies = [ - "fastrand", - "phf_shared", -] - -[[package]] -name = "phf_macros" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "piper" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - -[[package]] -name = "pkcs8" -version = "0.11.0-rc.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12922b6296c06eb741b02d7b5161e3aaa22864af38dfa025a1a3ba3f68c84577" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "png" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" -dependencies = [ - "bitflags 2.11.0", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide 0.8.9", -] - -[[package]] -name = "polling" -version = "3.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi 0.5.2", - "pin-project-lite", - "rustix 1.1.4", - "windows-sys 0.61.2", -] - -[[package]] -name = "pollster" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" - -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - -[[package]] -name = "portable-atomic-util" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" -dependencies = [ - "portable-atomic", -] - -[[package]] -name = "potential_utf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" -dependencies = [ - "zerovec", -] - -[[package]] -name = "presser" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" - -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro-crate" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" -dependencies = [ - "toml_edit", -] - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "profiling" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" - -[[package]] -name = "pxfm" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - -[[package]] -name = "quick-xml" -version = "0.38.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "quick-xml" -version = "0.39.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" -dependencies = [ - "memchr", -] - -[[package]] -name = "quote" -version = "1.0.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "r-efi" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" - -[[package]] -name = "rand" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" -dependencies = [ - "chacha20", - "getrandom 0.4.2", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" - -[[package]] -name = "range-alloc" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" - -[[package]] -name = "raw-window-handle" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" - -[[package]] -name = "raw-window-metal" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" -dependencies = [ - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-quartz-core 0.3.2", -] - -[[package]] -name = "read-fonts" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" -dependencies = [ - "bytemuck", - "font-types", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "redox_syscall" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "renderdoc-sys" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" - -[[package]] -name = "rust_lib_arbiter" -version = "0.1.0" -dependencies = [ - "anyhow", - "arbiter-crypto", - "eframe", - "egui", - "flutter_rust_bridge", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.11.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" -dependencies = [ - "bitflags 2.11.0", - "errno", - "libc", - "linux-raw-sys 0.12.1", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[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 = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sctk-adwaita" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" -dependencies = [ - "ab_glyph", - "log", - "memmap2", - "smithay-client-toolkit 0.19.2", - "tiny-skia", -] - -[[package]] -name = "self_cell" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" - -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.149" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "serde_repr" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sha3" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" -dependencies = [ - "digest 0.11.2", - "keccak", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] - -[[package]] -name = "signature" -version = "3.0.0-rc.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f1880df446116126965eeec169136b2e0251dba37c6223bcc819569550edea3" -dependencies = [ - "digest 0.11.2", - "rand_core", -] - -[[package]] -name = "simd-adler32" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" - -[[package]] -name = "simd_cesu8" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" -dependencies = [ - "rustc_version", - "simdutf8", -] - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - -[[package]] -name = "siphasher" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" - -[[package]] -name = "skrifa" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" -dependencies = [ - "bytemuck", - "read-fonts", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "slotmap" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" -dependencies = [ - "version_check", -] - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "smithay-client-toolkit" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" -dependencies = [ - "bitflags 2.11.0", - "calloop 0.13.0", - "calloop-wayland-source 0.3.0", - "cursor-icon", - "libc", - "log", - "memmap2", - "rustix 0.38.44", - "thiserror 1.0.69", - "wayland-backend", - "wayland-client", - "wayland-csd-frame", - "wayland-cursor", - "wayland-protocols", - "wayland-protocols-wlr", - "wayland-scanner", - "xkeysym", -] - -[[package]] -name = "smithay-client-toolkit" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" -dependencies = [ - "bitflags 2.11.0", - "calloop 0.14.4", - "calloop-wayland-source 0.4.1", - "cursor-icon", - "libc", - "log", - "memmap2", - "rustix 1.1.4", - "thiserror 2.0.18", - "wayland-backend", - "wayland-client", - "wayland-csd-frame", - "wayland-cursor", - "wayland-protocols", - "wayland-protocols-experimental", - "wayland-protocols-misc", - "wayland-protocols-wlr", - "wayland-scanner", - "xkeysym", -] - -[[package]] -name = "smithay-clipboard" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" -dependencies = [ - "libc", - "smithay-client-toolkit 0.20.0", - "wayland-backend", -] - -[[package]] -name = "smol_str" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" -dependencies = [ - "serde", -] - -[[package]] -name = "spirv" -version = "0.4.0+sdk-1.4.341.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" -dependencies = [ - "bitflags 2.11.0", -] - -[[package]] -name = "spki" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strict-num" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tempfile" -version = "3.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" -dependencies = [ - "fastrand", - "getrandom 0.4.2", - "once_cell", - "rustix 1.1.4", - "windows-sys 0.61.2", -] - -[[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.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl 2.0.18", -] - -[[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", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "threadpool" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" -dependencies = [ - "num_cpus", -] - -[[package]] -name = "tiff" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" -dependencies = [ - "fax", - "flate2", - "half", - "quick-error", - "weezl", - "zune-jpeg", -] - -[[package]] -name = "tiny-skia" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if", - "log", - "tiny-skia-path", -] - -[[package]] -name = "tiny-skia-path" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" -dependencies = [ - "arrayref", - "bytemuck", - "strict-num", -] - -[[package]] -name = "tinystr" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tokio" -version = "1.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" -dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", -] - -[[package]] -name = "toml_datetime" -version = "1.1.1+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_edit" -version = "0.25.10+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" -dependencies = [ - "indexmap", - "toml_datetime", - "toml_parser", - "winnow 1.0.1", -] - -[[package]] -name = "toml_parser" -version = "1.1.2+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" -dependencies = [ - "winnow 1.0.1", -] - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "ttf-parser" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" - -[[package]] -name = "type-map" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" -dependencies = [ - "rustc-hash 2.1.2", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "uds_windows" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" -dependencies = [ - "memoffset", - "tempfile", - "windows-sys 0.61.2", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-segmentation" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" - -[[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "url" -version = "2.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid" -version = "1.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" -dependencies = [ - "js-sys", - "serde_core", - "wasm-bindgen", -] - -[[package]] -name = "vello_common" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bd1a4c633ce09e7d713df1a6e036644a125e15e0c169cfb5180ddf5836ca04b" -dependencies = [ - "bytemuck", - "fearless_simd", - "hashbrown 0.16.1", - "log", - "peniko", - "skrifa", - "smallvec", -] - -[[package]] -name = "vello_cpu" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162bfe48aabf6a9fdcd401b628c7d9f260c2cbabb343c70a65feba6f7849edc" -dependencies = [ - "bytemuck", - "hashbrown 0.16.1", - "vello_common", -] - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[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 = "wasip2" -version = "1.0.2+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.117" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.11.0", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - -[[package]] -name = "wayland-backend" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" -dependencies = [ - "cc", - "downcast-rs", - "rustix 1.1.4", - "scoped-tls", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-client" -version = "0.31.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" -dependencies = [ - "bitflags 2.11.0", - "rustix 1.1.4", - "wayland-backend", - "wayland-scanner", -] - -[[package]] -name = "wayland-csd-frame" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" -dependencies = [ - "bitflags 2.11.0", - "cursor-icon", - "wayland-backend", -] - -[[package]] -name = "wayland-cursor" -version = "0.31.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" -dependencies = [ - "rustix 1.1.4", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.32.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-experimental" -version = "20250721.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-misc" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-plasma" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-wlr" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" -dependencies = [ - "bitflags 2.11.0", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" -dependencies = [ - "proc-macro2", - "quick-xml 0.39.2", - "quote", -] - -[[package]] -name = "wayland-sys" -version = "0.31.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" -dependencies = [ - "dlib", - "log", - "once_cell", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" -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 = "webbrowser" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe985f41e291eecef5e5c0770a18d28390addb03331c043964d9e916453d6f16" -dependencies = [ - "core-foundation 0.10.1", - "jni", - "log", - "ndk-context", - "objc2 0.6.4", - "objc2-foundation 0.3.2", - "url", - "web-sys", -] - -[[package]] -name = "weezl" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" - -[[package]] -name = "wgpu" -version = "29.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c239a9a747bbd379590985bac952c2e53cb19873f7072b3370c6a6a8e06837" -dependencies = [ - "arrayvec", - "bitflags 2.11.0", - "bytemuck", - "cfg-if", - "cfg_aliases", - "document-features", - "hashbrown 0.16.1", - "js-sys", - "log", - "naga", - "parking_lot", - "portable-atomic", - "profiling", - "raw-window-handle", - "smallvec", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "29.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e80ac6cf1895df6342f87d975162108f9d98772a0d74bc404ab7304ac29469e" -dependencies = [ - "arrayvec", - "bit-set", - "bit-vec", - "bitflags 2.11.0", - "bytemuck", - "cfg_aliases", - "document-features", - "hashbrown 0.16.1", - "indexmap", - "log", - "naga", - "once_cell", - "parking_lot", - "portable-atomic", - "profiling", - "raw-window-handle", - "rustc-hash 1.1.0", - "smallvec", - "thiserror 2.0.18", - "wgpu-core-deps-apple", - "wgpu-core-deps-emscripten", - "wgpu-core-deps-wasm", - "wgpu-core-deps-windows-linux-android", - "wgpu-hal", - "wgpu-naga-bridge", - "wgpu-types", -] - -[[package]] -name = "wgpu-core-deps-apple" -version = "29.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43acd053312501689cd92a01a9638d37f3e41a5fd9534875efa8917ee2d11ac0" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-emscripten" -version = "29.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef043bf135cc68b6f667c55ff4e345ce2b5924d75bad36a47921b0287ca4b24a" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-wasm" -version = "29.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7b75e72f49035f000dd5262e4126242e92a090a4fd75931ecfe7e60784e6fa" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-windows-linux-android" -version = "29.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "725d5c006a8c02967b6d93ef04f6537ec4593313e330cfe86d9d3f946eb90f28" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-hal" -version = "29.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a47aef47636562f3937285af4c44b4b5b404b46577471411cc5313a921da7e" -dependencies = [ - "android_system_properties", - "arrayvec", - "ash", - "bit-set", - "bitflags 2.11.0", - "block2 0.6.2", - "bytemuck", - "cfg-if", - "cfg_aliases", - "glow", - "glutin_wgl_sys", - "gpu-allocator", - "gpu-descriptor", - "hashbrown 0.16.1", - "js-sys", - "khronos-egl", - "libc", - "libloading", - "log", - "naga", - "ndk-sys", - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-metal 0.3.2", - "objc2-quartz-core 0.3.2", - "once_cell", - "ordered-float", - "parking_lot", - "portable-atomic", - "portable-atomic-util", - "profiling", - "range-alloc", - "raw-window-handle", - "raw-window-metal", - "renderdoc-sys", - "smallvec", - "thiserror 2.0.18", - "wasm-bindgen", - "wayland-sys", - "web-sys", - "wgpu-naga-bridge", - "wgpu-types", - "windows", - "windows-core", -] - -[[package]] -name = "wgpu-naga-bridge" -version = "29.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4684f4410da0cf95a4cb63bb5edaac022461dedb6adf0b64d0d9b5f6890d51" -dependencies = [ - "naga", - "wgpu-types", -] - -[[package]] -name = "wgpu-types" -version = "29.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2675540fb1a5cfa5ef122d3d5f390e2c75711a0b946410f2d6ac3a0f77d1f6" -dependencies = [ - "bitflags 2.11.0", - "bytemuck", - "js-sys", - "log", - "raw-window-handle", - "web-sys", -] - -[[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.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - -[[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" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" -dependencies = [ - "windows-collections", - "windows-core", - "windows-future", - "windows-numerics", -] - -[[package]] -name = "windows-collections" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" -dependencies = [ - "windows-core", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-future" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" -dependencies = [ - "windows-core", - "windows-link", - "windows-threading", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-numerics" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" -dependencies = [ - "windows-core", - "windows-link", -] - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[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-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[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 0.52.6", - "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-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows-threading" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" -dependencies = [ - "windows-link", -] - -[[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[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_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[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_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[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_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - -[[package]] -name = "winit" -version = "0.30.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" -dependencies = [ - "ahash", - "android-activity", - "atomic-waker", - "bitflags 2.11.0", - "block2 0.5.1", - "bytemuck", - "calloop 0.13.0", - "cfg_aliases", - "concurrent-queue", - "core-foundation 0.9.4", - "core-graphics", - "cursor-icon", - "dpi", - "js-sys", - "libc", - "memmap2", - "ndk", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", - "objc2-ui-kit 0.2.2", - "orbclient", - "percent-encoding", - "pin-project", - "raw-window-handle", - "redox_syscall 0.4.1", - "rustix 0.38.44", - "sctk-adwaita", - "smithay-client-toolkit 0.19.2", - "smol_str", - "tracing", - "unicode-segmentation", - "wasm-bindgen", - "wasm-bindgen-futures", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-protocols-plasma", - "web-sys", - "web-time", - "windows-sys 0.52.0", - "x11-dl", - "x11rb", - "xkbcommon-dl", -] - -[[package]] -name = "winnow" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" -dependencies = [ - "memchr", -] - -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.0", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - -[[package]] -name = "writeable" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" - -[[package]] -name = "x-wing" -version = "0.1.0-rc.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d0d5f4d1f26b9b9e7477af1d3bef960e1d1fb64edab7912fde472a8a8432e" -dependencies = [ - "kem", - "ml-kem", - "rand_core", - "sha3", - "x25519-dalek", - "zeroize", -] - -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "x11rb" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" -dependencies = [ - "as-raw-xcb-connection", - "gethostname", - "libc", - "libloading", - "once_cell", - "rustix 1.1.4", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" - -[[package]] -name = "x25519-dalek" -version = "3.0.0-pre.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d5d6ff67acd3945b933e592bfa7143db4fcbb2f871754b6b9fbd7847fc5aea" -dependencies = [ - "curve25519-dalek", - "rand_core", - "zeroize", -] - -[[package]] -name = "xcursor" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" - -[[package]] -name = "xkbcommon-dl" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" -dependencies = [ - "bitflags 2.11.0", - "dlib", - "log", - "once_cell", - "xkeysym", -] - -[[package]] -name = "xkeysym" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" - -[[package]] -name = "xml-rs" -version = "0.8.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" - -[[package]] -name = "yoke" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zbus" -version = "5.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" -dependencies = [ - "async-broadcast", - "async-executor", - "async-io", - "async-lock", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "enumflags2", - "event-listener", - "futures-core", - "futures-lite", - "hex", - "libc", - "ordered-stream", - "rustix 1.1.4", - "serde", - "serde_repr", - "tracing", - "uds_windows", - "uuid", - "windows-sys 0.61.2", - "winnow 0.7.15", - "zbus_macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus-lockstep" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6998de05217a084b7578728a9443d04ea4cd80f2a0839b8d78770b76ccd45863" -dependencies = [ - "zbus_xml", - "zvariant", -] - -[[package]] -name = "zbus-lockstep-macros" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "zbus-lockstep", - "zbus_xml", - "zvariant", -] - -[[package]] -name = "zbus_macros" -version = "5.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", - "zbus_names", - "zvariant", - "zvariant_utils", -] - -[[package]] -name = "zbus_names" -version = "4.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" -dependencies = [ - "serde", - "winnow 0.7.15", - "zvariant", -] - -[[package]] -name = "zbus_xml" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "441a0064125265655bccc3a6af6bef56814d9277ac83fce48b1cd7e160b80eac" -dependencies = [ - "quick-xml 0.38.4", - "serde", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zerocopy" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerofrom" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" - -[[package]] -name = "zerotrie" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" - -[[package]] -name = "zune-core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" - -[[package]] -name = "zune-jpeg" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" -dependencies = [ - "zune-core", -] - -[[package]] -name = "zvariant" -version = "5.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" -dependencies = [ - "endi", - "enumflags2", - "serde", - "winnow 0.7.15", - "zvariant_derive", - "zvariant_utils", -] - -[[package]] -name = "zvariant_derive" -version = "5.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", - "zvariant_utils", -] - -[[package]] -name = "zvariant_utils" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "syn", - "winnow 0.7.15", -] +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "accesskit" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5351dcebb14b579ccab05f288596b2ae097005be7ee50a7c3d4ca9d0d5a66f6a" +dependencies = [ + "uuid", +] + +[[package]] +name = "accesskit_atspi_common" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "842fd8203e6dfcf531d24f5bac792088edfba7d6b35844fead191603fb32a260" +dependencies = [ + "accesskit", + "accesskit_consumer", + "atspi-common", + "phf", + "serde", + "zvariant", +] + +[[package]] +name = "accesskit_consumer" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53cf47daed85312e763fbf85ceca136e0d7abc68e0a7e12abe11f48172bc3b10" +dependencies = [ + "accesskit", + "hashbrown 0.16.1", +] + +[[package]] +name = "accesskit_macos" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534bc3fdc89a64a1db3c46b33c198fde2b7c3c7d094e5809c8c8bf2970c18243" +dependencies = [ + "accesskit", + "accesskit_consumer", + "hashbrown 0.16.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "accesskit_unix" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e549dd7c6562b6a2ea807b44726e6241707db054a817dc4c7e2b8d3b39bfac" +dependencies = [ + "accesskit", + "accesskit_atspi_common", + "async-channel", + "async-executor", + "async-task", + "atspi", + "futures-lite", + "futures-util", + "serde", + "zbus", +] + +[[package]] +name = "accesskit_windows" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff7009f1a532e917d66970a1e80c965140c6cfbbabbdde3d64e5431e6c78e21" +dependencies = [ + "accesskit", + "accesskit_consumer", + "hashbrown 0.16.1", + "static_assertions", + "windows", + "windows-core", +] + +[[package]] +name = "accesskit_winit" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fe9a94394896352cc4660ca2288bd4ef883d83238853c038b44070c8f134313" +dependencies = [ + "accesskit", + "accesskit_macos", + "accesskit_unix", + "accesskit_windows", + "raw-window-handle", + "winit", +] + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "allo-isolate" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "449e356a4864c017286dbbec0e12767ea07efba29e3b7d984194c2a7ff3c4550" +dependencies = [ + "anyhow", + "atomic", + "backtrace", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-activity" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" +dependencies = [ + "android-properties", + "bitflags 2.11.0", + "cc", + "jni", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror 2.0.18", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" +dependencies = [ + "android_log-sys", + "env_filter", + "log", +] + +[[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.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arbiter-crypto" +version = "0.1.0" +dependencies = [ + "chrono", + "memsafe", + "ml-dsa", + "rand", + "x-wing", +] + +[[package]] +name = "arboard" +version = "3.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" +dependencies = [ + "clipboard-win", + "image", + "log", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", + "parking_lot", + "percent-encoding", + "windows-sys 0.60.2", + "x11rb", +] + +[[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 = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "ash" +version = "0.38.0+1.3.281" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" +dependencies = [ + "libloading", +] + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.4", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 1.1.4", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-signal" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.4", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "atspi" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77886257be21c9cd89a4ae7e64860c6f0eefca799bb79127913052bd0eefb3d" +dependencies = [ + "atspi-common", + "atspi-proxies", +] + +[[package]] +name = "atspi-common" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c5617155740c98003016429ad13fe43ce7a77b007479350a9f8bf95a29f63d" +dependencies = [ + "enumflags2", + "serde", + "static_assertions", + "zbus", + "zbus-lockstep", + "zbus-lockstep-macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "atspi-proxies" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2230e48787ed3eb4088996eab66a32ca20c0b67bbd4fd6cdfe79f04f1f04c9fc" +dependencies = [ + "atspi-common", + "serde", + "zbus", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide 0.7.1", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "bit-set" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ddef2995421ab6a5c779542c81ee77c115206f4ad9d5a8e05f4ff49716a3dd" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[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-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.4", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "build-target" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.11.0", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" +dependencies = [ + "bitflags 2.11.0", + "polling", + "rustix 1.1.4", + "slab", + "tracing", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop 0.13.0", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" +dependencies = [ + "calloop 0.14.4", + "rustix 1.1.4", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "jobserver", + "libc", +] + +[[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 = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core", +] + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "clipboard-win" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" +dependencies = [ + "error-code", +] + +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "color" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18ef4657441fb193b65f34dc39b3781f0dfec23d3bd94d0eeb4e88cde421edb" +dependencies = [ + "bytemuck", +] + +[[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_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 = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + +[[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" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +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 = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "crypto-common" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +dependencies = [ + "hybrid-array", + "rand_core", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", +] + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "curve25519-dalek" +version = "5.0.0-pre.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335f1947f241137a14106b6f5acc5918a5ede29c9d71d3f2cb1678d5075d9fc3" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "curve25519-dalek-derive", + "fiat-crypto", + "rustc_version", + "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", +] + +[[package]] +name = "dart-sys" +version = "4.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57967e4b200d767d091b961d6ab42cc7d0cc14fe9e052e75d0d3cf9eb732d895" +dependencies = [ + "cc", +] + +[[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 = "delegate-attr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51aac4c99b2e6775164b412ea33ae8441b2fde2dbf05a20bc0052a63d08c475b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "der" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b" +dependencies = [ + "const-oid", + "zeroize", +] + +[[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 0.1.6", +] + +[[package]] +name = "digest" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" +dependencies = [ + "block-buffer 0.12.0", + "crypto-common 0.2.1", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dlib" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" +dependencies = [ + "libloading", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "ecolor" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "137c0ce4ce4152ff7e223a7ce22ee1057cdff61fce0a45c32459c3ccec64868d" +dependencies = [ + "bytemuck", + "emath", +] + +[[package]] +name = "eframe" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6e995b8e434d65aefd12c4519221be3e8f38efd77804ef39ca10553f4ad7063" +dependencies = [ + "ahash", + "bytemuck", + "document-features", + "egui", + "egui-wgpu", + "egui-winit", + "egui_glow", + "glutin", + "glutin-winit", + "image", + "js-sys", + "log", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-foundation 0.3.2", + "parking_lot", + "percent-encoding", + "pollster", + "profiling", + "raw-window-handle", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time", + "wgpu", + "windows-sys 0.61.2", + "winit", +] + +[[package]] +name = "egui" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f34aaf627da598dfadd64b0fee6101d22e9c451d1e5348157312720b7f459f0f" +dependencies = [ + "accesskit", + "ahash", + "bitflags 2.11.0", + "emath", + "epaint", + "log", + "nohash-hasher", + "profiling", + "smallvec", + "unicode-segmentation", +] + +[[package]] +name = "egui-wgpu" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71033ff78b041c9c363450f4498ff95468ef3ecbcc71a62f67036a6207d98fa4" +dependencies = [ + "ahash", + "bytemuck", + "document-features", + "egui", + "epaint", + "log", + "profiling", + "thiserror 2.0.18", + "type-map", + "web-time", + "wgpu", + "winit", +] + +[[package]] +name = "egui-winit" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a2881b2bf1a305e413e644af63f836737a33d85077705ff808e88f902ff742" +dependencies = [ + "accesskit_winit", + "arboard", + "bytemuck", + "egui", + "log", + "objc2 0.6.4", + "objc2-foundation 0.3.2", + "objc2-ui-kit 0.3.2", + "profiling", + "raw-window-handle", + "smithay-clipboard", + "web-time", + "webbrowser", + "winit", +] + +[[package]] +name = "egui_glow" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3b28d39ab6c0cac238190e6cb1e8c9047d02cb470ab942a7a3302e4cb3a8e74" +dependencies = [ + "bytemuck", + "egui", + "glow", + "log", + "memoffset", + "profiling", + "wasm-bindgen", + "web-sys", + "winit", +] + +[[package]] +name = "emath" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a05cd8bdf3b598488c627ca97c7fe8909448ffa26278dd3c7e535cdb554d721" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "endi" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "epaint" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f3017dd67f147a697ee0c8484fb568fd9553e2a0c114be5020dbbc11962841" +dependencies = [ + "ahash", + "bytemuck", + "ecolor", + "emath", + "epaint_default_fonts", + "font-types", + "log", + "nohash-hasher", + "parking_lot", + "profiling", + "self_cell", + "skrifa", + "smallvec", + "vello_cpu", +] + +[[package]] +name = "epaint_default_fonts" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e3b85a2bb775a3ab02d077a65cc31575c11b2584581913253cc11ce49f48bba" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "error-code" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "fearless_simd" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb2907d1f08b2b316b9223ced5b0e89d87028ba8deae9764741dba8ff7f3903" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "fiat-crypto" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "flutter_rust_bridge" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0884853aae8a6517b5b58cf36f55da487f2fe110e1686938eb29b6640aae4a5" +dependencies = [ + "allo-isolate", + "android_logger", + "anyhow", + "build-target", + "bytemuck", + "byteorder", + "console_error_panic_hook", + "dart-sys", + "delegate-attr", + "flutter_rust_bridge_macros", + "futures", + "js-sys", + "lazy_static", + "log", + "oslog", + "portable-atomic", + "threadpool", + "tokio", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "flutter_rust_bridge_macros" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b5ce32f35f710ced8c5aa557f023f1a624e737b5460cee2b70fcd3a8df09e1b" +dependencies = [ + "hex", + "md-5", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "font-types" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d9237c6d82152100c691fb77ea18037b402bcc7257d2c876a4ffac81bc22a1c" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "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 = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.4", + "windows-link", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "rand_core", + "wasip2", + "wasip3", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glow" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" +dependencies = [ + "bitflags 2.11.0", + "cfg_aliases", + "cgl", + "dispatch2", + "glutin_egl_sys", + "glutin_glx_sys", + "glutin_wgl_sys", + "libloading", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "once_cell", + "raw-window-handle", + "wayland-sys", + "windows-sys 0.52.0", + "x11-dl", +] + +[[package]] +name = "glutin-winit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" +dependencies = [ + "cfg_aliases", + "glutin", + "raw-window-handle", + "winit", +] + +[[package]] +name = "glutin_egl_sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" +dependencies = [ + "gl_generator", + "windows-sys 0.52.0", +] + +[[package]] +name = "glutin_glx_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" +dependencies = [ + "gl_generator", + "x11-dl", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "gpu-allocator" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" +dependencies = [ + "ash", + "hashbrown 0.16.1", + "log", + "presser", + "thiserror 2.0.18", + "windows", +] + +[[package]] +name = "gpu-descriptor" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" +dependencies = [ + "bitflags 2.11.0", + "gpu-descriptor-types", + "hashbrown 0.15.5", +] + +[[package]] +name = "gpu-descriptor-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", +] + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[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.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hexf-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" + +[[package]] +name = "hybrid-array" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" +dependencies = [ + "ctutils", + "typenum", + "zeroize", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "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 = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png", + "tiff", +] + +[[package]] +name = "indexmap" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", +] + +[[package]] +name = "kem" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01737161ba802849cfd486b5bd209d38ba4943494c249a8126005170c7621edd" +dependencies = [ + "crypto-common 0.2.1", + "rand_core", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "kurbo" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7564e90fe3c0d5771e1f0bc95322b21baaeaa0d9213fa6a0b61c99f8b17b3bfb" +dependencies = [ + "arrayvec", + "euclid", + "smallvec", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.184" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +dependencies = [ + "bitflags 2.11.0", + "libc", + "plain", + "redox_syscall 0.7.3", +] + +[[package]] +name = "linebender_resource_handle" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[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.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +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 = "memsafe" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f3e199d5e8adf073900f95b635f1192c394a442ed406c16dc7991b74501645" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "ml-dsa" +version = "0.1.0-rc.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5b2bb0ad6fa2b40396775bd56f51345171490fef993f46f91a876ecdbdaea55" +dependencies = [ + "const-oid", + "ctutils", + "hybrid-array", + "module-lattice", + "pkcs8", + "rand_core", + "sha3", + "signature", + "zeroize", +] + +[[package]] +name = "ml-kem" +version = "0.3.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04437cb1a66c0b78740927b76cc61f218344b9f6ef3dd430e283274a718ef0e9" +dependencies = [ + "hybrid-array", + "kem", + "module-lattice", + "rand_core", + "sha3", + "zeroize", +] + +[[package]] +name = "module-lattice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "164eb3faeaecbd14b0b2a917c1b4d0c035097a9c559b0bed85c2cdd032bc8faa" +dependencies = [ + "ctutils", + "hybrid-array", + "num-traits", + "zeroize", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "naga" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2630921705b9b01dcdd0b6864b9562ca3c1951eecd0f0c4f5f04f61e412647" +dependencies = [ + "arrayvec", + "bit-set", + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases", + "codespan-reporting", + "half", + "hashbrown 0.16.1", + "hexf-parse", + "indexmap", + "libm", + "log", + "num-traits", + "once_cell", + "rustc-hash 1.1.0", + "spirv", + "thiserror 2.0.18", + "unicode-ident", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.11.0", + "jni-sys 0.3.1", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[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.3", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.11.0", + "dispatch2", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.11.0", + "dispatch2", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.11.0", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.11.0", + "block2 0.6.2", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core 0.2.2", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags 2.11.0", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.11.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "orbclient" +version = "0.3.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59aed3b33578edcfa1bc96a321d590d31832b6ad55a26f0313362ce687e9abd6" +dependencies = [ + "libc", + "libredox", +] + +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "oslog" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d2043d1f61d77cb2f4b1f7b7b2295f40507f5f8e9d1c8bf10a1ca5f97a3969" +dependencies = [ + "cc", + "dashmap", + "log", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser", +] + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link", +] + +[[package]] +name = "peniko" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2b6aadb221872732e87d465213e9be5af2849b0e8cc5300a8ba98fffa2e00a" +dependencies = [ + "bytemuck", + "color", + "kurbo", + "linebender_resource_handle", + "smallvec", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros", + "phf_shared", + "serde", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkcs8" +version = "0.11.0-rc.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12922b6296c06eb741b02d7b5161e3aaa22864af38dfa025a1a3ba3f68c84577" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.11.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.5.2", + "pin-project-lite", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" + +[[package]] +name = "pxfm" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quick-xml" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "quick-xml" +version = "0.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + +[[package]] +name = "range-alloc" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" +dependencies = [ + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "read-fonts" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5" +dependencies = [ + "bytemuck", + "font-types", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "redox_syscall" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "renderdoc-sys" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" + +[[package]] +name = "rust_lib_arbiter" +version = "0.1.0" +dependencies = [ + "anyhow", + "arbiter-crypto", + "eframe", + "egui", + "flutter_rust_bridge", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.11.0", + "errno", + "libc", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[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 = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit 0.19.2", + "tiny-skia", +] + +[[package]] +name = "self_cell" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha3" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" +dependencies = [ + "digest 0.11.2", + "keccak", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "signature" +version = "3.0.0-rc.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f1880df446116126965eeec169136b2e0251dba37c6223bcc819569550edea3" +dependencies = [ + "digest 0.11.2", + "rand_core", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "siphasher" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" + +[[package]] +name = "skrifa" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac" +dependencies = [ + "bytemuck", + "read-fonts", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.11.0", + "calloop 0.13.0", + "calloop-wayland-source 0.3.0", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-client-toolkit" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" +dependencies = [ + "bitflags 2.11.0", + "calloop 0.14.4", + "calloop-wayland-source 0.4.1", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 1.1.4", + "thiserror 2.0.18", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-clipboard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" +dependencies = [ + "libc", + "smithay-client-toolkit 0.20.0", + "wayland-backend", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "spirv" +version = "0.4.0+sdk-1.4.341.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "spki" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + +[[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.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[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", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +dependencies = [ + "backtrace", + "num_cpus", + "pin-project-lite", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.10+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow 1.0.1", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.1", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" + +[[package]] +name = "type-map" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" +dependencies = [ + "rustc-hash 2.1.2", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset", + "tempfile", + "windows-sys 0.61.2", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-segmentation" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "vello_common" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd1a4c633ce09e7d713df1a6e036644a125e15e0c169cfb5180ddf5836ca04b" +dependencies = [ + "bytemuck", + "fearless_simd", + "hashbrown 0.16.1", + "log", + "peniko", + "skrifa", + "smallvec", +] + +[[package]] +name = "vello_cpu" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0162bfe48aabf6a9fdcd401b628c7d9f260c2cbabb343c70a65feba6f7849edc" +dependencies = [ + "bytemuck", + "hashbrown 0.16.1", + "vello_common", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[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 = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + +[[package]] +name = "wayland-backend" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.4", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" +dependencies = [ + "bitflags 2.11.0", + "rustix 1.1.4", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.11.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" +dependencies = [ + "rustix 1.1.4", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-experimental" +version = "20250721.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" +dependencies = [ + "bitflags 2.11.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a" +dependencies = [ + "proc-macro2", + "quick-xml 0.39.2", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +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 = "webbrowser" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe985f41e291eecef5e5c0770a18d28390addb03331c043964d9e916453d6f16" +dependencies = [ + "core-foundation 0.10.1", + "jni", + "log", + "ndk-context", + "objc2 0.6.4", + "objc2-foundation 0.3.2", + "url", + "web-sys", +] + +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "wgpu" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c239a9a747bbd379590985bac952c2e53cb19873f7072b3370c6a6a8e06837" +dependencies = [ + "arrayvec", + "bitflags 2.11.0", + "bytemuck", + "cfg-if", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "js-sys", + "log", + "naga", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "smallvec", + "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "wgpu-core", + "wgpu-hal", + "wgpu-types", +] + +[[package]] +name = "wgpu-core" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e80ac6cf1895df6342f87d975162108f9d98772a0d74bc404ab7304ac29469e" +dependencies = [ + "arrayvec", + "bit-set", + "bit-vec", + "bitflags 2.11.0", + "bytemuck", + "cfg_aliases", + "document-features", + "hashbrown 0.16.1", + "indexmap", + "log", + "naga", + "once_cell", + "parking_lot", + "portable-atomic", + "profiling", + "raw-window-handle", + "rustc-hash 1.1.0", + "smallvec", + "thiserror 2.0.18", + "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", + "wgpu-core-deps-wasm", + "wgpu-core-deps-windows-linux-android", + "wgpu-hal", + "wgpu-naga-bridge", + "wgpu-types", +] + +[[package]] +name = "wgpu-core-deps-apple" +version = "29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43acd053312501689cd92a01a9638d37f3e41a5fd9534875efa8917ee2d11ac0" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-emscripten" +version = "29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef043bf135cc68b6f667c55ff4e345ce2b5924d75bad36a47921b0287ca4b24a" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-wasm" +version = "29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f7b75e72f49035f000dd5262e4126242e92a090a4fd75931ecfe7e60784e6fa" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-core-deps-windows-linux-android" +version = "29.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "725d5c006a8c02967b6d93ef04f6537ec4593313e330cfe86d9d3f946eb90f28" +dependencies = [ + "wgpu-hal", +] + +[[package]] +name = "wgpu-hal" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a47aef47636562f3937285af4c44b4b5b404b46577471411cc5313a921da7e" +dependencies = [ + "android_system_properties", + "arrayvec", + "ash", + "bit-set", + "bitflags 2.11.0", + "block2 0.6.2", + "bytemuck", + "cfg-if", + "cfg_aliases", + "glow", + "glutin_wgl_sys", + "gpu-allocator", + "gpu-descriptor", + "hashbrown 0.16.1", + "js-sys", + "khronos-egl", + "libc", + "libloading", + "log", + "naga", + "ndk-sys", + "objc2 0.6.4", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", + "objc2-quartz-core 0.3.2", + "once_cell", + "ordered-float", + "parking_lot", + "portable-atomic", + "portable-atomic-util", + "profiling", + "range-alloc", + "raw-window-handle", + "raw-window-metal", + "renderdoc-sys", + "smallvec", + "thiserror 2.0.18", + "wasm-bindgen", + "wayland-sys", + "web-sys", + "wgpu-naga-bridge", + "wgpu-types", + "windows", + "windows-core", +] + +[[package]] +name = "wgpu-naga-bridge" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4684f4410da0cf95a4cb63bb5edaac022461dedb6adf0b64d0d9b5f6890d51" +dependencies = [ + "naga", + "wgpu-types", +] + +[[package]] +name = "wgpu-types" +version = "29.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec2675540fb1a5cfa5ef122d3d5f390e2c75711a0b946410f2d6ac3a0f77d1f6" +dependencies = [ + "bitflags 2.11.0", + "bytemuck", + "js-sys", + "log", + "raw-window-handle", + "web-sys", +] + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[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" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[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-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[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 0.52.6", + "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-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[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_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[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_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[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_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[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_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[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_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winit" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" +dependencies = [ + "ahash", + "android-activity", + "atomic-waker", + "bitflags 2.11.0", + "block2 0.5.1", + "bytemuck", + "calloop 0.13.0", + "cfg_aliases", + "concurrent-queue", + "core-foundation 0.9.4", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit 0.2.2", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit 0.19.2", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "x-wing" +version = "0.1.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d0d5f4d1f26b9b9e7477af1d3bef960e1d1fb64edab7912fde472a8a8432e" +dependencies = [ + "kem", + "ml-kem", + "rand_core", + "sha3", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading", + "once_cell", + "rustix 1.1.4", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "x25519-dalek" +version = "3.0.0-pre.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d5d6ff67acd3945b933e592bfa7143db4fcbb2f871754b6b9fbd7847fc5aea" +dependencies = [ + "curve25519-dalek", + "rand_core", + "zeroize", +] + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.11.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "libc", + "ordered-stream", + "rustix 1.1.4", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow 0.7.15", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus-lockstep" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6998de05217a084b7578728a9443d04ea4cd80f2a0839b8d78770b76ccd45863" +dependencies = [ + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus-lockstep-macros" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "zbus-lockstep", + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" +dependencies = [ + "serde", + "winnow 0.7.15", + "zvariant", +] + +[[package]] +name = "zbus_xml" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "441a0064125265655bccc3a6af6bef56814d9277ac83fce48b1cd7e160b80eac" +dependencies = [ + "quick-xml 0.38.4", + "serde", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] + +[[package]] +name = "zvariant" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow 0.7.15", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn", + "winnow 0.7.15", +] diff --git a/useragent/rust/Cargo.toml b/useragent/rust/Cargo.toml index 4cbf5e2..15b7177 100644 --- a/useragent/rust/Cargo.toml +++ b/useragent/rust/Cargo.toml @@ -1,17 +1,17 @@ -[package] -name = "rust_lib_arbiter" -version = "0.1.0" -edition = "2021" - -[lib] -crate-type = ["cdylib", "staticlib"] - -[dependencies] -eframe = "0.34.1" -egui = "0.34.1" -flutter_rust_bridge = "=2.12.0" -arbiter-crypto = {path = "../../server/crates/arbiter-crypto"} -anyhow = "1.0.102" - -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(frb_expand)'] } +[package] +name = "rust_lib_arbiter" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "staticlib"] + +[dependencies] +eframe = "0.34.1" +egui = "0.34.1" +flutter_rust_bridge = "=2.12.0" +arbiter-crypto = {path = "../../server/crates/arbiter-crypto"} +anyhow = "1.0.102" + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(frb_expand)'] } diff --git a/useragent/rust/src/api/mod.rs b/useragent/rust/src/api/mod.rs index 0590ab0..544527a 100644 --- a/useragent/rust/src/api/mod.rs +++ b/useragent/rust/src/api/mod.rs @@ -1,38 +1,38 @@ -use anyhow::anyhow; -use arbiter_crypto::authn::{self, AuthChallenge, USERAGENT_CONTEXT}; -use flutter_rust_bridge::frb; - -#[frb(opaque)] -pub struct MldsaKey(authn::SigningKey); - -impl MldsaKey { - pub fn from_bytes(bytes: &[u8]) -> anyhow::Result { - let bytes: [u8; 32] = bytes - .try_into() - .map_err(|_| anyhow!("Invalid key length"))?; - Ok(Self(authn::SigningKey::from_seed(bytes))) - } - - pub fn to_bytes(&self) -> Vec { - self.0.to_seed().to_vec() - } - - pub fn sign(&self, message: &[u8]) -> anyhow::Result> { - Ok(self.0.sign_message(message, USERAGENT_CONTEXT)?.to_bytes()) - } - - pub fn generate() -> Self { - Self(authn::SigningKey::generate()) - } - - pub fn get_public_key(&self) -> Vec { - self.0.public_key().to_bytes().to_vec() - } -} - -pub fn format_challenge(random: Vec, timestamp: i64) -> Result, String> { - let challenge = AuthChallenge::from_parts(&random, timestamp) - .map_err(|_| "Invalid nonce length".to_string())?; - - Ok(challenge.format()) -} +use anyhow::anyhow; +use arbiter_crypto::authn::{self, AuthChallenge, USERAGENT_CONTEXT}; +use flutter_rust_bridge::frb; + +#[frb(opaque)] +pub struct MldsaKey(authn::SigningKey); + +impl MldsaKey { + pub fn from_bytes(bytes: &[u8]) -> anyhow::Result { + let bytes: [u8; 32] = bytes + .try_into() + .map_err(|_| anyhow!("Invalid key length"))?; + Ok(Self(authn::SigningKey::from_seed(bytes))) + } + + pub fn to_bytes(&self) -> Vec { + self.0.to_seed().to_vec() + } + + pub fn sign(&self, message: &[u8]) -> anyhow::Result> { + Ok(self.0.sign_message(message, USERAGENT_CONTEXT)?.to_bytes()) + } + + pub fn generate() -> Self { + Self(authn::SigningKey::generate()) + } + + pub fn get_public_key(&self) -> Vec { + self.0.public_key().to_bytes().to_vec() + } +} + +pub fn format_challenge(random: Vec, timestamp: i64) -> Result, String> { + let challenge = AuthChallenge::from_parts(&random, timestamp) + .map_err(|_| "Invalid nonce length".to_string())?; + + Ok(challenge.format()) +} diff --git a/useragent/rust/src/frb_generated.rs b/useragent/rust/src/frb_generated.rs index 46647d0..35f45d4 100644 --- a/useragent/rust/src/frb_generated.rs +++ b/useragent/rust/src/frb_generated.rs @@ -1,607 +1,607 @@ -// This file is automatically generated, so please do not edit it. -// @generated by `flutter_rust_bridge`@ 2.12.0. - -#![allow( - non_camel_case_types, - unused, - non_snake_case, - clippy::needless_return, - clippy::redundant_closure_call, - clippy::redundant_closure, - clippy::useless_conversion, - clippy::unit_arg, - clippy::unused_unit, - clippy::double_parens, - clippy::let_and_return, - clippy::too_many_arguments, - clippy::match_single_binding, - clippy::clone_on_copy, - clippy::let_unit_value, - clippy::deref_addrof, - clippy::explicit_auto_deref, - clippy::borrow_deref_ref, - clippy::uninlined_format_args, - clippy::needless_borrow -)] - -// Section: imports - -use crate::api::*; -use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; -use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; -use flutter_rust_bridge::{Handler, IntoIntoDart}; - -// Section: boilerplate - -flutter_rust_bridge::frb_generated_boilerplate!( - default_stream_sink_codec = SseCodec, - default_rust_opaque = RustOpaqueMoi, - default_rust_auto_opaque = RustAutoOpaqueMoi, -); -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1247923898; - -// Section: executor - -flutter_rust_bridge::frb_generated_default_handler!(); - -// Section: wire_funcs - -fn wire__crate__api__MldsaKey_from_bytes_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "MldsaKey_from_bytes", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_bytes = >::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let output_ok = crate::api::MldsaKey::from_bytes(&api_bytes)?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__api__MldsaKey_generate_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "MldsaKey_generate", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - deserializer.end(); - move |context| { - transform_result_sse::<_, ()>((move || { - let output_ok = Result::<_, ()>::Ok(crate::api::MldsaKey::generate())?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__MldsaKey_get_public_key_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "MldsaKey_get_public_key", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_that = , - >>::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, ()>((move || { - let mut api_that_guard = None; - let decode_indices_ = - flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ - flutter_rust_bridge::for_generated::LockableOrderInfo::new( - &api_that, 0, false, - ), - ]); - for i in decode_indices_ { - match i { - 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), - _ => unreachable!(), - } - } - let api_that_guard = api_that_guard.unwrap(); - let output_ok = Result::<_, ()>::Ok(crate::api::MldsaKey::get_public_key( - &*api_that_guard, - ))?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__MldsaKey_sign_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "MldsaKey_sign", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_that = , - >>::sse_decode(&mut deserializer); - let api_message = >::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( - (move || { - let mut api_that_guard = None; - let decode_indices_ = - flutter_rust_bridge::for_generated::lockable_compute_decode_order( - vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( - &api_that, 0, false, - )], - ); - for i in decode_indices_ { - match i { - 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), - _ => unreachable!(), - } - } - let api_that_guard = api_that_guard.unwrap(); - let output_ok = crate::api::MldsaKey::sign(&*api_that_guard, &api_message)?; - Ok(output_ok) - })(), - ) - } - }, - ) -} -fn wire__crate__api__MldsaKey_to_bytes_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "MldsaKey_to_bytes", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_that = , - >>::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, ()>((move || { - let mut api_that_guard = None; - let decode_indices_ = - flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ - flutter_rust_bridge::for_generated::LockableOrderInfo::new( - &api_that, 0, false, - ), - ]); - for i in decode_indices_ { - match i { - 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), - _ => unreachable!(), - } - } - let api_that_guard = api_that_guard.unwrap(); - let output_ok = - Result::<_, ()>::Ok(crate::api::MldsaKey::to_bytes(&*api_that_guard))?; - Ok(output_ok) - })()) - } - }, - ) -} -fn wire__crate__api__format_challenge_impl( - port_: flutter_rust_bridge::for_generated::MessagePort, - ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len_: i32, - data_len_: i32, -) { - FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( - flutter_rust_bridge::for_generated::TaskInfo { - debug_name: "format_challenge", - port: Some(port_), - mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, - }, - move || { - let message = unsafe { - flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( - ptr_, - rust_vec_len_, - data_len_, - ) - }; - let mut deserializer = - flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_random = >::sse_decode(&mut deserializer); - let api_timestamp = ::sse_decode(&mut deserializer); - deserializer.end(); - move |context| { - transform_result_sse::<_, String>((move || { - let output_ok = crate::api::format_challenge(api_random, api_timestamp)?; - Ok(output_ok) - })()) - } - }, - ) -} - -// Section: related_funcs - -flutter_rust_bridge::frb_generated_moi_arc_impl_value!( - flutter_rust_bridge::for_generated::RustAutoOpaqueInner -); - -// Section: dart2rust - -impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = ::sse_decode(deserializer); - return flutter_rust_bridge::for_generated::anyhow::anyhow!("{}", inner); - } -} - -impl SseDecode for MldsaKey { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = , - >>::sse_decode(deserializer); - return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); - } -} - -impl SseDecode - for RustOpaqueMoi> -{ - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = ::sse_decode(deserializer); - return decode_rust_opaque_moi(inner); - } -} - -impl SseDecode for String { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = >::sse_decode(deserializer); - return String::from_utf8(inner).unwrap(); - } -} - -impl SseDecode for i64 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_i64::().unwrap() - } -} - -impl SseDecode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut len_ = ::sse_decode(deserializer); - let mut ans_ = Vec::with_capacity(len_ as usize); - for idx_ in 0..len_ { - ans_.push(::sse_decode(deserializer)); - } - return ans_; - } -} - -impl SseDecode for u8 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_u8().unwrap() - } -} - -impl SseDecode for () { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {} -} - -impl SseDecode for usize { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_u64::().unwrap() as _ - } -} - -impl SseDecode for i32 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_i32::().unwrap() - } -} - -impl SseDecode for bool { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - deserializer.cursor.read_u8().unwrap() != 0 - } -} - -fn pde_ffi_dispatcher_primary_impl( - func_id: i32, - port: flutter_rust_bridge::for_generated::MessagePort, - ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len: i32, - data_len: i32, -) { - // Codec=Pde (Serialization + dispatch), see doc to use other codecs - match func_id { - 1 => wire__crate__api__MldsaKey_from_bytes_impl(port, ptr, rust_vec_len, data_len), - 2 => wire__crate__api__MldsaKey_generate_impl(port, ptr, rust_vec_len, data_len), - 3 => wire__crate__api__MldsaKey_get_public_key_impl(port, ptr, rust_vec_len, data_len), - 4 => wire__crate__api__MldsaKey_sign_impl(port, ptr, rust_vec_len, data_len), - 5 => wire__crate__api__MldsaKey_to_bytes_impl(port, ptr, rust_vec_len, data_len), - 6 => wire__crate__api__format_challenge_impl(port, ptr, rust_vec_len, data_len), - _ => unreachable!(), - } -} - -fn pde_ffi_dispatcher_sync_impl( - func_id: i32, - ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, - rust_vec_len: i32, - data_len: i32, -) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { - // Codec=Pde (Serialization + dispatch), see doc to use other codecs - match func_id { - _ => unreachable!(), - } -} - -// Section: rust2dart - -// Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) - .into_dart() - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} - -impl flutter_rust_bridge::IntoIntoDart> for MldsaKey { - fn into_into_dart(self) -> FrbWrapper { - self.into() - } -} - -impl SseEncode for flutter_rust_bridge::for_generated::anyhow::Error { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(format!("{:?}", self), serializer); - } -} - -impl SseEncode for MldsaKey { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - >>::sse_encode(flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self), serializer); - } -} - -impl SseEncode - for RustOpaqueMoi> -{ - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - let (ptr, size) = self.sse_encode_raw(); - ::sse_encode(ptr, serializer); - ::sse_encode(size, serializer); - } -} - -impl SseEncode for String { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - >::sse_encode(self.into_bytes(), serializer); - } -} - -impl SseEncode for i64 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer.cursor.write_i64::(self).unwrap(); - } -} - -impl SseEncode for Vec { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode(self.len() as _, serializer); - for item in self { - ::sse_encode(item, serializer); - } - } -} - -impl SseEncode for u8 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer.cursor.write_u8(self).unwrap(); - } -} - -impl SseEncode for () { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {} -} - -impl SseEncode for usize { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer - .cursor - .write_u64::(self as _) - .unwrap(); - } -} - -impl SseEncode for i32 { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer.cursor.write_i32::(self).unwrap(); - } -} - -impl SseEncode for bool { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - serializer.cursor.write_u8(self as _).unwrap(); - } -} - -#[cfg(not(target_family = "wasm"))] -mod io { - // This file is automatically generated, so please do not edit it. - // @generated by `flutter_rust_bridge`@ 2.12.0. - - // Section: imports - - use super::*; - use crate::api::*; - use flutter_rust_bridge::for_generated::byteorder::{ - NativeEndian, ReadBytesExt, WriteBytesExt, - }; - use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; - use flutter_rust_bridge::{Handler, IntoIntoDart}; - - // Section: boilerplate - - flutter_rust_bridge::frb_generated_boilerplate_io!(); - - #[unsafe(no_mangle)] - pub extern "C" fn frbgen_arbiter_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::increment_strong_count(ptr as _); - } - - #[unsafe(no_mangle)] - pub extern "C" fn frbgen_arbiter_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::decrement_strong_count(ptr as _); - } -} -#[cfg(not(target_family = "wasm"))] -pub use io::*; - -/// cbindgen:ignore -#[cfg(target_family = "wasm")] -mod web { - // This file is automatically generated, so please do not edit it. - // @generated by `flutter_rust_bridge`@ 2.12.0. - - // Section: imports - - use super::*; - use crate::api::*; - use flutter_rust_bridge::for_generated::byteorder::{ - NativeEndian, ReadBytesExt, WriteBytesExt, - }; - use flutter_rust_bridge::for_generated::wasm_bindgen; - use flutter_rust_bridge::for_generated::wasm_bindgen::prelude::*; - use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; - use flutter_rust_bridge::{Handler, IntoIntoDart}; - - // Section: boilerplate - - flutter_rust_bridge::frb_generated_boilerplate_web!(); - - #[wasm_bindgen] - pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::increment_strong_count(ptr as _); - } - - #[wasm_bindgen] - pub fn rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( - ptr: *const std::ffi::c_void, - ) { - MoiArc::>::decrement_strong_count(ptr as _); - } -} -#[cfg(target_family = "wasm")] -pub use web::*; +// This file is automatically generated, so please do not edit it. +// @generated by `flutter_rust_bridge`@ 2.12.0. + +#![allow( + non_camel_case_types, + unused, + non_snake_case, + clippy::needless_return, + clippy::redundant_closure_call, + clippy::redundant_closure, + clippy::useless_conversion, + clippy::unit_arg, + clippy::unused_unit, + clippy::double_parens, + clippy::let_and_return, + clippy::too_many_arguments, + clippy::match_single_binding, + clippy::clone_on_copy, + clippy::let_unit_value, + clippy::deref_addrof, + clippy::explicit_auto_deref, + clippy::borrow_deref_ref, + clippy::uninlined_format_args, + clippy::needless_borrow +)] + +// Section: imports + +use crate::api::*; +use flutter_rust_bridge::for_generated::byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; +use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; +use flutter_rust_bridge::{Handler, IntoIntoDart}; + +// Section: boilerplate + +flutter_rust_bridge::frb_generated_boilerplate!( + default_stream_sink_codec = SseCodec, + default_rust_opaque = RustOpaqueMoi, + default_rust_auto_opaque = RustAutoOpaqueMoi, +); +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.12.0"; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1247923898; + +// Section: executor + +flutter_rust_bridge::frb_generated_default_handler!(); + +// Section: wire_funcs + +fn wire__crate__api__MldsaKey_from_bytes_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "MldsaKey_from_bytes", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_bytes = >::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::MldsaKey::from_bytes(&api_bytes)?; + Ok(output_ok) + })(), + ) + } + }, + ) +} +fn wire__crate__api__MldsaKey_generate_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "MldsaKey_generate", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let output_ok = Result::<_, ()>::Ok(crate::api::MldsaKey::generate())?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__MldsaKey_get_public_key_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "MldsaKey_get_public_key", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = Result::<_, ()>::Ok(crate::api::MldsaKey::get_public_key( + &*api_that_guard, + ))?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__MldsaKey_sign_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "MldsaKey_sign", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + let api_message = >::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order( + vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + )], + ); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = crate::api::MldsaKey::sign(&*api_that_guard, &api_message)?; + Ok(output_ok) + })(), + ) + } + }, + ) +} +fn wire__crate__api__MldsaKey_to_bytes_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "MldsaKey_to_bytes", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_that = , + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, ()>((move || { + let mut api_that_guard = None; + let decode_indices_ = + flutter_rust_bridge::for_generated::lockable_compute_decode_order(vec![ + flutter_rust_bridge::for_generated::LockableOrderInfo::new( + &api_that, 0, false, + ), + ]); + for i in decode_indices_ { + match i { + 0 => api_that_guard = Some(api_that.lockable_decode_sync_ref()), + _ => unreachable!(), + } + } + let api_that_guard = api_that_guard.unwrap(); + let output_ok = + Result::<_, ()>::Ok(crate::api::MldsaKey::to_bytes(&*api_that_guard))?; + Ok(output_ok) + })()) + } + }, + ) +} +fn wire__crate__api__format_challenge_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "format_challenge", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_random = >::sse_decode(&mut deserializer); + let api_timestamp = ::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse::<_, String>((move || { + let output_ok = crate::api::format_challenge(api_random, api_timestamp)?; + Ok(output_ok) + })()) + } + }, + ) +} + +// Section: related_funcs + +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::RustAutoOpaqueInner +); + +// Section: dart2rust + +impl SseDecode for flutter_rust_bridge::for_generated::anyhow::Error { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return flutter_rust_bridge::for_generated::anyhow::anyhow!("{}", inner); + } +} + +impl SseDecode for MldsaKey { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = , + >>::sse_decode(deserializer); + return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); + } +} + +impl SseDecode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return decode_rust_opaque_moi(inner); + } +} + +impl SseDecode for String { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = >::sse_decode(deserializer); + return String::from_utf8(inner).unwrap(); + } +} + +impl SseDecode for i64 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_i64::().unwrap() + } +} + +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = Vec::with_capacity(len_ as usize); + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); + } + return ans_; + } +} + +impl SseDecode for u8 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u8().unwrap() + } +} + +impl SseDecode for () { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {} +} + +impl SseDecode for usize { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u64::().unwrap() as _ + } +} + +impl SseDecode for i32 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_i32::().unwrap() + } +} + +impl SseDecode for bool { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + deserializer.cursor.read_u8().unwrap() != 0 + } +} + +fn pde_ffi_dispatcher_primary_impl( + func_id: i32, + port: flutter_rust_bridge::for_generated::MessagePort, + ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len: i32, + data_len: i32, +) { + // Codec=Pde (Serialization + dispatch), see doc to use other codecs + match func_id { + 1 => wire__crate__api__MldsaKey_from_bytes_impl(port, ptr, rust_vec_len, data_len), + 2 => wire__crate__api__MldsaKey_generate_impl(port, ptr, rust_vec_len, data_len), + 3 => wire__crate__api__MldsaKey_get_public_key_impl(port, ptr, rust_vec_len, data_len), + 4 => wire__crate__api__MldsaKey_sign_impl(port, ptr, rust_vec_len, data_len), + 5 => wire__crate__api__MldsaKey_to_bytes_impl(port, ptr, rust_vec_len, data_len), + 6 => wire__crate__api__format_challenge_impl(port, ptr, rust_vec_len, data_len), + _ => unreachable!(), + } +} + +fn pde_ffi_dispatcher_sync_impl( + func_id: i32, + ptr: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len: i32, + data_len: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + // Codec=Pde (Serialization + dispatch), see doc to use other codecs + match func_id { + _ => unreachable!(), + } +} + +// Section: rust2dart + +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for MldsaKey { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + +impl SseEncode for flutter_rust_bridge::for_generated::anyhow::Error { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(format!("{:?}", self), serializer); + } +} + +impl SseEncode for MldsaKey { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >>::sse_encode(flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self), serializer); + } +} + +impl SseEncode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + let (ptr, size) = self.sse_encode_raw(); + ::sse_encode(ptr, serializer); + ::sse_encode(size, serializer); + } +} + +impl SseEncode for String { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >::sse_encode(self.into_bytes(), serializer); + } +} + +impl SseEncode for i64 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_i64::(self).unwrap(); + } +} + +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + +impl SseEncode for u8 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_u8(self).unwrap(); + } +} + +impl SseEncode for () { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {} +} + +impl SseEncode for usize { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer + .cursor + .write_u64::(self as _) + .unwrap(); + } +} + +impl SseEncode for i32 { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_i32::(self).unwrap(); + } +} + +impl SseEncode for bool { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + serializer.cursor.write_u8(self as _).unwrap(); + } +} + +#[cfg(not(target_family = "wasm"))] +mod io { + // This file is automatically generated, so please do not edit it. + // @generated by `flutter_rust_bridge`@ 2.12.0. + + // Section: imports + + use super::*; + use crate::api::*; + use flutter_rust_bridge::for_generated::byteorder::{ + NativeEndian, ReadBytesExt, WriteBytesExt, + }; + use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; + use flutter_rust_bridge::{Handler, IntoIntoDart}; + + // Section: boilerplate + + flutter_rust_bridge::frb_generated_boilerplate_io!(); + + #[unsafe(no_mangle)] + pub extern "C" fn frbgen_arbiter_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[unsafe(no_mangle)] + pub extern "C" fn frbgen_arbiter_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } +} +#[cfg(not(target_family = "wasm"))] +pub use io::*; + +/// cbindgen:ignore +#[cfg(target_family = "wasm")] +mod web { + // This file is automatically generated, so please do not edit it. + // @generated by `flutter_rust_bridge`@ 2.12.0. + + // Section: imports + + use super::*; + use crate::api::*; + use flutter_rust_bridge::for_generated::byteorder::{ + NativeEndian, ReadBytesExt, WriteBytesExt, + }; + use flutter_rust_bridge::for_generated::wasm_bindgen; + use flutter_rust_bridge::for_generated::wasm_bindgen::prelude::*; + use flutter_rust_bridge::for_generated::{transform_result_dco, Lifetimeable, Lockable}; + use flutter_rust_bridge::{Handler, IntoIntoDart}; + + // Section: boilerplate + + flutter_rust_bridge::frb_generated_boilerplate_web!(); + + #[wasm_bindgen] + pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[wasm_bindgen] + pub fn rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerMldsaKey( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } +} +#[cfg(target_family = "wasm")] +pub use web::*; diff --git a/useragent/rust/src/lib.rs b/useragent/rust/src/lib.rs index cbb071f..6a595ed 100644 --- a/useragent/rust/src/lib.rs +++ b/useragent/rust/src/lib.rs @@ -1,2 +1,2 @@ -pub mod api; -mod frb_generated; +pub mod api; +mod frb_generated; diff --git a/useragent/rust_builder/.gitignore b/useragent/rust_builder/.gitignore index ac5aa98..1ba0790 100644 --- a/useragent/rust_builder/.gitignore +++ b/useragent/rust_builder/.gitignore @@ -1,29 +1,29 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -build/ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +build/ diff --git a/useragent/rust_builder/android/.gitignore b/useragent/rust_builder/android/.gitignore index 161bdcd..a2b1dea 100644 --- a/useragent/rust_builder/android/.gitignore +++ b/useragent/rust_builder/android/.gitignore @@ -1,9 +1,9 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures -.cxx +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.cxx diff --git a/useragent/rust_builder/android/build.gradle b/useragent/rust_builder/android/build.gradle index 222ff73..adda3f3 100644 --- a/useragent/rust_builder/android/build.gradle +++ b/useragent/rust_builder/android/build.gradle @@ -1,56 +1,56 @@ -// The Android Gradle Plugin builds the native code with the Android NDK. - -group 'com.flutter_rust_bridge.rust_lib_arbiter' -version '1.0' - -buildscript { - repositories { - google() - mavenCentral() - } - - dependencies { - // The Android Gradle Plugin knows how to build native code with the NDK. - classpath 'com.android.tools.build:gradle:7.3.0' - } -} - -rootProject.allprojects { - repositories { - google() - mavenCentral() - } -} - -apply plugin: 'com.android.library' - -android { - if (project.android.hasProperty("namespace")) { - namespace 'com.flutter_rust_bridge.rust_lib_arbiter' - } - - // Bumping the plugin compileSdkVersion requires all clients of this plugin - // to bump the version in their app. - compileSdkVersion 33 - - // Use the NDK version - // declared in /android/app/build.gradle file of the Flutter project. - // Replace it with a version number if this plugin requires a specfic NDK version. - // (e.g. ndkVersion "23.1.7779620") - ndkVersion android.ndkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - defaultConfig { - minSdkVersion 19 - } -} - -apply from: "../cargokit/gradle/plugin.gradle" -cargokit { - manifestDir = "../../rust" - libname = "rust_lib_arbiter" -} +// The Android Gradle Plugin builds the native code with the Android NDK. + +group 'com.flutter_rust_bridge.rust_lib_arbiter' +version '1.0' + +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + // The Android Gradle Plugin knows how to build native code with the NDK. + classpath 'com.android.tools.build:gradle:7.3.0' + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' + +android { + if (project.android.hasProperty("namespace")) { + namespace 'com.flutter_rust_bridge.rust_lib_arbiter' + } + + // Bumping the plugin compileSdkVersion requires all clients of this plugin + // to bump the version in their app. + compileSdkVersion 33 + + // Use the NDK version + // declared in /android/app/build.gradle file of the Flutter project. + // Replace it with a version number if this plugin requires a specfic NDK version. + // (e.g. ndkVersion "23.1.7779620") + ndkVersion android.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + defaultConfig { + minSdkVersion 19 + } +} + +apply from: "../cargokit/gradle/plugin.gradle" +cargokit { + manifestDir = "../../rust" + libname = "rust_lib_arbiter" +} diff --git a/useragent/rust_builder/android/settings.gradle b/useragent/rust_builder/android/settings.gradle index cb25a60..d9de2b4 100644 --- a/useragent/rust_builder/android/settings.gradle +++ b/useragent/rust_builder/android/settings.gradle @@ -1 +1 @@ -rootProject.name = 'rust_lib_arbiter' +rootProject.name = 'rust_lib_arbiter' diff --git a/useragent/rust_builder/android/src/main/AndroidManifest.xml b/useragent/rust_builder/android/src/main/AndroidManifest.xml index d22bc1b..0dd7891 100644 --- a/useragent/rust_builder/android/src/main/AndroidManifest.xml +++ b/useragent/rust_builder/android/src/main/AndroidManifest.xml @@ -1,3 +1,3 @@ - - + + diff --git a/useragent/rust_builder/cargokit/.gitignore b/useragent/rust_builder/cargokit/.gitignore index cf7bb86..9c21030 100644 --- a/useragent/rust_builder/cargokit/.gitignore +++ b/useragent/rust_builder/cargokit/.gitignore @@ -1,4 +1,4 @@ -target -.dart_tool -*.iml -!pubspec.lock +target +.dart_tool +*.iml +!pubspec.lock diff --git a/useragent/rust_builder/cargokit/LICENSE b/useragent/rust_builder/cargokit/LICENSE index d33a5fe..e015761 100644 --- a/useragent/rust_builder/cargokit/LICENSE +++ b/useragent/rust_builder/cargokit/LICENSE @@ -1,42 +1,42 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -Copyright 2022 Matej Knopp - -================================================================================ - -MIT LICENSE - -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. - -================================================================================ - -APACHE LICENSE, VERSION 2.0 - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +Copyright 2022 Matej Knopp + +================================================================================ + +MIT LICENSE + +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. + +================================================================================ + +APACHE LICENSE, VERSION 2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + diff --git a/useragent/rust_builder/cargokit/README b/useragent/rust_builder/cargokit/README index 398474d..1e0cae3 100644 --- a/useragent/rust_builder/cargokit/README +++ b/useragent/rust_builder/cargokit/README @@ -1,11 +1,11 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -Experimental repository to provide glue for seamlessly integrating cargo build -with flutter plugins and packages. - -See https://matejknopp.com/post/flutter_plugin_in_rust_with_no_prebuilt_binaries/ -for a tutorial on how to use Cargokit. - -Example plugin available at https://github.com/irondash/hello_rust_ffi_plugin. - +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +Experimental repository to provide glue for seamlessly integrating cargo build +with flutter plugins and packages. + +See https://matejknopp.com/post/flutter_plugin_in_rust_with_no_prebuilt_binaries/ +for a tutorial on how to use Cargokit. + +Example plugin available at https://github.com/irondash/hello_rust_ffi_plugin. + diff --git a/useragent/rust_builder/cargokit/build_pod.sh b/useragent/rust_builder/cargokit/build_pod.sh index ed0e0d9..c2f1721 100755 --- a/useragent/rust_builder/cargokit/build_pod.sh +++ b/useragent/rust_builder/cargokit/build_pod.sh @@ -1,58 +1,58 @@ -#!/bin/sh -set -e - -BASEDIR=$(dirname "$0") - -# Workaround for https://github.com/dart-lang/pub/issues/4010 -BASEDIR=$(cd "$BASEDIR" ; pwd -P) - -# Remove XCode SDK from path. Otherwise this breaks tool compilation when building iOS project -NEW_PATH=`echo $PATH | tr ":" "\n" | grep -v "Contents/Developer/" | tr "\n" ":"` - -export PATH=${NEW_PATH%?} # remove trailing : - -env - -# Platform name (macosx, iphoneos, iphonesimulator) -export CARGOKIT_DARWIN_PLATFORM_NAME=$PLATFORM_NAME - -# Arctive architectures (arm64, armv7, x86_64), space separated. -export CARGOKIT_DARWIN_ARCHS=$ARCHS - -# Current build configuration (Debug, Release) -export CARGOKIT_CONFIGURATION=$CONFIGURATION - -# Path to directory containing Cargo.toml. -export CARGOKIT_MANIFEST_DIR=$PODS_TARGET_SRCROOT/$1 - -# Temporary directory for build artifacts. -export CARGOKIT_TARGET_TEMP_DIR=$TARGET_TEMP_DIR - -# Output directory for final artifacts. -export CARGOKIT_OUTPUT_DIR=$PODS_CONFIGURATION_BUILD_DIR/$PRODUCT_NAME - -# Directory to store built tool artifacts. -export CARGOKIT_TOOL_TEMP_DIR=$TARGET_TEMP_DIR/build_tool - -# Directory inside root project. Not necessarily the top level directory of root project. -export CARGOKIT_ROOT_PROJECT_DIR=$SRCROOT - -FLUTTER_EXPORT_BUILD_ENVIRONMENT=( - "$PODS_ROOT/../Flutter/ephemeral/flutter_export_environment.sh" # macOS - "$PODS_ROOT/../Flutter/flutter_export_environment.sh" # iOS -) - -for path in "${FLUTTER_EXPORT_BUILD_ENVIRONMENT[@]}" -do - if [[ -f "$path" ]]; then - source "$path" - fi -done - -sh "$BASEDIR/run_build_tool.sh" build-pod "$@" - -# Make a symlink from built framework to phony file, which will be used as input to -# build script. This should force rebuild (podspec currently doesn't support alwaysOutOfDate -# attribute on custom build phase) -ln -fs "$OBJROOT/XCBuildData/build.db" "${BUILT_PRODUCTS_DIR}/cargokit_phony" -ln -fs "${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}" "${BUILT_PRODUCTS_DIR}/cargokit_phony_out" +#!/bin/sh +set -e + +BASEDIR=$(dirname "$0") + +# Workaround for https://github.com/dart-lang/pub/issues/4010 +BASEDIR=$(cd "$BASEDIR" ; pwd -P) + +# Remove XCode SDK from path. Otherwise this breaks tool compilation when building iOS project +NEW_PATH=`echo $PATH | tr ":" "\n" | grep -v "Contents/Developer/" | tr "\n" ":"` + +export PATH=${NEW_PATH%?} # remove trailing : + +env + +# Platform name (macosx, iphoneos, iphonesimulator) +export CARGOKIT_DARWIN_PLATFORM_NAME=$PLATFORM_NAME + +# Arctive architectures (arm64, armv7, x86_64), space separated. +export CARGOKIT_DARWIN_ARCHS=$ARCHS + +# Current build configuration (Debug, Release) +export CARGOKIT_CONFIGURATION=$CONFIGURATION + +# Path to directory containing Cargo.toml. +export CARGOKIT_MANIFEST_DIR=$PODS_TARGET_SRCROOT/$1 + +# Temporary directory for build artifacts. +export CARGOKIT_TARGET_TEMP_DIR=$TARGET_TEMP_DIR + +# Output directory for final artifacts. +export CARGOKIT_OUTPUT_DIR=$PODS_CONFIGURATION_BUILD_DIR/$PRODUCT_NAME + +# Directory to store built tool artifacts. +export CARGOKIT_TOOL_TEMP_DIR=$TARGET_TEMP_DIR/build_tool + +# Directory inside root project. Not necessarily the top level directory of root project. +export CARGOKIT_ROOT_PROJECT_DIR=$SRCROOT + +FLUTTER_EXPORT_BUILD_ENVIRONMENT=( + "$PODS_ROOT/../Flutter/ephemeral/flutter_export_environment.sh" # macOS + "$PODS_ROOT/../Flutter/flutter_export_environment.sh" # iOS +) + +for path in "${FLUTTER_EXPORT_BUILD_ENVIRONMENT[@]}" +do + if [[ -f "$path" ]]; then + source "$path" + fi +done + +sh "$BASEDIR/run_build_tool.sh" build-pod "$@" + +# Make a symlink from built framework to phony file, which will be used as input to +# build script. This should force rebuild (podspec currently doesn't support alwaysOutOfDate +# attribute on custom build phase) +ln -fs "$OBJROOT/XCBuildData/build.db" "${BUILT_PRODUCTS_DIR}/cargokit_phony" +ln -fs "${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}" "${BUILT_PRODUCTS_DIR}/cargokit_phony_out" diff --git a/useragent/rust_builder/cargokit/build_tool/README.md b/useragent/rust_builder/cargokit/build_tool/README.md index a878c27..0969319 100644 --- a/useragent/rust_builder/cargokit/build_tool/README.md +++ b/useragent/rust_builder/cargokit/build_tool/README.md @@ -1,5 +1,5 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -A sample command-line application with an entrypoint in `bin/`, library code -in `lib/`, and example unit test in `test/`. +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +A sample command-line application with an entrypoint in `bin/`, library code +in `lib/`, and example unit test in `test/`. diff --git a/useragent/rust_builder/cargokit/build_tool/analysis_options.yaml b/useragent/rust_builder/cargokit/build_tool/analysis_options.yaml index 0e16a8b..e784cc3 100644 --- a/useragent/rust_builder/cargokit/build_tool/analysis_options.yaml +++ b/useragent/rust_builder/cargokit/build_tool/analysis_options.yaml @@ -1,34 +1,34 @@ -# This is copied from Cargokit (which is the official way to use it currently) -# Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -# This file configures the static analysis results for your project (errors, -# warnings, and lints). -# -# This enables the 'recommended' set of lints from `package:lints`. -# This set helps identify many issues that may lead to problems when running -# or consuming Dart code, and enforces writing Dart using a single, idiomatic -# style and format. -# -# If you want a smaller set of lints you can change this to specify -# 'package:lints/core.yaml'. These are just the most critical lints -# (the recommended set includes the core lints). -# The core lints are also what is used by pub.dev for scoring packages. - -include: package:lints/recommended.yaml - -# Uncomment the following section to specify additional rules. - -linter: - rules: - - prefer_relative_imports - - directives_ordering - -# analyzer: -# exclude: -# - path/to/excluded/files/** - -# For more information about the core and recommended set of lints, see -# https://dart.dev/go/core-lints - -# For additional information about configuring this file, see -# https://dart.dev/guides/language/analysis-options +# This is copied from Cargokit (which is the official way to use it currently) +# Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +# This file configures the static analysis results for your project (errors, +# warnings, and lints). +# +# This enables the 'recommended' set of lints from `package:lints`. +# This set helps identify many issues that may lead to problems when running +# or consuming Dart code, and enforces writing Dart using a single, idiomatic +# style and format. +# +# If you want a smaller set of lints you can change this to specify +# 'package:lints/core.yaml'. These are just the most critical lints +# (the recommended set includes the core lints). +# The core lints are also what is used by pub.dev for scoring packages. + +include: package:lints/recommended.yaml + +# Uncomment the following section to specify additional rules. + +linter: + rules: + - prefer_relative_imports + - directives_ordering + +# analyzer: +# exclude: +# - path/to/excluded/files/** + +# For more information about the core and recommended set of lints, see +# https://dart.dev/go/core-lints + +# For additional information about configuring this file, see +# https://dart.dev/guides/language/analysis-options diff --git a/useragent/rust_builder/cargokit/build_tool/bin/build_tool.dart b/useragent/rust_builder/cargokit/build_tool/bin/build_tool.dart index 268eb52..cdc8e6a 100644 --- a/useragent/rust_builder/cargokit/build_tool/bin/build_tool.dart +++ b/useragent/rust_builder/cargokit/build_tool/bin/build_tool.dart @@ -1,8 +1,8 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'package:build_tool/build_tool.dart' as build_tool; - -void main(List arguments) { - build_tool.runMain(arguments); -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'package:build_tool/build_tool.dart' as build_tool; + +void main(List arguments) { + build_tool.runMain(arguments); +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/build_tool.dart b/useragent/rust_builder/cargokit/build_tool/lib/build_tool.dart index 7c1bb75..8520b83 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/build_tool.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/build_tool.dart @@ -1,8 +1,8 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'src/build_tool.dart' as build_tool; - -Future runMain(List args) async { - return build_tool.runMain(args); -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'src/build_tool.dart' as build_tool; + +Future runMain(List args) async { + return build_tool.runMain(args); +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/android_environment.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/android_environment.dart index 15fc9ee..082e4a2 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/android_environment.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/android_environment.dart @@ -1,195 +1,195 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; -import 'dart:isolate'; -import 'dart:math' as math; - -import 'package:collection/collection.dart'; -import 'package:path/path.dart' as path; -import 'package:version/version.dart'; - -import 'target.dart'; -import 'util.dart'; - -class AndroidEnvironment { - AndroidEnvironment({ - required this.sdkPath, - required this.ndkVersion, - required this.minSdkVersion, - required this.targetTempDir, - required this.target, - }); - - static void clangLinkerWrapper(List args) { - final clang = Platform.environment['_CARGOKIT_NDK_LINK_CLANG']; - if (clang == null) { - throw Exception( - "cargo-ndk rustc linker: didn't find _CARGOKIT_NDK_LINK_CLANG env var"); - } - final target = Platform.environment['_CARGOKIT_NDK_LINK_TARGET']; - if (target == null) { - throw Exception( - "cargo-ndk rustc linker: didn't find _CARGOKIT_NDK_LINK_TARGET env var"); - } - - runCommand(clang, [ - target, - ...args, - ]); - } - - /// Full path to Android SDK. - final String sdkPath; - - /// Full version of Android NDK. - final String ndkVersion; - - /// Minimum supported SDK version. - final int minSdkVersion; - - /// Target directory for build artifacts. - final String targetTempDir; - - /// Target being built. - final Target target; - - bool ndkIsInstalled() { - final ndkPath = path.join(sdkPath, 'ndk', ndkVersion); - final ndkPackageXml = File(path.join(ndkPath, 'package.xml')); - return ndkPackageXml.existsSync(); - } - - void installNdk({ - required String javaHome, - }) { - final sdkManagerExtension = Platform.isWindows ? '.bat' : ''; - final sdkManager = path.join( - sdkPath, - 'cmdline-tools', - 'latest', - 'bin', - 'sdkmanager$sdkManagerExtension', - ); - - log.info('Installing NDK $ndkVersion'); - runCommand(sdkManager, [ - '--install', - 'ndk;$ndkVersion', - ], environment: { - 'JAVA_HOME': javaHome, - }); - } - - Future> buildEnvironment() async { - final hostArch = Platform.isMacOS - ? "darwin-x86_64" - : (Platform.isLinux ? "linux-x86_64" : "windows-x86_64"); - - final ndkPath = path.join(sdkPath, 'ndk', ndkVersion); - final toolchainPath = path.join( - ndkPath, - 'toolchains', - 'llvm', - 'prebuilt', - hostArch, - 'bin', - ); - - final minSdkVersion = - math.max(target.androidMinSdkVersion!, this.minSdkVersion); - - final exe = Platform.isWindows ? '.exe' : ''; - - final arKey = 'AR_${target.rust}'; - final arValue = ['${target.rust}-ar', 'llvm-ar', 'llvm-ar.exe'] - .map((e) => path.join(toolchainPath, e)) - .firstWhereOrNull((element) => File(element).existsSync()); - if (arValue == null) { - throw Exception('Failed to find ar for $target in $toolchainPath'); - } - - final targetArg = '--target=${target.rust}$minSdkVersion'; - - final ccKey = 'CC_${target.rust}'; - final ccValue = path.join(toolchainPath, 'clang$exe'); - final cfFlagsKey = 'CFLAGS_${target.rust}'; - final cFlagsValue = targetArg; - - final cxxKey = 'CXX_${target.rust}'; - final cxxValue = path.join(toolchainPath, 'clang++$exe'); - final cxxFlagsKey = 'CXXFLAGS_${target.rust}'; - final cxxFlagsValue = targetArg; - - final linkerKey = - 'cargo_target_${target.rust.replaceAll('-', '_')}_linker'.toUpperCase(); - - final ranlibKey = 'RANLIB_${target.rust}'; - final ranlibValue = path.join(toolchainPath, 'llvm-ranlib$exe'); - - final ndkVersionParsed = Version.parse(ndkVersion); - final rustFlagsKey = 'CARGO_ENCODED_RUSTFLAGS'; - final rustFlagsValue = _libGccWorkaround(targetTempDir, ndkVersionParsed); - - final runRustTool = - Platform.isWindows ? 'run_build_tool.cmd' : 'run_build_tool.sh'; - - final packagePath = (await Isolate.resolvePackageUri( - Uri.parse('package:build_tool/buildtool.dart')))! - .toFilePath(); - final selfPath = path.canonicalize(path.join( - packagePath, - '..', - '..', - '..', - runRustTool, - )); - - // Make sure that run_build_tool is working properly even initially launched directly - // through dart run. - final toolTempDir = - Platform.environment['CARGOKIT_TOOL_TEMP_DIR'] ?? targetTempDir; - - return { - arKey: arValue, - ccKey: ccValue, - cfFlagsKey: cFlagsValue, - cxxKey: cxxValue, - cxxFlagsKey: cxxFlagsValue, - ranlibKey: ranlibValue, - rustFlagsKey: rustFlagsValue, - linkerKey: selfPath, - // Recognized by main() so we know when we're acting as a wrapper - '_CARGOKIT_NDK_LINK_TARGET': targetArg, - '_CARGOKIT_NDK_LINK_CLANG': ccValue, - 'CARGOKIT_TOOL_TEMP_DIR': toolTempDir, - }; - } - - // Workaround for libgcc missing in NDK23, inspired by cargo-ndk - String _libGccWorkaround(String buildDir, Version ndkVersion) { - final workaroundDir = path.join( - buildDir, - 'cargokit', - 'libgcc_workaround', - '${ndkVersion.major}', - ); - Directory(workaroundDir).createSync(recursive: true); - if (ndkVersion.major >= 23) { - File(path.join(workaroundDir, 'libgcc.a')) - .writeAsStringSync('INPUT(-lunwind)'); - } else { - // Other way around, untested, forward libgcc.a from libunwind once Rust - // gets updated for NDK23+. - File(path.join(workaroundDir, 'libunwind.a')) - .writeAsStringSync('INPUT(-lgcc)'); - } - - var rustFlags = Platform.environment['CARGO_ENCODED_RUSTFLAGS'] ?? ''; - if (rustFlags.isNotEmpty) { - rustFlags = '$rustFlags\x1f'; - } - rustFlags = '$rustFlags-L\x1f$workaroundDir'; - return rustFlags; - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; +import 'dart:isolate'; +import 'dart:math' as math; + +import 'package:collection/collection.dart'; +import 'package:path/path.dart' as path; +import 'package:version/version.dart'; + +import 'target.dart'; +import 'util.dart'; + +class AndroidEnvironment { + AndroidEnvironment({ + required this.sdkPath, + required this.ndkVersion, + required this.minSdkVersion, + required this.targetTempDir, + required this.target, + }); + + static void clangLinkerWrapper(List args) { + final clang = Platform.environment['_CARGOKIT_NDK_LINK_CLANG']; + if (clang == null) { + throw Exception( + "cargo-ndk rustc linker: didn't find _CARGOKIT_NDK_LINK_CLANG env var"); + } + final target = Platform.environment['_CARGOKIT_NDK_LINK_TARGET']; + if (target == null) { + throw Exception( + "cargo-ndk rustc linker: didn't find _CARGOKIT_NDK_LINK_TARGET env var"); + } + + runCommand(clang, [ + target, + ...args, + ]); + } + + /// Full path to Android SDK. + final String sdkPath; + + /// Full version of Android NDK. + final String ndkVersion; + + /// Minimum supported SDK version. + final int minSdkVersion; + + /// Target directory for build artifacts. + final String targetTempDir; + + /// Target being built. + final Target target; + + bool ndkIsInstalled() { + final ndkPath = path.join(sdkPath, 'ndk', ndkVersion); + final ndkPackageXml = File(path.join(ndkPath, 'package.xml')); + return ndkPackageXml.existsSync(); + } + + void installNdk({ + required String javaHome, + }) { + final sdkManagerExtension = Platform.isWindows ? '.bat' : ''; + final sdkManager = path.join( + sdkPath, + 'cmdline-tools', + 'latest', + 'bin', + 'sdkmanager$sdkManagerExtension', + ); + + log.info('Installing NDK $ndkVersion'); + runCommand(sdkManager, [ + '--install', + 'ndk;$ndkVersion', + ], environment: { + 'JAVA_HOME': javaHome, + }); + } + + Future> buildEnvironment() async { + final hostArch = Platform.isMacOS + ? "darwin-x86_64" + : (Platform.isLinux ? "linux-x86_64" : "windows-x86_64"); + + final ndkPath = path.join(sdkPath, 'ndk', ndkVersion); + final toolchainPath = path.join( + ndkPath, + 'toolchains', + 'llvm', + 'prebuilt', + hostArch, + 'bin', + ); + + final minSdkVersion = + math.max(target.androidMinSdkVersion!, this.minSdkVersion); + + final exe = Platform.isWindows ? '.exe' : ''; + + final arKey = 'AR_${target.rust}'; + final arValue = ['${target.rust}-ar', 'llvm-ar', 'llvm-ar.exe'] + .map((e) => path.join(toolchainPath, e)) + .firstWhereOrNull((element) => File(element).existsSync()); + if (arValue == null) { + throw Exception('Failed to find ar for $target in $toolchainPath'); + } + + final targetArg = '--target=${target.rust}$minSdkVersion'; + + final ccKey = 'CC_${target.rust}'; + final ccValue = path.join(toolchainPath, 'clang$exe'); + final cfFlagsKey = 'CFLAGS_${target.rust}'; + final cFlagsValue = targetArg; + + final cxxKey = 'CXX_${target.rust}'; + final cxxValue = path.join(toolchainPath, 'clang++$exe'); + final cxxFlagsKey = 'CXXFLAGS_${target.rust}'; + final cxxFlagsValue = targetArg; + + final linkerKey = + 'cargo_target_${target.rust.replaceAll('-', '_')}_linker'.toUpperCase(); + + final ranlibKey = 'RANLIB_${target.rust}'; + final ranlibValue = path.join(toolchainPath, 'llvm-ranlib$exe'); + + final ndkVersionParsed = Version.parse(ndkVersion); + final rustFlagsKey = 'CARGO_ENCODED_RUSTFLAGS'; + final rustFlagsValue = _libGccWorkaround(targetTempDir, ndkVersionParsed); + + final runRustTool = + Platform.isWindows ? 'run_build_tool.cmd' : 'run_build_tool.sh'; + + final packagePath = (await Isolate.resolvePackageUri( + Uri.parse('package:build_tool/buildtool.dart')))! + .toFilePath(); + final selfPath = path.canonicalize(path.join( + packagePath, + '..', + '..', + '..', + runRustTool, + )); + + // Make sure that run_build_tool is working properly even initially launched directly + // through dart run. + final toolTempDir = + Platform.environment['CARGOKIT_TOOL_TEMP_DIR'] ?? targetTempDir; + + return { + arKey: arValue, + ccKey: ccValue, + cfFlagsKey: cFlagsValue, + cxxKey: cxxValue, + cxxFlagsKey: cxxFlagsValue, + ranlibKey: ranlibValue, + rustFlagsKey: rustFlagsValue, + linkerKey: selfPath, + // Recognized by main() so we know when we're acting as a wrapper + '_CARGOKIT_NDK_LINK_TARGET': targetArg, + '_CARGOKIT_NDK_LINK_CLANG': ccValue, + 'CARGOKIT_TOOL_TEMP_DIR': toolTempDir, + }; + } + + // Workaround for libgcc missing in NDK23, inspired by cargo-ndk + String _libGccWorkaround(String buildDir, Version ndkVersion) { + final workaroundDir = path.join( + buildDir, + 'cargokit', + 'libgcc_workaround', + '${ndkVersion.major}', + ); + Directory(workaroundDir).createSync(recursive: true); + if (ndkVersion.major >= 23) { + File(path.join(workaroundDir, 'libgcc.a')) + .writeAsStringSync('INPUT(-lunwind)'); + } else { + // Other way around, untested, forward libgcc.a from libunwind once Rust + // gets updated for NDK23+. + File(path.join(workaroundDir, 'libunwind.a')) + .writeAsStringSync('INPUT(-lgcc)'); + } + + var rustFlags = Platform.environment['CARGO_ENCODED_RUSTFLAGS'] ?? ''; + if (rustFlags.isNotEmpty) { + rustFlags = '$rustFlags\x1f'; + } + rustFlags = '$rustFlags-L\x1f$workaroundDir'; + return rustFlags; + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/artifacts_provider.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/artifacts_provider.dart index e608cec..c5c39ee 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/artifacts_provider.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/artifacts_provider.dart @@ -1,266 +1,266 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:ed25519_edwards/ed25519_edwards.dart'; -import 'package:http/http.dart'; -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as path; - -import 'builder.dart'; -import 'crate_hash.dart'; -import 'options.dart'; -import 'precompile_binaries.dart'; -import 'rustup.dart'; -import 'target.dart'; - -class Artifact { - /// File system location of the artifact. - final String path; - - /// Actual file name that the artifact should have in destination folder. - final String finalFileName; - - AritifactType get type { - if (finalFileName.endsWith('.dll') || - finalFileName.endsWith('.dll.lib') || - finalFileName.endsWith('.pdb') || - finalFileName.endsWith('.so') || - finalFileName.endsWith('.dylib')) { - return AritifactType.dylib; - } else if (finalFileName.endsWith('.lib') || finalFileName.endsWith('.a')) { - return AritifactType.staticlib; - } else { - throw Exception('Unknown artifact type for $finalFileName'); - } - } - - Artifact({ - required this.path, - required this.finalFileName, - }); -} - -final _log = Logger('artifacts_provider'); - -class ArtifactProvider { - ArtifactProvider({ - required this.environment, - required this.userOptions, - }); - - final BuildEnvironment environment; - final CargokitUserOptions userOptions; - - Future>> getArtifacts(List targets) async { - final result = await _getPrecompiledArtifacts(targets); - - final pendingTargets = List.of(targets); - pendingTargets.removeWhere((element) => result.containsKey(element)); - - if (pendingTargets.isEmpty) { - return result; - } - - final rustup = Rustup(); - for (final target in targets) { - final builder = RustBuilder(target: target, environment: environment); - builder.prepare(rustup); - _log.info('Building ${environment.crateInfo.packageName} for $target'); - final targetDir = await builder.build(); - // For local build accept both static and dynamic libraries. - final artifactNames = { - ...getArtifactNames( - target: target, - libraryName: environment.crateInfo.packageName, - aritifactType: AritifactType.dylib, - remote: false, - ), - ...getArtifactNames( - target: target, - libraryName: environment.crateInfo.packageName, - aritifactType: AritifactType.staticlib, - remote: false, - ) - }; - final artifacts = artifactNames - .map((artifactName) => Artifact( - path: path.join(targetDir, artifactName), - finalFileName: artifactName, - )) - .where((element) => File(element.path).existsSync()) - .toList(); - result[target] = artifacts; - } - return result; - } - - Future>> _getPrecompiledArtifacts( - List targets) async { - if (userOptions.usePrecompiledBinaries == false) { - _log.info('Precompiled binaries are disabled'); - return {}; - } - if (environment.crateOptions.precompiledBinaries == null) { - _log.fine('Precompiled binaries not enabled for this crate'); - return {}; - } - - final start = Stopwatch()..start(); - final crateHash = CrateHash.compute(environment.manifestDir, - tempStorage: environment.targetTempDir); - _log.fine( - 'Computed crate hash $crateHash in ${start.elapsedMilliseconds}ms'); - - final downloadedArtifactsDir = - path.join(environment.targetTempDir, 'precompiled', crateHash); - Directory(downloadedArtifactsDir).createSync(recursive: true); - - final res = >{}; - - for (final target in targets) { - final requiredArtifacts = getArtifactNames( - target: target, - libraryName: environment.crateInfo.packageName, - remote: true, - ); - final artifactsForTarget = []; - - for (final artifact in requiredArtifacts) { - final fileName = PrecompileBinaries.fileName(target, artifact); - final downloadedPath = path.join(downloadedArtifactsDir, fileName); - if (!File(downloadedPath).existsSync()) { - final signatureFileName = - PrecompileBinaries.signatureFileName(target, artifact); - await _tryDownloadArtifacts( - crateHash: crateHash, - fileName: fileName, - signatureFileName: signatureFileName, - finalPath: downloadedPath, - ); - } - if (File(downloadedPath).existsSync()) { - artifactsForTarget.add(Artifact( - path: downloadedPath, - finalFileName: artifact, - )); - } else { - break; - } - } - - // Only provide complete set of artifacts. - if (artifactsForTarget.length == requiredArtifacts.length) { - _log.fine('Found precompiled artifacts for $target'); - res[target] = artifactsForTarget; - } - } - - return res; - } - - static Future _get(Uri url, {Map? headers}) async { - int attempt = 0; - const maxAttempts = 10; - while (true) { - try { - return await get(url, headers: headers); - } on SocketException catch (e) { - // Try to detect reset by peer error and retry. - if (attempt++ < maxAttempts && - (e.osError?.errorCode == 54 || e.osError?.errorCode == 10054)) { - _log.severe( - 'Failed to download $url: $e, attempt $attempt of $maxAttempts, will retry...'); - await Future.delayed(Duration(seconds: 1)); - continue; - } else { - rethrow; - } - } - } - } - - Future _tryDownloadArtifacts({ - required String crateHash, - required String fileName, - required String signatureFileName, - required String finalPath, - }) async { - final precompiledBinaries = environment.crateOptions.precompiledBinaries!; - final prefix = precompiledBinaries.uriPrefix; - final url = Uri.parse('$prefix$crateHash/$fileName'); - final signatureUrl = Uri.parse('$prefix$crateHash/$signatureFileName'); - _log.fine('Downloading signature from $signatureUrl'); - final signature = await _get(signatureUrl); - if (signature.statusCode == 404) { - _log.warning( - 'Precompiled binaries not available for crate hash $crateHash ($fileName)'); - return; - } - if (signature.statusCode != 200) { - _log.severe( - 'Failed to download signature $signatureUrl: status ${signature.statusCode}'); - return; - } - _log.fine('Downloading binary from $url'); - final res = await _get(url); - if (res.statusCode != 200) { - _log.severe('Failed to download binary $url: status ${res.statusCode}'); - return; - } - if (verify( - precompiledBinaries.publicKey, res.bodyBytes, signature.bodyBytes)) { - File(finalPath).writeAsBytesSync(res.bodyBytes); - } else { - _log.shout('Signature verification failed! Ignoring binary.'); - } - } -} - -enum AritifactType { - staticlib, - dylib, -} - -AritifactType artifactTypeForTarget(Target target) { - if (target.darwinPlatform != null) { - return AritifactType.staticlib; - } else { - return AritifactType.dylib; - } -} - -List getArtifactNames({ - required Target target, - required String libraryName, - required bool remote, - AritifactType? aritifactType, -}) { - aritifactType ??= artifactTypeForTarget(target); - if (target.darwinArch != null) { - if (aritifactType == AritifactType.staticlib) { - return ['lib$libraryName.a']; - } else { - return ['lib$libraryName.dylib']; - } - } else if (target.rust.contains('-windows-')) { - if (aritifactType == AritifactType.staticlib) { - return ['$libraryName.lib']; - } else { - return [ - '$libraryName.dll', - '$libraryName.dll.lib', - if (!remote) '$libraryName.pdb' - ]; - } - } else if (target.rust.contains('-linux-')) { - if (aritifactType == AritifactType.staticlib) { - return ['lib$libraryName.a']; - } else { - return ['lib$libraryName.so']; - } - } else { - throw Exception("Unsupported target: ${target.rust}"); - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:ed25519_edwards/ed25519_edwards.dart'; +import 'package:http/http.dart'; +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as path; + +import 'builder.dart'; +import 'crate_hash.dart'; +import 'options.dart'; +import 'precompile_binaries.dart'; +import 'rustup.dart'; +import 'target.dart'; + +class Artifact { + /// File system location of the artifact. + final String path; + + /// Actual file name that the artifact should have in destination folder. + final String finalFileName; + + AritifactType get type { + if (finalFileName.endsWith('.dll') || + finalFileName.endsWith('.dll.lib') || + finalFileName.endsWith('.pdb') || + finalFileName.endsWith('.so') || + finalFileName.endsWith('.dylib')) { + return AritifactType.dylib; + } else if (finalFileName.endsWith('.lib') || finalFileName.endsWith('.a')) { + return AritifactType.staticlib; + } else { + throw Exception('Unknown artifact type for $finalFileName'); + } + } + + Artifact({ + required this.path, + required this.finalFileName, + }); +} + +final _log = Logger('artifacts_provider'); + +class ArtifactProvider { + ArtifactProvider({ + required this.environment, + required this.userOptions, + }); + + final BuildEnvironment environment; + final CargokitUserOptions userOptions; + + Future>> getArtifacts(List targets) async { + final result = await _getPrecompiledArtifacts(targets); + + final pendingTargets = List.of(targets); + pendingTargets.removeWhere((element) => result.containsKey(element)); + + if (pendingTargets.isEmpty) { + return result; + } + + final rustup = Rustup(); + for (final target in targets) { + final builder = RustBuilder(target: target, environment: environment); + builder.prepare(rustup); + _log.info('Building ${environment.crateInfo.packageName} for $target'); + final targetDir = await builder.build(); + // For local build accept both static and dynamic libraries. + final artifactNames = { + ...getArtifactNames( + target: target, + libraryName: environment.crateInfo.packageName, + aritifactType: AritifactType.dylib, + remote: false, + ), + ...getArtifactNames( + target: target, + libraryName: environment.crateInfo.packageName, + aritifactType: AritifactType.staticlib, + remote: false, + ) + }; + final artifacts = artifactNames + .map((artifactName) => Artifact( + path: path.join(targetDir, artifactName), + finalFileName: artifactName, + )) + .where((element) => File(element.path).existsSync()) + .toList(); + result[target] = artifacts; + } + return result; + } + + Future>> _getPrecompiledArtifacts( + List targets) async { + if (userOptions.usePrecompiledBinaries == false) { + _log.info('Precompiled binaries are disabled'); + return {}; + } + if (environment.crateOptions.precompiledBinaries == null) { + _log.fine('Precompiled binaries not enabled for this crate'); + return {}; + } + + final start = Stopwatch()..start(); + final crateHash = CrateHash.compute(environment.manifestDir, + tempStorage: environment.targetTempDir); + _log.fine( + 'Computed crate hash $crateHash in ${start.elapsedMilliseconds}ms'); + + final downloadedArtifactsDir = + path.join(environment.targetTempDir, 'precompiled', crateHash); + Directory(downloadedArtifactsDir).createSync(recursive: true); + + final res = >{}; + + for (final target in targets) { + final requiredArtifacts = getArtifactNames( + target: target, + libraryName: environment.crateInfo.packageName, + remote: true, + ); + final artifactsForTarget = []; + + for (final artifact in requiredArtifacts) { + final fileName = PrecompileBinaries.fileName(target, artifact); + final downloadedPath = path.join(downloadedArtifactsDir, fileName); + if (!File(downloadedPath).existsSync()) { + final signatureFileName = + PrecompileBinaries.signatureFileName(target, artifact); + await _tryDownloadArtifacts( + crateHash: crateHash, + fileName: fileName, + signatureFileName: signatureFileName, + finalPath: downloadedPath, + ); + } + if (File(downloadedPath).existsSync()) { + artifactsForTarget.add(Artifact( + path: downloadedPath, + finalFileName: artifact, + )); + } else { + break; + } + } + + // Only provide complete set of artifacts. + if (artifactsForTarget.length == requiredArtifacts.length) { + _log.fine('Found precompiled artifacts for $target'); + res[target] = artifactsForTarget; + } + } + + return res; + } + + static Future _get(Uri url, {Map? headers}) async { + int attempt = 0; + const maxAttempts = 10; + while (true) { + try { + return await get(url, headers: headers); + } on SocketException catch (e) { + // Try to detect reset by peer error and retry. + if (attempt++ < maxAttempts && + (e.osError?.errorCode == 54 || e.osError?.errorCode == 10054)) { + _log.severe( + 'Failed to download $url: $e, attempt $attempt of $maxAttempts, will retry...'); + await Future.delayed(Duration(seconds: 1)); + continue; + } else { + rethrow; + } + } + } + } + + Future _tryDownloadArtifacts({ + required String crateHash, + required String fileName, + required String signatureFileName, + required String finalPath, + }) async { + final precompiledBinaries = environment.crateOptions.precompiledBinaries!; + final prefix = precompiledBinaries.uriPrefix; + final url = Uri.parse('$prefix$crateHash/$fileName'); + final signatureUrl = Uri.parse('$prefix$crateHash/$signatureFileName'); + _log.fine('Downloading signature from $signatureUrl'); + final signature = await _get(signatureUrl); + if (signature.statusCode == 404) { + _log.warning( + 'Precompiled binaries not available for crate hash $crateHash ($fileName)'); + return; + } + if (signature.statusCode != 200) { + _log.severe( + 'Failed to download signature $signatureUrl: status ${signature.statusCode}'); + return; + } + _log.fine('Downloading binary from $url'); + final res = await _get(url); + if (res.statusCode != 200) { + _log.severe('Failed to download binary $url: status ${res.statusCode}'); + return; + } + if (verify( + precompiledBinaries.publicKey, res.bodyBytes, signature.bodyBytes)) { + File(finalPath).writeAsBytesSync(res.bodyBytes); + } else { + _log.shout('Signature verification failed! Ignoring binary.'); + } + } +} + +enum AritifactType { + staticlib, + dylib, +} + +AritifactType artifactTypeForTarget(Target target) { + if (target.darwinPlatform != null) { + return AritifactType.staticlib; + } else { + return AritifactType.dylib; + } +} + +List getArtifactNames({ + required Target target, + required String libraryName, + required bool remote, + AritifactType? aritifactType, +}) { + aritifactType ??= artifactTypeForTarget(target); + if (target.darwinArch != null) { + if (aritifactType == AritifactType.staticlib) { + return ['lib$libraryName.a']; + } else { + return ['lib$libraryName.dylib']; + } + } else if (target.rust.contains('-windows-')) { + if (aritifactType == AritifactType.staticlib) { + return ['$libraryName.lib']; + } else { + return [ + '$libraryName.dll', + '$libraryName.dll.lib', + if (!remote) '$libraryName.pdb' + ]; + } + } else if (target.rust.contains('-linux-')) { + if (aritifactType == AritifactType.staticlib) { + return ['lib$libraryName.a']; + } else { + return ['lib$libraryName.so']; + } + } else { + throw Exception("Unsupported target: ${target.rust}"); + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/build_cmake.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/build_cmake.dart index 6f3b2a4..a28b748 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/build_cmake.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/build_cmake.dart @@ -1,40 +1,40 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:path/path.dart' as path; - -import 'artifacts_provider.dart'; -import 'builder.dart'; -import 'environment.dart'; -import 'options.dart'; -import 'target.dart'; - -class BuildCMake { - final CargokitUserOptions userOptions; - - BuildCMake({required this.userOptions}); - - Future build() async { - final targetPlatform = Environment.targetPlatform; - final target = Target.forFlutterName(Environment.targetPlatform); - if (target == null) { - throw Exception("Unknown target platform: $targetPlatform"); - } - - final environment = BuildEnvironment.fromEnvironment(isAndroid: false); - final provider = - ArtifactProvider(environment: environment, userOptions: userOptions); - final artifacts = await provider.getArtifacts([target]); - - final libs = artifacts[target]!; - - for (final lib in libs) { - if (lib.type == AritifactType.dylib) { - File(lib.path) - .copySync(path.join(Environment.outputDir, lib.finalFileName)); - } - } - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:path/path.dart' as path; + +import 'artifacts_provider.dart'; +import 'builder.dart'; +import 'environment.dart'; +import 'options.dart'; +import 'target.dart'; + +class BuildCMake { + final CargokitUserOptions userOptions; + + BuildCMake({required this.userOptions}); + + Future build() async { + final targetPlatform = Environment.targetPlatform; + final target = Target.forFlutterName(Environment.targetPlatform); + if (target == null) { + throw Exception("Unknown target platform: $targetPlatform"); + } + + final environment = BuildEnvironment.fromEnvironment(isAndroid: false); + final provider = + ArtifactProvider(environment: environment, userOptions: userOptions); + final artifacts = await provider.getArtifacts([target]); + + final libs = artifacts[target]!; + + for (final lib in libs) { + if (lib.type == AritifactType.dylib) { + File(lib.path) + .copySync(path.join(Environment.outputDir, lib.finalFileName)); + } + } + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/build_gradle.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/build_gradle.dart index 7e61fcb..9b585bc 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/build_gradle.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/build_gradle.dart @@ -1,49 +1,49 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as path; - -import 'artifacts_provider.dart'; -import 'builder.dart'; -import 'environment.dart'; -import 'options.dart'; -import 'target.dart'; - -final log = Logger('build_gradle'); - -class BuildGradle { - BuildGradle({required this.userOptions}); - - final CargokitUserOptions userOptions; - - Future build() async { - final targets = Environment.targetPlatforms.map((arch) { - final target = Target.forFlutterName(arch); - if (target == null) { - throw Exception( - "Unknown darwin target or platform: $arch, ${Environment.darwinPlatformName}"); - } - return target; - }).toList(); - - final environment = BuildEnvironment.fromEnvironment(isAndroid: true); - final provider = - ArtifactProvider(environment: environment, userOptions: userOptions); - final artifacts = await provider.getArtifacts(targets); - - for (final target in targets) { - final libs = artifacts[target]!; - final outputDir = path.join(Environment.outputDir, target.android!); - Directory(outputDir).createSync(recursive: true); - - for (final lib in libs) { - if (lib.type == AritifactType.dylib) { - File(lib.path).copySync(path.join(outputDir, lib.finalFileName)); - } - } - } - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as path; + +import 'artifacts_provider.dart'; +import 'builder.dart'; +import 'environment.dart'; +import 'options.dart'; +import 'target.dart'; + +final log = Logger('build_gradle'); + +class BuildGradle { + BuildGradle({required this.userOptions}); + + final CargokitUserOptions userOptions; + + Future build() async { + final targets = Environment.targetPlatforms.map((arch) { + final target = Target.forFlutterName(arch); + if (target == null) { + throw Exception( + "Unknown darwin target or platform: $arch, ${Environment.darwinPlatformName}"); + } + return target; + }).toList(); + + final environment = BuildEnvironment.fromEnvironment(isAndroid: true); + final provider = + ArtifactProvider(environment: environment, userOptions: userOptions); + final artifacts = await provider.getArtifacts(targets); + + for (final target in targets) { + final libs = artifacts[target]!; + final outputDir = path.join(Environment.outputDir, target.android!); + Directory(outputDir).createSync(recursive: true); + + for (final lib in libs) { + if (lib.type == AritifactType.dylib) { + File(lib.path).copySync(path.join(outputDir, lib.finalFileName)); + } + } + } + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/build_pod.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/build_pod.dart index 8a9c0db..057afc8 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/build_pod.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/build_pod.dart @@ -1,89 +1,89 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:path/path.dart' as path; - -import 'artifacts_provider.dart'; -import 'builder.dart'; -import 'environment.dart'; -import 'options.dart'; -import 'target.dart'; -import 'util.dart'; - -class BuildPod { - BuildPod({required this.userOptions}); - - final CargokitUserOptions userOptions; - - Future build() async { - final targets = Environment.darwinArchs.map((arch) { - final target = Target.forDarwin( - platformName: Environment.darwinPlatformName, darwinAarch: arch); - if (target == null) { - throw Exception( - "Unknown darwin target or platform: $arch, ${Environment.darwinPlatformName}"); - } - return target; - }).toList(); - - final environment = BuildEnvironment.fromEnvironment(isAndroid: false); - final provider = - ArtifactProvider(environment: environment, userOptions: userOptions); - final artifacts = await provider.getArtifacts(targets); - - void performLipo(String targetFile, Iterable sourceFiles) { - runCommand("lipo", [ - '-create', - ...sourceFiles, - '-output', - targetFile, - ]); - } - - final outputDir = Environment.outputDir; - - Directory(outputDir).createSync(recursive: true); - - final staticLibs = artifacts.values - .expand((element) => element) - .where((element) => element.type == AritifactType.staticlib) - .toList(); - final dynamicLibs = artifacts.values - .expand((element) => element) - .where((element) => element.type == AritifactType.dylib) - .toList(); - - final libName = environment.crateInfo.packageName; - - // If there is static lib, use it and link it with pod - if (staticLibs.isNotEmpty) { - final finalTargetFile = path.join(outputDir, "lib$libName.a"); - performLipo(finalTargetFile, staticLibs.map((e) => e.path)); - } else { - // Otherwise try to replace bundle dylib with our dylib - final bundlePaths = [ - '$libName.framework/Versions/A/$libName', - '$libName.framework/$libName', - ]; - - for (final bundlePath in bundlePaths) { - final targetFile = path.join(outputDir, bundlePath); - if (File(targetFile).existsSync()) { - performLipo(targetFile, dynamicLibs.map((e) => e.path)); - - // Replace absolute id with @rpath one so that it works properly - // when moved to Frameworks. - runCommand("install_name_tool", [ - '-id', - '@rpath/$bundlePath', - targetFile, - ]); - return; - } - } - throw Exception('Unable to find bundle for dynamic library'); - } - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:path/path.dart' as path; + +import 'artifacts_provider.dart'; +import 'builder.dart'; +import 'environment.dart'; +import 'options.dart'; +import 'target.dart'; +import 'util.dart'; + +class BuildPod { + BuildPod({required this.userOptions}); + + final CargokitUserOptions userOptions; + + Future build() async { + final targets = Environment.darwinArchs.map((arch) { + final target = Target.forDarwin( + platformName: Environment.darwinPlatformName, darwinAarch: arch); + if (target == null) { + throw Exception( + "Unknown darwin target or platform: $arch, ${Environment.darwinPlatformName}"); + } + return target; + }).toList(); + + final environment = BuildEnvironment.fromEnvironment(isAndroid: false); + final provider = + ArtifactProvider(environment: environment, userOptions: userOptions); + final artifacts = await provider.getArtifacts(targets); + + void performLipo(String targetFile, Iterable sourceFiles) { + runCommand("lipo", [ + '-create', + ...sourceFiles, + '-output', + targetFile, + ]); + } + + final outputDir = Environment.outputDir; + + Directory(outputDir).createSync(recursive: true); + + final staticLibs = artifacts.values + .expand((element) => element) + .where((element) => element.type == AritifactType.staticlib) + .toList(); + final dynamicLibs = artifacts.values + .expand((element) => element) + .where((element) => element.type == AritifactType.dylib) + .toList(); + + final libName = environment.crateInfo.packageName; + + // If there is static lib, use it and link it with pod + if (staticLibs.isNotEmpty) { + final finalTargetFile = path.join(outputDir, "lib$libName.a"); + performLipo(finalTargetFile, staticLibs.map((e) => e.path)); + } else { + // Otherwise try to replace bundle dylib with our dylib + final bundlePaths = [ + '$libName.framework/Versions/A/$libName', + '$libName.framework/$libName', + ]; + + for (final bundlePath in bundlePaths) { + final targetFile = path.join(outputDir, bundlePath); + if (File(targetFile).existsSync()) { + performLipo(targetFile, dynamicLibs.map((e) => e.path)); + + // Replace absolute id with @rpath one so that it works properly + // when moved to Frameworks. + runCommand("install_name_tool", [ + '-id', + '@rpath/$bundlePath', + targetFile, + ]); + return; + } + } + throw Exception('Unable to find bundle for dynamic library'); + } + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/build_tool.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/build_tool.dart index 70dfe0e..be18fa6 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/build_tool.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/build_tool.dart @@ -1,276 +1,276 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:args/command_runner.dart'; -import 'package:ed25519_edwards/ed25519_edwards.dart'; -import 'package:github/github.dart'; -import 'package:hex/hex.dart'; -import 'package:logging/logging.dart'; - -import 'android_environment.dart'; -import 'build_cmake.dart'; -import 'build_gradle.dart'; -import 'build_pod.dart'; -import 'logging.dart'; -import 'options.dart'; -import 'precompile_binaries.dart'; -import 'target.dart'; -import 'util.dart'; -import 'verify_binaries.dart'; - -final log = Logger('build_tool'); - -abstract class BuildCommand extends Command { - Future runBuildCommand(CargokitUserOptions options); - - @override - Future run() async { - final options = CargokitUserOptions.load(); - - if (options.verboseLogging || - Platform.environment['CARGOKIT_VERBOSE'] == '1') { - enableVerboseLogging(); - } - - await runBuildCommand(options); - } -} - -class BuildPodCommand extends BuildCommand { - @override - final name = 'build-pod'; - - @override - final description = 'Build cocoa pod library'; - - @override - Future runBuildCommand(CargokitUserOptions options) async { - final build = BuildPod(userOptions: options); - await build.build(); - } -} - -class BuildGradleCommand extends BuildCommand { - @override - final name = 'build-gradle'; - - @override - final description = 'Build android library'; - - @override - Future runBuildCommand(CargokitUserOptions options) async { - final build = BuildGradle(userOptions: options); - await build.build(); - } -} - -class BuildCMakeCommand extends BuildCommand { - @override - final name = 'build-cmake'; - - @override - final description = 'Build CMake library'; - - @override - Future runBuildCommand(CargokitUserOptions options) async { - final build = BuildCMake(userOptions: options); - await build.build(); - } -} - -class GenKeyCommand extends Command { - @override - final name = 'gen-key'; - - @override - final description = 'Generate key pair for signing precompiled binaries'; - - @override - void run() { - final kp = generateKey(); - final private = HEX.encode(kp.privateKey.bytes); - final public = HEX.encode(kp.publicKey.bytes); - print("Private Key: $private"); - print("Public Key: $public"); - } -} - -class PrecompileBinariesCommand extends Command { - PrecompileBinariesCommand() { - argParser - ..addOption( - 'repository', - mandatory: true, - help: 'Github repository slug in format owner/name', - ) - ..addOption( - 'manifest-dir', - mandatory: true, - help: 'Directory containing Cargo.toml', - ) - ..addMultiOption('target', - help: 'Rust target triple of artifact to build.\n' - 'Can be specified multiple times or omitted in which case\n' - 'all targets for current platform will be built.') - ..addOption( - 'android-sdk-location', - help: 'Location of Android SDK (if available)', - ) - ..addOption( - 'android-ndk-version', - help: 'Android NDK version (if available)', - ) - ..addOption( - 'android-min-sdk-version', - help: 'Android minimum rquired version (if available)', - ) - ..addOption( - 'temp-dir', - help: 'Directory to store temporary build artifacts', - ) - ..addOption( - 'glibc-version', - help: 'GLIBC version to use for linux builds', - ) - ..addFlag( - "verbose", - abbr: "v", - defaultsTo: false, - help: "Enable verbose logging", - ); - } - - @override - final name = 'precompile-binaries'; - - @override - final description = 'Prebuild and upload binaries\n' - 'Private key must be passed through PRIVATE_KEY environment variable. ' - 'Use gen_key through generate priave key.\n' - 'Github token must be passed as GITHUB_TOKEN environment variable.\n'; - - @override - Future run() async { - final verbose = argResults!['verbose'] as bool; - if (verbose) { - enableVerboseLogging(); - } - - final privateKeyString = Platform.environment['PRIVATE_KEY']; - if (privateKeyString == null) { - throw ArgumentError('Missing PRIVATE_KEY environment variable'); - } - final githubToken = Platform.environment['GITHUB_TOKEN']; - if (githubToken == null) { - throw ArgumentError('Missing GITHUB_TOKEN environment variable'); - } - final privateKey = HEX.decode(privateKeyString); - if (privateKey.length != 64) { - throw ArgumentError('Private key must be 64 bytes long'); - } - final manifestDir = argResults!['manifest-dir'] as String; - if (!Directory(manifestDir).existsSync()) { - throw ArgumentError('Manifest directory does not exist: $manifestDir'); - } - String? androidMinSdkVersionString = - argResults!['android-min-sdk-version'] as String?; - int? androidMinSdkVersion; - if (androidMinSdkVersionString != null) { - androidMinSdkVersion = int.tryParse(androidMinSdkVersionString); - if (androidMinSdkVersion == null) { - throw ArgumentError( - 'Invalid android-min-sdk-version: $androidMinSdkVersionString'); - } - } - final targetStrigns = argResults!['target'] as List; - final targets = targetStrigns.map((target) { - final res = Target.forRustTriple(target); - if (res == null) { - throw ArgumentError('Invalid target: $target'); - } - return res; - }).toList(growable: false); - final precompileBinaries = PrecompileBinaries( - privateKey: PrivateKey(privateKey), - githubToken: githubToken, - manifestDir: manifestDir, - repositorySlug: RepositorySlug.full(argResults!['repository'] as String), - targets: targets, - androidSdkLocation: argResults!['android-sdk-location'] as String?, - androidNdkVersion: argResults!['android-ndk-version'] as String?, - androidMinSdkVersion: androidMinSdkVersion, - tempDir: argResults!['temp-dir'] as String?, - glibcVersion: argResults!['glibc-version'] as String?, - ); - - await precompileBinaries.run(); - } -} - -class VerifyBinariesCommand extends Command { - VerifyBinariesCommand() { - argParser.addOption( - 'manifest-dir', - mandatory: true, - help: 'Directory containing Cargo.toml', - ); - } - - @override - final name = "verify-binaries"; - - @override - final description = 'Verifies published binaries\n' - 'Checks whether there is a binary published for each targets\n' - 'and checks the signature.'; - - @override - Future run() async { - final manifestDir = argResults!['manifest-dir'] as String; - final verifyBinaries = VerifyBinaries( - manifestDir: manifestDir, - ); - await verifyBinaries.run(); - } -} - -Future runMain(List args) async { - try { - // Init logging before options are loaded - initLogging(); - - if (Platform.environment['_CARGOKIT_NDK_LINK_TARGET'] != null) { - return AndroidEnvironment.clangLinkerWrapper(args); - } - - final runner = CommandRunner('build_tool', 'Cargokit built_tool') - ..addCommand(BuildPodCommand()) - ..addCommand(BuildGradleCommand()) - ..addCommand(BuildCMakeCommand()) - ..addCommand(GenKeyCommand()) - ..addCommand(PrecompileBinariesCommand()) - ..addCommand(VerifyBinariesCommand()); - - await runner.run(args); - } on ArgumentError catch (e) { - stderr.writeln(e.toString()); - exit(1); - } catch (e, s) { - log.severe(kDoubleSeparator); - log.severe('Cargokit BuildTool failed with error:'); - log.severe(kSeparator); - log.severe(e); - // This tells user to install Rust, there's no need to pollute the log with - // stack trace. - if (e is! RustupNotFoundException) { - log.severe(kSeparator); - log.severe(s); - log.severe(kSeparator); - log.severe('BuildTool arguments: $args'); - } - log.severe(kDoubleSeparator); - exit(1); - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:args/command_runner.dart'; +import 'package:ed25519_edwards/ed25519_edwards.dart'; +import 'package:github/github.dart'; +import 'package:hex/hex.dart'; +import 'package:logging/logging.dart'; + +import 'android_environment.dart'; +import 'build_cmake.dart'; +import 'build_gradle.dart'; +import 'build_pod.dart'; +import 'logging.dart'; +import 'options.dart'; +import 'precompile_binaries.dart'; +import 'target.dart'; +import 'util.dart'; +import 'verify_binaries.dart'; + +final log = Logger('build_tool'); + +abstract class BuildCommand extends Command { + Future runBuildCommand(CargokitUserOptions options); + + @override + Future run() async { + final options = CargokitUserOptions.load(); + + if (options.verboseLogging || + Platform.environment['CARGOKIT_VERBOSE'] == '1') { + enableVerboseLogging(); + } + + await runBuildCommand(options); + } +} + +class BuildPodCommand extends BuildCommand { + @override + final name = 'build-pod'; + + @override + final description = 'Build cocoa pod library'; + + @override + Future runBuildCommand(CargokitUserOptions options) async { + final build = BuildPod(userOptions: options); + await build.build(); + } +} + +class BuildGradleCommand extends BuildCommand { + @override + final name = 'build-gradle'; + + @override + final description = 'Build android library'; + + @override + Future runBuildCommand(CargokitUserOptions options) async { + final build = BuildGradle(userOptions: options); + await build.build(); + } +} + +class BuildCMakeCommand extends BuildCommand { + @override + final name = 'build-cmake'; + + @override + final description = 'Build CMake library'; + + @override + Future runBuildCommand(CargokitUserOptions options) async { + final build = BuildCMake(userOptions: options); + await build.build(); + } +} + +class GenKeyCommand extends Command { + @override + final name = 'gen-key'; + + @override + final description = 'Generate key pair for signing precompiled binaries'; + + @override + void run() { + final kp = generateKey(); + final private = HEX.encode(kp.privateKey.bytes); + final public = HEX.encode(kp.publicKey.bytes); + print("Private Key: $private"); + print("Public Key: $public"); + } +} + +class PrecompileBinariesCommand extends Command { + PrecompileBinariesCommand() { + argParser + ..addOption( + 'repository', + mandatory: true, + help: 'Github repository slug in format owner/name', + ) + ..addOption( + 'manifest-dir', + mandatory: true, + help: 'Directory containing Cargo.toml', + ) + ..addMultiOption('target', + help: 'Rust target triple of artifact to build.\n' + 'Can be specified multiple times or omitted in which case\n' + 'all targets for current platform will be built.') + ..addOption( + 'android-sdk-location', + help: 'Location of Android SDK (if available)', + ) + ..addOption( + 'android-ndk-version', + help: 'Android NDK version (if available)', + ) + ..addOption( + 'android-min-sdk-version', + help: 'Android minimum rquired version (if available)', + ) + ..addOption( + 'temp-dir', + help: 'Directory to store temporary build artifacts', + ) + ..addOption( + 'glibc-version', + help: 'GLIBC version to use for linux builds', + ) + ..addFlag( + "verbose", + abbr: "v", + defaultsTo: false, + help: "Enable verbose logging", + ); + } + + @override + final name = 'precompile-binaries'; + + @override + final description = 'Prebuild and upload binaries\n' + 'Private key must be passed through PRIVATE_KEY environment variable. ' + 'Use gen_key through generate priave key.\n' + 'Github token must be passed as GITHUB_TOKEN environment variable.\n'; + + @override + Future run() async { + final verbose = argResults!['verbose'] as bool; + if (verbose) { + enableVerboseLogging(); + } + + final privateKeyString = Platform.environment['PRIVATE_KEY']; + if (privateKeyString == null) { + throw ArgumentError('Missing PRIVATE_KEY environment variable'); + } + final githubToken = Platform.environment['GITHUB_TOKEN']; + if (githubToken == null) { + throw ArgumentError('Missing GITHUB_TOKEN environment variable'); + } + final privateKey = HEX.decode(privateKeyString); + if (privateKey.length != 64) { + throw ArgumentError('Private key must be 64 bytes long'); + } + final manifestDir = argResults!['manifest-dir'] as String; + if (!Directory(manifestDir).existsSync()) { + throw ArgumentError('Manifest directory does not exist: $manifestDir'); + } + String? androidMinSdkVersionString = + argResults!['android-min-sdk-version'] as String?; + int? androidMinSdkVersion; + if (androidMinSdkVersionString != null) { + androidMinSdkVersion = int.tryParse(androidMinSdkVersionString); + if (androidMinSdkVersion == null) { + throw ArgumentError( + 'Invalid android-min-sdk-version: $androidMinSdkVersionString'); + } + } + final targetStrigns = argResults!['target'] as List; + final targets = targetStrigns.map((target) { + final res = Target.forRustTriple(target); + if (res == null) { + throw ArgumentError('Invalid target: $target'); + } + return res; + }).toList(growable: false); + final precompileBinaries = PrecompileBinaries( + privateKey: PrivateKey(privateKey), + githubToken: githubToken, + manifestDir: manifestDir, + repositorySlug: RepositorySlug.full(argResults!['repository'] as String), + targets: targets, + androidSdkLocation: argResults!['android-sdk-location'] as String?, + androidNdkVersion: argResults!['android-ndk-version'] as String?, + androidMinSdkVersion: androidMinSdkVersion, + tempDir: argResults!['temp-dir'] as String?, + glibcVersion: argResults!['glibc-version'] as String?, + ); + + await precompileBinaries.run(); + } +} + +class VerifyBinariesCommand extends Command { + VerifyBinariesCommand() { + argParser.addOption( + 'manifest-dir', + mandatory: true, + help: 'Directory containing Cargo.toml', + ); + } + + @override + final name = "verify-binaries"; + + @override + final description = 'Verifies published binaries\n' + 'Checks whether there is a binary published for each targets\n' + 'and checks the signature.'; + + @override + Future run() async { + final manifestDir = argResults!['manifest-dir'] as String; + final verifyBinaries = VerifyBinaries( + manifestDir: manifestDir, + ); + await verifyBinaries.run(); + } +} + +Future runMain(List args) async { + try { + // Init logging before options are loaded + initLogging(); + + if (Platform.environment['_CARGOKIT_NDK_LINK_TARGET'] != null) { + return AndroidEnvironment.clangLinkerWrapper(args); + } + + final runner = CommandRunner('build_tool', 'Cargokit built_tool') + ..addCommand(BuildPodCommand()) + ..addCommand(BuildGradleCommand()) + ..addCommand(BuildCMakeCommand()) + ..addCommand(GenKeyCommand()) + ..addCommand(PrecompileBinariesCommand()) + ..addCommand(VerifyBinariesCommand()); + + await runner.run(args); + } on ArgumentError catch (e) { + stderr.writeln(e.toString()); + exit(1); + } catch (e, s) { + log.severe(kDoubleSeparator); + log.severe('Cargokit BuildTool failed with error:'); + log.severe(kSeparator); + log.severe(e); + // This tells user to install Rust, there's no need to pollute the log with + // stack trace. + if (e is! RustupNotFoundException) { + log.severe(kSeparator); + log.severe(s); + log.severe(kSeparator); + log.severe('BuildTool arguments: $args'); + } + log.severe(kDoubleSeparator); + exit(1); + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/builder.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/builder.dart index cd5269f..54b1cdc 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/builder.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/builder.dart @@ -1,209 +1,209 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'package:collection/collection.dart'; -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as path; - -import 'android_environment.dart'; -import 'cargo.dart'; -import 'environment.dart'; -import 'options.dart'; -import 'rustup.dart'; -import 'target.dart'; -import 'util.dart'; - -final _log = Logger('builder'); - -enum BuildConfiguration { - debug, - release, - profile, -} - -extension on BuildConfiguration { - bool get isDebug => this == BuildConfiguration.debug; - String get rustName => switch (this) { - BuildConfiguration.debug => 'debug', - BuildConfiguration.release => 'release', - BuildConfiguration.profile => 'release', - }; -} - -class BuildException implements Exception { - final String message; - - BuildException(this.message); - - @override - String toString() { - return 'BuildException: $message'; - } -} - -class BuildEnvironment { - final BuildConfiguration configuration; - final CargokitCrateOptions crateOptions; - final String targetTempDir; - final String manifestDir; - final CrateInfo crateInfo; - - final bool isAndroid; - final String? androidSdkPath; - final String? androidNdkVersion; - final int? androidMinSdkVersion; - final String? javaHome; - - final String? glibcVersion; - - BuildEnvironment({ - required this.configuration, - required this.crateOptions, - required this.targetTempDir, - required this.manifestDir, - required this.crateInfo, - required this.isAndroid, - this.androidSdkPath, - this.androidNdkVersion, - this.androidMinSdkVersion, - this.javaHome, - this.glibcVersion, - }); - - static BuildConfiguration parseBuildConfiguration(String value) { - // XCode configuration adds the flavor to configuration name. - final firstSegment = value.split('-').first; - final buildConfiguration = BuildConfiguration.values.firstWhereOrNull( - (e) => e.name == firstSegment, - ); - if (buildConfiguration == null) { - _log.warning('Unknown build configuraiton $value, will assume release'); - return BuildConfiguration.release; - } - return buildConfiguration; - } - - static BuildEnvironment fromEnvironment({ - required bool isAndroid, - }) { - final buildConfiguration = - parseBuildConfiguration(Environment.configuration); - final manifestDir = Environment.manifestDir; - final crateOptions = CargokitCrateOptions.load( - manifestDir: manifestDir, - ); - final crateInfo = CrateInfo.load(manifestDir); - return BuildEnvironment( - configuration: buildConfiguration, - crateOptions: crateOptions, - targetTempDir: Environment.targetTempDir, - manifestDir: manifestDir, - crateInfo: crateInfo, - isAndroid: isAndroid, - androidSdkPath: isAndroid ? Environment.sdkPath : null, - androidNdkVersion: isAndroid ? Environment.ndkVersion : null, - androidMinSdkVersion: - isAndroid ? int.parse(Environment.minSdkVersion) : null, - javaHome: isAndroid ? Environment.javaHome : null, - ); - } -} - -class RustBuilder { - final Target target; - final BuildEnvironment environment; - - RustBuilder({ - required this.target, - required this.environment, - }); - - void prepare( - Rustup rustup, - ) { - final toolchain = _toolchain; - if (rustup.installedTargets(toolchain) == null) { - rustup.installToolchain(toolchain); - } - if (toolchain == 'nightly') { - rustup.installRustSrcForNightly(); - } - if (!rustup.installedTargets(toolchain)!.contains(target.rust)) { - rustup.installTarget(target.rust, toolchain: toolchain); - } - if (environment.glibcVersion != null) { - rustup.installZigBuild(toolchain); - } - } - - CargoBuildOptions? get _buildOptions => - environment.crateOptions.cargo[environment.configuration]; - - String get _toolchain => _buildOptions?.toolchain.name ?? 'stable'; - - /// Returns the path of directory containing build artifacts. - Future build() async { - final extraArgs = _buildOptions?.flags ?? []; - final manifestPath = path.join(environment.manifestDir, 'Cargo.toml'); - runCommand( - 'rustup', - [ - 'run', - _toolchain, - 'cargo', - (target.android == null && environment.glibcVersion != null) - ? 'zigbuild' - : 'build', - ...extraArgs, - '--manifest-path', - manifestPath, - '-p', - environment.crateInfo.packageName, - if (!environment.configuration.isDebug) '--release', - '--target', - target.rust + - ((target.android == null && environment.glibcVersion != null) - ? '.${environment.glibcVersion!}' - : ""), - '--target-dir', - environment.targetTempDir, - ], - environment: await _buildEnvironment(), - ); - return path.join( - environment.targetTempDir, - target.rust, - environment.configuration.rustName, - ); - } - - Future> _buildEnvironment() async { - if (target.android == null) { - return {}; - } else { - final sdkPath = environment.androidSdkPath; - final ndkVersion = environment.androidNdkVersion; - final minSdkVersion = environment.androidMinSdkVersion; - if (sdkPath == null) { - throw BuildException('androidSdkPath is not set'); - } - if (ndkVersion == null) { - throw BuildException('androidNdkVersion is not set'); - } - if (minSdkVersion == null) { - throw BuildException('androidMinSdkVersion is not set'); - } - final env = AndroidEnvironment( - sdkPath: sdkPath, - ndkVersion: ndkVersion, - minSdkVersion: minSdkVersion, - targetTempDir: environment.targetTempDir, - target: target, - ); - if (!env.ndkIsInstalled() && environment.javaHome != null) { - env.installNdk(javaHome: environment.javaHome!); - } - return env.buildEnvironment(); - } - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'package:collection/collection.dart'; +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as path; + +import 'android_environment.dart'; +import 'cargo.dart'; +import 'environment.dart'; +import 'options.dart'; +import 'rustup.dart'; +import 'target.dart'; +import 'util.dart'; + +final _log = Logger('builder'); + +enum BuildConfiguration { + debug, + release, + profile, +} + +extension on BuildConfiguration { + bool get isDebug => this == BuildConfiguration.debug; + String get rustName => switch (this) { + BuildConfiguration.debug => 'debug', + BuildConfiguration.release => 'release', + BuildConfiguration.profile => 'release', + }; +} + +class BuildException implements Exception { + final String message; + + BuildException(this.message); + + @override + String toString() { + return 'BuildException: $message'; + } +} + +class BuildEnvironment { + final BuildConfiguration configuration; + final CargokitCrateOptions crateOptions; + final String targetTempDir; + final String manifestDir; + final CrateInfo crateInfo; + + final bool isAndroid; + final String? androidSdkPath; + final String? androidNdkVersion; + final int? androidMinSdkVersion; + final String? javaHome; + + final String? glibcVersion; + + BuildEnvironment({ + required this.configuration, + required this.crateOptions, + required this.targetTempDir, + required this.manifestDir, + required this.crateInfo, + required this.isAndroid, + this.androidSdkPath, + this.androidNdkVersion, + this.androidMinSdkVersion, + this.javaHome, + this.glibcVersion, + }); + + static BuildConfiguration parseBuildConfiguration(String value) { + // XCode configuration adds the flavor to configuration name. + final firstSegment = value.split('-').first; + final buildConfiguration = BuildConfiguration.values.firstWhereOrNull( + (e) => e.name == firstSegment, + ); + if (buildConfiguration == null) { + _log.warning('Unknown build configuraiton $value, will assume release'); + return BuildConfiguration.release; + } + return buildConfiguration; + } + + static BuildEnvironment fromEnvironment({ + required bool isAndroid, + }) { + final buildConfiguration = + parseBuildConfiguration(Environment.configuration); + final manifestDir = Environment.manifestDir; + final crateOptions = CargokitCrateOptions.load( + manifestDir: manifestDir, + ); + final crateInfo = CrateInfo.load(manifestDir); + return BuildEnvironment( + configuration: buildConfiguration, + crateOptions: crateOptions, + targetTempDir: Environment.targetTempDir, + manifestDir: manifestDir, + crateInfo: crateInfo, + isAndroid: isAndroid, + androidSdkPath: isAndroid ? Environment.sdkPath : null, + androidNdkVersion: isAndroid ? Environment.ndkVersion : null, + androidMinSdkVersion: + isAndroid ? int.parse(Environment.minSdkVersion) : null, + javaHome: isAndroid ? Environment.javaHome : null, + ); + } +} + +class RustBuilder { + final Target target; + final BuildEnvironment environment; + + RustBuilder({ + required this.target, + required this.environment, + }); + + void prepare( + Rustup rustup, + ) { + final toolchain = _toolchain; + if (rustup.installedTargets(toolchain) == null) { + rustup.installToolchain(toolchain); + } + if (toolchain == 'nightly') { + rustup.installRustSrcForNightly(); + } + if (!rustup.installedTargets(toolchain)!.contains(target.rust)) { + rustup.installTarget(target.rust, toolchain: toolchain); + } + if (environment.glibcVersion != null) { + rustup.installZigBuild(toolchain); + } + } + + CargoBuildOptions? get _buildOptions => + environment.crateOptions.cargo[environment.configuration]; + + String get _toolchain => _buildOptions?.toolchain.name ?? 'stable'; + + /// Returns the path of directory containing build artifacts. + Future build() async { + final extraArgs = _buildOptions?.flags ?? []; + final manifestPath = path.join(environment.manifestDir, 'Cargo.toml'); + runCommand( + 'rustup', + [ + 'run', + _toolchain, + 'cargo', + (target.android == null && environment.glibcVersion != null) + ? 'zigbuild' + : 'build', + ...extraArgs, + '--manifest-path', + manifestPath, + '-p', + environment.crateInfo.packageName, + if (!environment.configuration.isDebug) '--release', + '--target', + target.rust + + ((target.android == null && environment.glibcVersion != null) + ? '.${environment.glibcVersion!}' + : ""), + '--target-dir', + environment.targetTempDir, + ], + environment: await _buildEnvironment(), + ); + return path.join( + environment.targetTempDir, + target.rust, + environment.configuration.rustName, + ); + } + + Future> _buildEnvironment() async { + if (target.android == null) { + return {}; + } else { + final sdkPath = environment.androidSdkPath; + final ndkVersion = environment.androidNdkVersion; + final minSdkVersion = environment.androidMinSdkVersion; + if (sdkPath == null) { + throw BuildException('androidSdkPath is not set'); + } + if (ndkVersion == null) { + throw BuildException('androidNdkVersion is not set'); + } + if (minSdkVersion == null) { + throw BuildException('androidMinSdkVersion is not set'); + } + final env = AndroidEnvironment( + sdkPath: sdkPath, + ndkVersion: ndkVersion, + minSdkVersion: minSdkVersion, + targetTempDir: environment.targetTempDir, + target: target, + ); + if (!env.ndkIsInstalled() && environment.javaHome != null) { + env.installNdk(javaHome: environment.javaHome!); + } + return env.buildEnvironment(); + } + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/cargo.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/cargo.dart index 0d8958f..7d818cf 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/cargo.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/cargo.dart @@ -1,48 +1,48 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:path/path.dart' as path; -import 'package:toml/toml.dart'; - -class ManifestException { - ManifestException(this.message, {required this.fileName}); - - final String? fileName; - final String message; - - @override - String toString() { - if (fileName != null) { - return 'Failed to parse package manifest at $fileName: $message'; - } else { - return 'Failed to parse package manifest: $message'; - } - } -} - -class CrateInfo { - CrateInfo({required this.packageName}); - - final String packageName; - - static CrateInfo parseManifest(String manifest, {final String? fileName}) { - final toml = TomlDocument.parse(manifest); - final package = toml.toMap()['package']; - if (package == null) { - throw ManifestException('Missing package section', fileName: fileName); - } - final name = package['name']; - if (name == null) { - throw ManifestException('Missing package name', fileName: fileName); - } - return CrateInfo(packageName: name); - } - - static CrateInfo load(String manifestDir) { - final manifestFile = File(path.join(manifestDir, 'Cargo.toml')); - final manifest = manifestFile.readAsStringSync(); - return parseManifest(manifest, fileName: manifestFile.path); - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:path/path.dart' as path; +import 'package:toml/toml.dart'; + +class ManifestException { + ManifestException(this.message, {required this.fileName}); + + final String? fileName; + final String message; + + @override + String toString() { + if (fileName != null) { + return 'Failed to parse package manifest at $fileName: $message'; + } else { + return 'Failed to parse package manifest: $message'; + } + } +} + +class CrateInfo { + CrateInfo({required this.packageName}); + + final String packageName; + + static CrateInfo parseManifest(String manifest, {final String? fileName}) { + final toml = TomlDocument.parse(manifest); + final package = toml.toMap()['package']; + if (package == null) { + throw ManifestException('Missing package section', fileName: fileName); + } + final name = package['name']; + if (name == null) { + throw ManifestException('Missing package name', fileName: fileName); + } + return CrateInfo(packageName: name); + } + + static CrateInfo load(String manifestDir) { + final manifestFile = File(path.join(manifestDir, 'Cargo.toml')); + final manifest = manifestFile.readAsStringSync(); + return parseManifest(manifest, fileName: manifestFile.path); + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/crate_hash.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/crate_hash.dart index 0c4d88d..00d7db3 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/crate_hash.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/crate_hash.dart @@ -1,124 +1,124 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:collection/collection.dart'; -import 'package:convert/convert.dart'; -import 'package:crypto/crypto.dart'; -import 'package:path/path.dart' as path; - -class CrateHash { - /// Computes a hash uniquely identifying crate content. This takes into account - /// content all all .rs files inside the src directory, as well as Cargo.toml, - /// Cargo.lock, build.rs and cargokit.yaml. - /// - /// If [tempStorage] is provided, computed hash is stored in a file in that directory - /// and reused on subsequent calls if the crate content hasn't changed. - static String compute(String manifestDir, {String? tempStorage}) { - return CrateHash._( - manifestDir: manifestDir, - tempStorage: tempStorage, - )._compute(); - } - - CrateHash._({ - required this.manifestDir, - required this.tempStorage, - }); - - String _compute() { - final files = getFiles(); - final tempStorage = this.tempStorage; - if (tempStorage != null) { - final quickHash = _computeQuickHash(files); - final quickHashFolder = Directory(path.join(tempStorage, 'crate_hash')); - quickHashFolder.createSync(recursive: true); - final quickHashFile = File(path.join(quickHashFolder.path, quickHash)); - if (quickHashFile.existsSync()) { - return quickHashFile.readAsStringSync(); - } - final hash = _computeHash(files); - quickHashFile.writeAsStringSync(hash); - return hash; - } else { - return _computeHash(files); - } - } - - /// Computes a quick hash based on files stat (without reading contents). This - /// is used to cache the real hash, which is slower to compute since it involves - /// reading every single file. - String _computeQuickHash(List files) { - final output = AccumulatorSink(); - final input = sha256.startChunkedConversion(output); - - final data = ByteData(8); - for (final file in files) { - input.add(utf8.encode(file.path)); - final stat = file.statSync(); - data.setUint64(0, stat.size); - input.add(data.buffer.asUint8List()); - data.setUint64(0, stat.modified.millisecondsSinceEpoch); - input.add(data.buffer.asUint8List()); - } - - input.close(); - return base64Url.encode(output.events.single.bytes); - } - - String _computeHash(List files) { - final output = AccumulatorSink(); - final input = sha256.startChunkedConversion(output); - - void addTextFile(File file) { - // text Files are hashed by lines in case we're dealing with github checkout - // that auto-converts line endings. - final splitter = LineSplitter(); - if (file.existsSync()) { - final data = file.readAsStringSync(); - final lines = splitter.convert(data); - for (final line in lines) { - input.add(utf8.encode(line)); - } - } - } - - for (final file in files) { - addTextFile(file); - } - - input.close(); - final res = output.events.single; - - // Truncate to 128bits. - final hash = res.bytes.sublist(0, 16); - return hex.encode(hash); - } - - List getFiles() { - final src = Directory(path.join(manifestDir, 'src')); - final files = src - .listSync(recursive: true, followLinks: false) - .whereType() - .toList(); - files.sortBy((element) => element.path); - void addFile(String relative) { - final file = File(path.join(manifestDir, relative)); - if (file.existsSync()) { - files.add(file); - } - } - - addFile('Cargo.toml'); - addFile('Cargo.lock'); - addFile('build.rs'); - addFile('cargokit.yaml'); - return files; - } - - final String manifestDir; - final String? tempStorage; -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:collection/collection.dart'; +import 'package:convert/convert.dart'; +import 'package:crypto/crypto.dart'; +import 'package:path/path.dart' as path; + +class CrateHash { + /// Computes a hash uniquely identifying crate content. This takes into account + /// content all all .rs files inside the src directory, as well as Cargo.toml, + /// Cargo.lock, build.rs and cargokit.yaml. + /// + /// If [tempStorage] is provided, computed hash is stored in a file in that directory + /// and reused on subsequent calls if the crate content hasn't changed. + static String compute(String manifestDir, {String? tempStorage}) { + return CrateHash._( + manifestDir: manifestDir, + tempStorage: tempStorage, + )._compute(); + } + + CrateHash._({ + required this.manifestDir, + required this.tempStorage, + }); + + String _compute() { + final files = getFiles(); + final tempStorage = this.tempStorage; + if (tempStorage != null) { + final quickHash = _computeQuickHash(files); + final quickHashFolder = Directory(path.join(tempStorage, 'crate_hash')); + quickHashFolder.createSync(recursive: true); + final quickHashFile = File(path.join(quickHashFolder.path, quickHash)); + if (quickHashFile.existsSync()) { + return quickHashFile.readAsStringSync(); + } + final hash = _computeHash(files); + quickHashFile.writeAsStringSync(hash); + return hash; + } else { + return _computeHash(files); + } + } + + /// Computes a quick hash based on files stat (without reading contents). This + /// is used to cache the real hash, which is slower to compute since it involves + /// reading every single file. + String _computeQuickHash(List files) { + final output = AccumulatorSink(); + final input = sha256.startChunkedConversion(output); + + final data = ByteData(8); + for (final file in files) { + input.add(utf8.encode(file.path)); + final stat = file.statSync(); + data.setUint64(0, stat.size); + input.add(data.buffer.asUint8List()); + data.setUint64(0, stat.modified.millisecondsSinceEpoch); + input.add(data.buffer.asUint8List()); + } + + input.close(); + return base64Url.encode(output.events.single.bytes); + } + + String _computeHash(List files) { + final output = AccumulatorSink(); + final input = sha256.startChunkedConversion(output); + + void addTextFile(File file) { + // text Files are hashed by lines in case we're dealing with github checkout + // that auto-converts line endings. + final splitter = LineSplitter(); + if (file.existsSync()) { + final data = file.readAsStringSync(); + final lines = splitter.convert(data); + for (final line in lines) { + input.add(utf8.encode(line)); + } + } + } + + for (final file in files) { + addTextFile(file); + } + + input.close(); + final res = output.events.single; + + // Truncate to 128bits. + final hash = res.bytes.sublist(0, 16); + return hex.encode(hash); + } + + List getFiles() { + final src = Directory(path.join(manifestDir, 'src')); + final files = src + .listSync(recursive: true, followLinks: false) + .whereType() + .toList(); + files.sortBy((element) => element.path); + void addFile(String relative) { + final file = File(path.join(manifestDir, relative)); + if (file.existsSync()) { + files.add(file); + } + } + + addFile('Cargo.toml'); + addFile('Cargo.lock'); + addFile('build.rs'); + addFile('cargokit.yaml'); + return files; + } + + final String manifestDir; + final String? tempStorage; +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/environment.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/environment.dart index 996483a..0b5434e 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/environment.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/environment.dart @@ -1,68 +1,68 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -extension on String { - String resolveSymlink() => File(this).resolveSymbolicLinksSync(); -} - -class Environment { - /// Current build configuration (debug or release). - static String get configuration => - _getEnv("CARGOKIT_CONFIGURATION").toLowerCase(); - - static bool get isDebug => configuration == 'debug'; - static bool get isRelease => configuration == 'release'; - - /// Temporary directory where Rust build artifacts are placed. - static String get targetTempDir => _getEnv("CARGOKIT_TARGET_TEMP_DIR"); - - /// Final output directory where the build artifacts are placed. - static String get outputDir => _getEnvPath('CARGOKIT_OUTPUT_DIR'); - - /// Path to the crate manifest (containing Cargo.toml). - static String get manifestDir => _getEnvPath('CARGOKIT_MANIFEST_DIR'); - - /// Directory inside root project. Not necessarily root folder. Symlinks are - /// not resolved on purpose. - static String get rootProjectDir => _getEnv('CARGOKIT_ROOT_PROJECT_DIR'); - - // Pod - - /// Platform name (macosx, iphoneos, iphonesimulator). - static String get darwinPlatformName => - _getEnv("CARGOKIT_DARWIN_PLATFORM_NAME"); - - /// List of architectures to build for (arm64, armv7, x86_64). - static List get darwinArchs => - _getEnv("CARGOKIT_DARWIN_ARCHS").split(' '); - - // Gradle - static String get minSdkVersion => _getEnv("CARGOKIT_MIN_SDK_VERSION"); - static String get ndkVersion => _getEnv("CARGOKIT_NDK_VERSION"); - static String get sdkPath => _getEnvPath("CARGOKIT_SDK_DIR"); - static String get javaHome => _getEnvPath("CARGOKIT_JAVA_HOME"); - static List get targetPlatforms => - _getEnv("CARGOKIT_TARGET_PLATFORMS").split(','); - - // CMAKE - static String get targetPlatform => _getEnv("CARGOKIT_TARGET_PLATFORM"); - - static String _getEnv(String key) { - final res = Platform.environment[key]; - if (res == null) { - throw Exception("Missing environment variable $key"); - } - return res; - } - - static String _getEnvPath(String key) { - final res = _getEnv(key); - if (Directory(res).existsSync()) { - return res.resolveSymlink(); - } else { - return res; - } - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +extension on String { + String resolveSymlink() => File(this).resolveSymbolicLinksSync(); +} + +class Environment { + /// Current build configuration (debug or release). + static String get configuration => + _getEnv("CARGOKIT_CONFIGURATION").toLowerCase(); + + static bool get isDebug => configuration == 'debug'; + static bool get isRelease => configuration == 'release'; + + /// Temporary directory where Rust build artifacts are placed. + static String get targetTempDir => _getEnv("CARGOKIT_TARGET_TEMP_DIR"); + + /// Final output directory where the build artifacts are placed. + static String get outputDir => _getEnvPath('CARGOKIT_OUTPUT_DIR'); + + /// Path to the crate manifest (containing Cargo.toml). + static String get manifestDir => _getEnvPath('CARGOKIT_MANIFEST_DIR'); + + /// Directory inside root project. Not necessarily root folder. Symlinks are + /// not resolved on purpose. + static String get rootProjectDir => _getEnv('CARGOKIT_ROOT_PROJECT_DIR'); + + // Pod + + /// Platform name (macosx, iphoneos, iphonesimulator). + static String get darwinPlatformName => + _getEnv("CARGOKIT_DARWIN_PLATFORM_NAME"); + + /// List of architectures to build for (arm64, armv7, x86_64). + static List get darwinArchs => + _getEnv("CARGOKIT_DARWIN_ARCHS").split(' '); + + // Gradle + static String get minSdkVersion => _getEnv("CARGOKIT_MIN_SDK_VERSION"); + static String get ndkVersion => _getEnv("CARGOKIT_NDK_VERSION"); + static String get sdkPath => _getEnvPath("CARGOKIT_SDK_DIR"); + static String get javaHome => _getEnvPath("CARGOKIT_JAVA_HOME"); + static List get targetPlatforms => + _getEnv("CARGOKIT_TARGET_PLATFORMS").split(','); + + // CMAKE + static String get targetPlatform => _getEnv("CARGOKIT_TARGET_PLATFORM"); + + static String _getEnv(String key) { + final res = Platform.environment[key]; + if (res == null) { + throw Exception("Missing environment variable $key"); + } + return res; + } + + static String _getEnvPath(String key) { + final res = _getEnv(key); + if (Directory(res).existsSync()) { + return res.resolveSymlink(); + } else { + return res; + } + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/logging.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/logging.dart index 5edd4fd..a4d6684 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/logging.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/logging.dart @@ -1,52 +1,52 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:logging/logging.dart'; - -const String kSeparator = "--"; -const String kDoubleSeparator = "=="; - -bool _lastMessageWasSeparator = false; - -void _log(LogRecord rec) { - final prefix = '${rec.level.name}: '; - final out = rec.level == Level.SEVERE ? stderr : stdout; - if (rec.message == kSeparator) { - if (!_lastMessageWasSeparator) { - out.write(prefix); - out.writeln('-' * 80); - _lastMessageWasSeparator = true; - } - return; - } else if (rec.message == kDoubleSeparator) { - out.write(prefix); - out.writeln('=' * 80); - _lastMessageWasSeparator = true; - return; - } - out.write(prefix); - out.writeln(rec.message); - _lastMessageWasSeparator = false; -} - -void initLogging() { - Logger.root.level = Level.INFO; - Logger.root.onRecord.listen((LogRecord rec) { - final lines = rec.message.split('\n'); - for (final line in lines) { - if (line.isNotEmpty || lines.length == 1 || line != lines.last) { - _log(LogRecord( - rec.level, - line, - rec.loggerName, - )); - } - } - }); -} - -void enableVerboseLogging() { - Logger.root.level = Level.ALL; -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:logging/logging.dart'; + +const String kSeparator = "--"; +const String kDoubleSeparator = "=="; + +bool _lastMessageWasSeparator = false; + +void _log(LogRecord rec) { + final prefix = '${rec.level.name}: '; + final out = rec.level == Level.SEVERE ? stderr : stdout; + if (rec.message == kSeparator) { + if (!_lastMessageWasSeparator) { + out.write(prefix); + out.writeln('-' * 80); + _lastMessageWasSeparator = true; + } + return; + } else if (rec.message == kDoubleSeparator) { + out.write(prefix); + out.writeln('=' * 80); + _lastMessageWasSeparator = true; + return; + } + out.write(prefix); + out.writeln(rec.message); + _lastMessageWasSeparator = false; +} + +void initLogging() { + Logger.root.level = Level.INFO; + Logger.root.onRecord.listen((LogRecord rec) { + final lines = rec.message.split('\n'); + for (final line in lines) { + if (line.isNotEmpty || lines.length == 1 || line != lines.last) { + _log(LogRecord( + rec.level, + line, + rec.loggerName, + )); + } + } + }); +} + +void enableVerboseLogging() { + Logger.root.level = Level.ALL; +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/options.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/options.dart index 22aef1d..cdb7b7d 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/options.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/options.dart @@ -1,309 +1,309 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:collection/collection.dart'; -import 'package:ed25519_edwards/ed25519_edwards.dart'; -import 'package:hex/hex.dart'; -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as path; -import 'package:source_span/source_span.dart'; -import 'package:yaml/yaml.dart'; - -import 'builder.dart'; -import 'environment.dart'; -import 'rustup.dart'; - -final _log = Logger('options'); - -/// A class for exceptions that have source span information attached. -class SourceSpanException implements Exception { - // This is a getter so that subclasses can override it. - /// A message describing the exception. - String get message => _message; - final String _message; - - // This is a getter so that subclasses can override it. - /// The span associated with this exception. - /// - /// This may be `null` if the source location can't be determined. - SourceSpan? get span => _span; - final SourceSpan? _span; - - SourceSpanException(this._message, this._span); - - /// Returns a string representation of `this`. - /// - /// [color] may either be a [String], a [bool], or `null`. If it's a string, - /// it indicates an ANSI terminal color escape that should be used to - /// highlight the span's text. If it's `true`, it indicates that the text - /// should be highlighted using the default color. If it's `false` or `null`, - /// it indicates that the text shouldn't be highlighted. - @override - String toString({Object? color}) { - if (span == null) return message; - return 'Error on ${span!.message(message, color: color)}'; - } -} - -enum Toolchain { - stable, - beta, - nightly, -} - -class CargoBuildOptions { - final Toolchain toolchain; - final List flags; - - CargoBuildOptions({ - required this.toolchain, - required this.flags, - }); - - static Toolchain _toolchainFromNode(YamlNode node) { - if (node case YamlScalar(value: String name)) { - final toolchain = - Toolchain.values.firstWhereOrNull((element) => element.name == name); - if (toolchain != null) { - return toolchain; - } - } - throw SourceSpanException( - 'Unknown toolchain. Must be one of ${Toolchain.values.map((e) => e.name)}.', - node.span); - } - - static CargoBuildOptions parse(YamlNode node) { - if (node is! YamlMap) { - throw SourceSpanException('Cargo options must be a map', node.span); - } - Toolchain toolchain = Toolchain.stable; - List flags = []; - for (final MapEntry(:key, :value) in node.nodes.entries) { - if (key case YamlScalar(value: 'toolchain')) { - toolchain = _toolchainFromNode(value); - } else if (key case YamlScalar(value: 'extra_flags')) { - if (value case YamlList(nodes: List list)) { - if (list.every((element) { - if (element case YamlScalar(value: String _)) { - return true; - } - return false; - })) { - flags = list.map((e) => e.value as String).toList(); - continue; - } - } - throw SourceSpanException( - 'Extra flags must be a list of strings', value.span); - } else { - throw SourceSpanException( - 'Unknown cargo option type. Must be "toolchain" or "extra_flags".', - key.span); - } - } - return CargoBuildOptions(toolchain: toolchain, flags: flags); - } -} - -extension on YamlMap { - /// Map that extracts keys so that we can do map case check on them. - Map get valueMap => - nodes.map((key, value) => MapEntry(key.value, value)); -} - -class PrecompiledBinaries { - final String uriPrefix; - final PublicKey publicKey; - - PrecompiledBinaries({ - required this.uriPrefix, - required this.publicKey, - }); - - static PublicKey _publicKeyFromHex(String key, SourceSpan? span) { - final bytes = HEX.decode(key); - if (bytes.length != 32) { - throw SourceSpanException( - 'Invalid public key. Must be 32 bytes long.', span); - } - return PublicKey(bytes); - } - - static PrecompiledBinaries parse(YamlNode node) { - if (node case YamlMap(valueMap: Map map)) { - if (map - case { - 'url_prefix': YamlNode urlPrefixNode, - 'public_key': YamlNode publicKeyNode, - }) { - final urlPrefix = switch (urlPrefixNode) { - YamlScalar(value: String urlPrefix) => urlPrefix, - _ => throw SourceSpanException( - 'Invalid URL prefix value.', urlPrefixNode.span), - }; - final publicKey = switch (publicKeyNode) { - YamlScalar(value: String publicKey) => - _publicKeyFromHex(publicKey, publicKeyNode.span), - _ => throw SourceSpanException( - 'Invalid public key value.', publicKeyNode.span), - }; - return PrecompiledBinaries( - uriPrefix: urlPrefix, - publicKey: publicKey, - ); - } - } - throw SourceSpanException( - 'Invalid precompiled binaries value. ' - 'Expected Map with "url_prefix" and "public_key".', - node.span); - } -} - -/// Cargokit options specified for Rust crate. -class CargokitCrateOptions { - CargokitCrateOptions({ - this.cargo = const {}, - this.precompiledBinaries, - }); - - final Map cargo; - final PrecompiledBinaries? precompiledBinaries; - - static CargokitCrateOptions parse(YamlNode node) { - if (node is! YamlMap) { - throw SourceSpanException('Cargokit options must be a map', node.span); - } - final options = {}; - PrecompiledBinaries? precompiledBinaries; - - for (final entry in node.nodes.entries) { - if (entry - case MapEntry( - key: YamlScalar(value: 'cargo'), - value: YamlNode node, - )) { - if (node is! YamlMap) { - throw SourceSpanException('Cargo options must be a map', node.span); - } - for (final MapEntry(:YamlNode key, :value) in node.nodes.entries) { - if (key case YamlScalar(value: String name)) { - final configuration = BuildConfiguration.values - .firstWhereOrNull((element) => element.name == name); - if (configuration != null) { - options[configuration] = CargoBuildOptions.parse(value); - continue; - } - } - throw SourceSpanException( - 'Unknown build configuration. Must be one of ${BuildConfiguration.values.map((e) => e.name)}.', - key.span); - } - } else if (entry.key case YamlScalar(value: 'precompiled_binaries')) { - precompiledBinaries = PrecompiledBinaries.parse(entry.value); - } else { - throw SourceSpanException( - 'Unknown cargokit option type. Must be "cargo" or "precompiled_binaries".', - entry.key.span); - } - } - return CargokitCrateOptions( - cargo: options, - precompiledBinaries: precompiledBinaries, - ); - } - - static CargokitCrateOptions load({ - required String manifestDir, - }) { - final uri = Uri.file(path.join(manifestDir, "cargokit.yaml")); - final file = File.fromUri(uri); - if (file.existsSync()) { - final contents = loadYamlNode(file.readAsStringSync(), sourceUrl: uri); - return parse(contents); - } else { - return CargokitCrateOptions(); - } - } -} - -class CargokitUserOptions { - // When Rustup is installed always build locally unless user opts into - // using precompiled binaries. - static bool defaultUsePrecompiledBinaries() { - return Rustup.executablePath() == null; - } - - CargokitUserOptions({ - required this.usePrecompiledBinaries, - required this.verboseLogging, - }); - - CargokitUserOptions._() - : usePrecompiledBinaries = defaultUsePrecompiledBinaries(), - verboseLogging = false; - - static CargokitUserOptions parse(YamlNode node) { - if (node is! YamlMap) { - throw SourceSpanException('Cargokit options must be a map', node.span); - } - bool usePrecompiledBinaries = defaultUsePrecompiledBinaries(); - bool verboseLogging = false; - - for (final entry in node.nodes.entries) { - if (entry.key case YamlScalar(value: 'use_precompiled_binaries')) { - if (entry.value case YamlScalar(value: bool value)) { - usePrecompiledBinaries = value; - continue; - } - throw SourceSpanException( - 'Invalid value for "use_precompiled_binaries". Must be a boolean.', - entry.value.span); - } else if (entry.key case YamlScalar(value: 'verbose_logging')) { - if (entry.value case YamlScalar(value: bool value)) { - verboseLogging = value; - continue; - } - throw SourceSpanException( - 'Invalid value for "verbose_logging". Must be a boolean.', - entry.value.span); - } else { - throw SourceSpanException( - 'Unknown cargokit option type. Must be "use_precompiled_binaries" or "verbose_logging".', - entry.key.span); - } - } - return CargokitUserOptions( - usePrecompiledBinaries: usePrecompiledBinaries, - verboseLogging: verboseLogging, - ); - } - - static CargokitUserOptions load() { - String fileName = "cargokit_options.yaml"; - var userProjectDir = Directory(Environment.rootProjectDir); - - while (userProjectDir.parent.path != userProjectDir.path) { - final configFile = File(path.join(userProjectDir.path, fileName)); - if (configFile.existsSync()) { - final contents = loadYamlNode( - configFile.readAsStringSync(), - sourceUrl: configFile.uri, - ); - final res = parse(contents); - if (res.verboseLogging) { - _log.info('Found user options file at ${configFile.path}'); - } - return res; - } - userProjectDir = userProjectDir.parent; - } - return CargokitUserOptions._(); - } - - final bool usePrecompiledBinaries; - final bool verboseLogging; -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:collection/collection.dart'; +import 'package:ed25519_edwards/ed25519_edwards.dart'; +import 'package:hex/hex.dart'; +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as path; +import 'package:source_span/source_span.dart'; +import 'package:yaml/yaml.dart'; + +import 'builder.dart'; +import 'environment.dart'; +import 'rustup.dart'; + +final _log = Logger('options'); + +/// A class for exceptions that have source span information attached. +class SourceSpanException implements Exception { + // This is a getter so that subclasses can override it. + /// A message describing the exception. + String get message => _message; + final String _message; + + // This is a getter so that subclasses can override it. + /// The span associated with this exception. + /// + /// This may be `null` if the source location can't be determined. + SourceSpan? get span => _span; + final SourceSpan? _span; + + SourceSpanException(this._message, this._span); + + /// Returns a string representation of `this`. + /// + /// [color] may either be a [String], a [bool], or `null`. If it's a string, + /// it indicates an ANSI terminal color escape that should be used to + /// highlight the span's text. If it's `true`, it indicates that the text + /// should be highlighted using the default color. If it's `false` or `null`, + /// it indicates that the text shouldn't be highlighted. + @override + String toString({Object? color}) { + if (span == null) return message; + return 'Error on ${span!.message(message, color: color)}'; + } +} + +enum Toolchain { + stable, + beta, + nightly, +} + +class CargoBuildOptions { + final Toolchain toolchain; + final List flags; + + CargoBuildOptions({ + required this.toolchain, + required this.flags, + }); + + static Toolchain _toolchainFromNode(YamlNode node) { + if (node case YamlScalar(value: String name)) { + final toolchain = + Toolchain.values.firstWhereOrNull((element) => element.name == name); + if (toolchain != null) { + return toolchain; + } + } + throw SourceSpanException( + 'Unknown toolchain. Must be one of ${Toolchain.values.map((e) => e.name)}.', + node.span); + } + + static CargoBuildOptions parse(YamlNode node) { + if (node is! YamlMap) { + throw SourceSpanException('Cargo options must be a map', node.span); + } + Toolchain toolchain = Toolchain.stable; + List flags = []; + for (final MapEntry(:key, :value) in node.nodes.entries) { + if (key case YamlScalar(value: 'toolchain')) { + toolchain = _toolchainFromNode(value); + } else if (key case YamlScalar(value: 'extra_flags')) { + if (value case YamlList(nodes: List list)) { + if (list.every((element) { + if (element case YamlScalar(value: String _)) { + return true; + } + return false; + })) { + flags = list.map((e) => e.value as String).toList(); + continue; + } + } + throw SourceSpanException( + 'Extra flags must be a list of strings', value.span); + } else { + throw SourceSpanException( + 'Unknown cargo option type. Must be "toolchain" or "extra_flags".', + key.span); + } + } + return CargoBuildOptions(toolchain: toolchain, flags: flags); + } +} + +extension on YamlMap { + /// Map that extracts keys so that we can do map case check on them. + Map get valueMap => + nodes.map((key, value) => MapEntry(key.value, value)); +} + +class PrecompiledBinaries { + final String uriPrefix; + final PublicKey publicKey; + + PrecompiledBinaries({ + required this.uriPrefix, + required this.publicKey, + }); + + static PublicKey _publicKeyFromHex(String key, SourceSpan? span) { + final bytes = HEX.decode(key); + if (bytes.length != 32) { + throw SourceSpanException( + 'Invalid public key. Must be 32 bytes long.', span); + } + return PublicKey(bytes); + } + + static PrecompiledBinaries parse(YamlNode node) { + if (node case YamlMap(valueMap: Map map)) { + if (map + case { + 'url_prefix': YamlNode urlPrefixNode, + 'public_key': YamlNode publicKeyNode, + }) { + final urlPrefix = switch (urlPrefixNode) { + YamlScalar(value: String urlPrefix) => urlPrefix, + _ => throw SourceSpanException( + 'Invalid URL prefix value.', urlPrefixNode.span), + }; + final publicKey = switch (publicKeyNode) { + YamlScalar(value: String publicKey) => + _publicKeyFromHex(publicKey, publicKeyNode.span), + _ => throw SourceSpanException( + 'Invalid public key value.', publicKeyNode.span), + }; + return PrecompiledBinaries( + uriPrefix: urlPrefix, + publicKey: publicKey, + ); + } + } + throw SourceSpanException( + 'Invalid precompiled binaries value. ' + 'Expected Map with "url_prefix" and "public_key".', + node.span); + } +} + +/// Cargokit options specified for Rust crate. +class CargokitCrateOptions { + CargokitCrateOptions({ + this.cargo = const {}, + this.precompiledBinaries, + }); + + final Map cargo; + final PrecompiledBinaries? precompiledBinaries; + + static CargokitCrateOptions parse(YamlNode node) { + if (node is! YamlMap) { + throw SourceSpanException('Cargokit options must be a map', node.span); + } + final options = {}; + PrecompiledBinaries? precompiledBinaries; + + for (final entry in node.nodes.entries) { + if (entry + case MapEntry( + key: YamlScalar(value: 'cargo'), + value: YamlNode node, + )) { + if (node is! YamlMap) { + throw SourceSpanException('Cargo options must be a map', node.span); + } + for (final MapEntry(:YamlNode key, :value) in node.nodes.entries) { + if (key case YamlScalar(value: String name)) { + final configuration = BuildConfiguration.values + .firstWhereOrNull((element) => element.name == name); + if (configuration != null) { + options[configuration] = CargoBuildOptions.parse(value); + continue; + } + } + throw SourceSpanException( + 'Unknown build configuration. Must be one of ${BuildConfiguration.values.map((e) => e.name)}.', + key.span); + } + } else if (entry.key case YamlScalar(value: 'precompiled_binaries')) { + precompiledBinaries = PrecompiledBinaries.parse(entry.value); + } else { + throw SourceSpanException( + 'Unknown cargokit option type. Must be "cargo" or "precompiled_binaries".', + entry.key.span); + } + } + return CargokitCrateOptions( + cargo: options, + precompiledBinaries: precompiledBinaries, + ); + } + + static CargokitCrateOptions load({ + required String manifestDir, + }) { + final uri = Uri.file(path.join(manifestDir, "cargokit.yaml")); + final file = File.fromUri(uri); + if (file.existsSync()) { + final contents = loadYamlNode(file.readAsStringSync(), sourceUrl: uri); + return parse(contents); + } else { + return CargokitCrateOptions(); + } + } +} + +class CargokitUserOptions { + // When Rustup is installed always build locally unless user opts into + // using precompiled binaries. + static bool defaultUsePrecompiledBinaries() { + return Rustup.executablePath() == null; + } + + CargokitUserOptions({ + required this.usePrecompiledBinaries, + required this.verboseLogging, + }); + + CargokitUserOptions._() + : usePrecompiledBinaries = defaultUsePrecompiledBinaries(), + verboseLogging = false; + + static CargokitUserOptions parse(YamlNode node) { + if (node is! YamlMap) { + throw SourceSpanException('Cargokit options must be a map', node.span); + } + bool usePrecompiledBinaries = defaultUsePrecompiledBinaries(); + bool verboseLogging = false; + + for (final entry in node.nodes.entries) { + if (entry.key case YamlScalar(value: 'use_precompiled_binaries')) { + if (entry.value case YamlScalar(value: bool value)) { + usePrecompiledBinaries = value; + continue; + } + throw SourceSpanException( + 'Invalid value for "use_precompiled_binaries". Must be a boolean.', + entry.value.span); + } else if (entry.key case YamlScalar(value: 'verbose_logging')) { + if (entry.value case YamlScalar(value: bool value)) { + verboseLogging = value; + continue; + } + throw SourceSpanException( + 'Invalid value for "verbose_logging". Must be a boolean.', + entry.value.span); + } else { + throw SourceSpanException( + 'Unknown cargokit option type. Must be "use_precompiled_binaries" or "verbose_logging".', + entry.key.span); + } + } + return CargokitUserOptions( + usePrecompiledBinaries: usePrecompiledBinaries, + verboseLogging: verboseLogging, + ); + } + + static CargokitUserOptions load() { + String fileName = "cargokit_options.yaml"; + var userProjectDir = Directory(Environment.rootProjectDir); + + while (userProjectDir.parent.path != userProjectDir.path) { + final configFile = File(path.join(userProjectDir.path, fileName)); + if (configFile.existsSync()) { + final contents = loadYamlNode( + configFile.readAsStringSync(), + sourceUrl: configFile.uri, + ); + final res = parse(contents); + if (res.verboseLogging) { + _log.info('Found user options file at ${configFile.path}'); + } + return res; + } + userProjectDir = userProjectDir.parent; + } + return CargokitUserOptions._(); + } + + final bool usePrecompiledBinaries; + final bool verboseLogging; +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/precompile_binaries.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/precompile_binaries.dart index 019859c..807c56e 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/precompile_binaries.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/precompile_binaries.dart @@ -1,205 +1,205 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:ed25519_edwards/ed25519_edwards.dart'; -import 'package:github/github.dart'; -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as path; - -import 'artifacts_provider.dart'; -import 'builder.dart'; -import 'cargo.dart'; -import 'crate_hash.dart'; -import 'options.dart'; -import 'rustup.dart'; -import 'target.dart'; - -final _log = Logger('precompile_binaries'); - -class PrecompileBinaries { - PrecompileBinaries({ - required this.privateKey, - required this.githubToken, - required this.repositorySlug, - required this.manifestDir, - required this.targets, - this.androidSdkLocation, - this.androidNdkVersion, - this.androidMinSdkVersion, - this.tempDir, - this.glibcVersion, - }); - - final PrivateKey privateKey; - final String githubToken; - final RepositorySlug repositorySlug; - final String manifestDir; - final List targets; - final String? androidSdkLocation; - final String? androidNdkVersion; - final int? androidMinSdkVersion; - final String? tempDir; - final String? glibcVersion; - - static String fileName(Target target, String name) { - return '${target.rust}_$name'; - } - - static String signatureFileName(Target target, String name) { - return '${target.rust}_$name.sig'; - } - - Future run() async { - final crateInfo = CrateInfo.load(manifestDir); - - final targets = List.of(this.targets); - if (targets.isEmpty) { - targets.addAll([ - ...Target.buildableTargets(), - if (androidSdkLocation != null) ...Target.androidTargets(), - ]); - } - - _log.info('Precompiling binaries for $targets'); - - final hash = CrateHash.compute(manifestDir); - _log.info('Computed crate hash: $hash'); - - final String tagName = 'precompiled_$hash'; - - final github = GitHub(auth: Authentication.withToken(githubToken)); - final repo = github.repositories; - final release = await _getOrCreateRelease( - repo: repo, - tagName: tagName, - packageName: crateInfo.packageName, - hash: hash, - ); - - final tempDir = this.tempDir != null - ? Directory(this.tempDir!) - : Directory.systemTemp.createTempSync('precompiled_'); - - tempDir.createSync(recursive: true); - - final crateOptions = CargokitCrateOptions.load( - manifestDir: manifestDir, - ); - - final buildEnvironment = BuildEnvironment( - configuration: BuildConfiguration.release, - crateOptions: crateOptions, - targetTempDir: tempDir.path, - manifestDir: manifestDir, - crateInfo: crateInfo, - isAndroid: androidSdkLocation != null, - androidSdkPath: androidSdkLocation, - androidNdkVersion: androidNdkVersion, - androidMinSdkVersion: androidMinSdkVersion, - glibcVersion: glibcVersion, - ); - - final rustup = Rustup(); - - for (final target in targets) { - final artifactNames = getArtifactNames( - target: target, - libraryName: crateInfo.packageName, - remote: true, - ); - - if (artifactNames.every((name) { - final fileName = PrecompileBinaries.fileName(target, name); - return (release.assets ?? []).any((e) => e.name == fileName); - })) { - _log.info("All artifacts for $target already exist - skipping"); - continue; - } - - _log.info('Building for $target'); - - final builder = - RustBuilder(target: target, environment: buildEnvironment); - builder.prepare(rustup); - final res = await builder.build(); - - final assets = []; - for (final name in artifactNames) { - final file = File(path.join(res, name)); - if (!file.existsSync()) { - throw Exception('Missing artifact: ${file.path}'); - } - - final data = file.readAsBytesSync(); - final create = CreateReleaseAsset( - name: PrecompileBinaries.fileName(target, name), - contentType: "application/octet-stream", - assetData: data, - ); - final signature = sign(privateKey, data); - final signatureCreate = CreateReleaseAsset( - name: signatureFileName(target, name), - contentType: "application/octet-stream", - assetData: signature, - ); - bool verified = verify(public(privateKey), data, signature); - if (!verified) { - throw Exception('Signature verification failed'); - } - assets.add(create); - assets.add(signatureCreate); - } - _log.info('Uploading assets: ${assets.map((e) => e.name)}'); - for (final asset in assets) { - // This seems to be failing on CI so do it one by one - int retryCount = 0; - while (true) { - try { - await repo.uploadReleaseAssets(release, [asset]); - break; - } on Exception catch (e) { - if (retryCount == 10) { - rethrow; - } - ++retryCount; - _log.shout( - 'Upload failed (attempt $retryCount, will retry): ${e.toString()}'); - await Future.delayed(Duration(seconds: 2)); - } - } - } - } - - _log.info('Cleaning up'); - tempDir.deleteSync(recursive: true); - } - - Future _getOrCreateRelease({ - required RepositoriesService repo, - required String tagName, - required String packageName, - required String hash, - }) async { - Release release; - try { - _log.info('Fetching release $tagName'); - release = await repo.getReleaseByTagName(repositorySlug, tagName); - } on ReleaseNotFound { - _log.info('Release not found - creating release $tagName'); - release = await repo.createRelease( - repositorySlug, - CreateRelease.from( - tagName: tagName, - name: 'Precompiled binaries ${hash.substring(0, 8)}', - targetCommitish: null, - isDraft: false, - isPrerelease: false, - body: 'Precompiled binaries for crate $packageName, ' - 'crate hash $hash.', - )); - } - return release; - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:ed25519_edwards/ed25519_edwards.dart'; +import 'package:github/github.dart'; +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as path; + +import 'artifacts_provider.dart'; +import 'builder.dart'; +import 'cargo.dart'; +import 'crate_hash.dart'; +import 'options.dart'; +import 'rustup.dart'; +import 'target.dart'; + +final _log = Logger('precompile_binaries'); + +class PrecompileBinaries { + PrecompileBinaries({ + required this.privateKey, + required this.githubToken, + required this.repositorySlug, + required this.manifestDir, + required this.targets, + this.androidSdkLocation, + this.androidNdkVersion, + this.androidMinSdkVersion, + this.tempDir, + this.glibcVersion, + }); + + final PrivateKey privateKey; + final String githubToken; + final RepositorySlug repositorySlug; + final String manifestDir; + final List targets; + final String? androidSdkLocation; + final String? androidNdkVersion; + final int? androidMinSdkVersion; + final String? tempDir; + final String? glibcVersion; + + static String fileName(Target target, String name) { + return '${target.rust}_$name'; + } + + static String signatureFileName(Target target, String name) { + return '${target.rust}_$name.sig'; + } + + Future run() async { + final crateInfo = CrateInfo.load(manifestDir); + + final targets = List.of(this.targets); + if (targets.isEmpty) { + targets.addAll([ + ...Target.buildableTargets(), + if (androidSdkLocation != null) ...Target.androidTargets(), + ]); + } + + _log.info('Precompiling binaries for $targets'); + + final hash = CrateHash.compute(manifestDir); + _log.info('Computed crate hash: $hash'); + + final String tagName = 'precompiled_$hash'; + + final github = GitHub(auth: Authentication.withToken(githubToken)); + final repo = github.repositories; + final release = await _getOrCreateRelease( + repo: repo, + tagName: tagName, + packageName: crateInfo.packageName, + hash: hash, + ); + + final tempDir = this.tempDir != null + ? Directory(this.tempDir!) + : Directory.systemTemp.createTempSync('precompiled_'); + + tempDir.createSync(recursive: true); + + final crateOptions = CargokitCrateOptions.load( + manifestDir: manifestDir, + ); + + final buildEnvironment = BuildEnvironment( + configuration: BuildConfiguration.release, + crateOptions: crateOptions, + targetTempDir: tempDir.path, + manifestDir: manifestDir, + crateInfo: crateInfo, + isAndroid: androidSdkLocation != null, + androidSdkPath: androidSdkLocation, + androidNdkVersion: androidNdkVersion, + androidMinSdkVersion: androidMinSdkVersion, + glibcVersion: glibcVersion, + ); + + final rustup = Rustup(); + + for (final target in targets) { + final artifactNames = getArtifactNames( + target: target, + libraryName: crateInfo.packageName, + remote: true, + ); + + if (artifactNames.every((name) { + final fileName = PrecompileBinaries.fileName(target, name); + return (release.assets ?? []).any((e) => e.name == fileName); + })) { + _log.info("All artifacts for $target already exist - skipping"); + continue; + } + + _log.info('Building for $target'); + + final builder = + RustBuilder(target: target, environment: buildEnvironment); + builder.prepare(rustup); + final res = await builder.build(); + + final assets = []; + for (final name in artifactNames) { + final file = File(path.join(res, name)); + if (!file.existsSync()) { + throw Exception('Missing artifact: ${file.path}'); + } + + final data = file.readAsBytesSync(); + final create = CreateReleaseAsset( + name: PrecompileBinaries.fileName(target, name), + contentType: "application/octet-stream", + assetData: data, + ); + final signature = sign(privateKey, data); + final signatureCreate = CreateReleaseAsset( + name: signatureFileName(target, name), + contentType: "application/octet-stream", + assetData: signature, + ); + bool verified = verify(public(privateKey), data, signature); + if (!verified) { + throw Exception('Signature verification failed'); + } + assets.add(create); + assets.add(signatureCreate); + } + _log.info('Uploading assets: ${assets.map((e) => e.name)}'); + for (final asset in assets) { + // This seems to be failing on CI so do it one by one + int retryCount = 0; + while (true) { + try { + await repo.uploadReleaseAssets(release, [asset]); + break; + } on Exception catch (e) { + if (retryCount == 10) { + rethrow; + } + ++retryCount; + _log.shout( + 'Upload failed (attempt $retryCount, will retry): ${e.toString()}'); + await Future.delayed(Duration(seconds: 2)); + } + } + } + } + + _log.info('Cleaning up'); + tempDir.deleteSync(recursive: true); + } + + Future _getOrCreateRelease({ + required RepositoriesService repo, + required String tagName, + required String packageName, + required String hash, + }) async { + Release release; + try { + _log.info('Fetching release $tagName'); + release = await repo.getReleaseByTagName(repositorySlug, tagName); + } on ReleaseNotFound { + _log.info('Release not found - creating release $tagName'); + release = await repo.createRelease( + repositorySlug, + CreateRelease.from( + tagName: tagName, + name: 'Precompiled binaries ${hash.substring(0, 8)}', + targetCommitish: null, + isDraft: false, + isPrerelease: false, + body: 'Precompiled binaries for crate $packageName, ' + 'crate hash $hash.', + )); + } + return release; + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/rustup.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/rustup.dart index e46722b..168328b 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/rustup.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/rustup.dart @@ -1,149 +1,149 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:collection/collection.dart'; -import 'package:path/path.dart' as path; - -import 'util.dart'; - -class _Toolchain { - _Toolchain( - this.name, - this.targets, - ); - - final String name; - final List targets; -} - -class Rustup { - List? installedTargets(String toolchain) { - final targets = _installedTargets(toolchain); - return targets != null ? List.unmodifiable(targets) : null; - } - - void installToolchain(String toolchain) { - log.info("Installing Rust toolchain: $toolchain"); - runCommand("rustup", ['toolchain', 'install', toolchain]); - _installedToolchains - .add(_Toolchain(toolchain, _getInstalledTargets(toolchain))); - } - - void installTarget( - String target, { - required String toolchain, - }) { - log.info("Installing Rust target: $target"); - runCommand("rustup", ['target', 'add', '--toolchain', toolchain, target]); - _installedTargets(toolchain)?.add(target); - } - - bool _didInstallZigBuild = false; - - void installZigBuild(String toolchain) { - if (_didInstallZigBuild) { - return; - } - - log.info("Installing Zig build"); - runCommand("rustup", [ - 'run', - toolchain, - 'cargo', - 'install', - '--locked', - 'cargo-zigbuild', - ]); - _didInstallZigBuild = true; - } - - final List<_Toolchain> _installedToolchains; - - Rustup() : _installedToolchains = _getInstalledToolchains(); - - List? _installedTargets(String toolchain) => _installedToolchains - .firstWhereOrNull( - (e) => e.name == toolchain || e.name.startsWith('$toolchain-')) - ?.targets; - - static List<_Toolchain> _getInstalledToolchains() { - String extractToolchainName(String line) { - // ignore (default) after toolchain name - final parts = line.split(' '); - return parts[0]; - } - - final res = runCommand("rustup", ['toolchain', 'list']); - - // To list all non-custom toolchains, we need to filter out lines that - // don't start with "stable", "beta", or "nightly". - Pattern nonCustom = RegExp(r"^(stable|beta|nightly)"); - final lines = res.stdout - .toString() - .split('\n') - .where((e) => e.isNotEmpty && e.startsWith(nonCustom)) - .map(extractToolchainName) - .toList(growable: true); - - return lines - .map( - (name) => _Toolchain( - name, - _getInstalledTargets(name), - ), - ) - .toList(growable: true); - } - - static List _getInstalledTargets(String toolchain) { - final res = runCommand("rustup", [ - 'target', - 'list', - '--toolchain', - toolchain, - '--installed', - ]); - final lines = res.stdout - .toString() - .split('\n') - .where((e) => e.isNotEmpty) - .toList(growable: true); - return lines; - } - - bool _didInstallRustSrcForNightly = false; - - void installRustSrcForNightly() { - if (_didInstallRustSrcForNightly) { - return; - } - // Useful for -Z build-std - runCommand( - "rustup", - ['component', 'add', 'rust-src', '--toolchain', 'nightly'], - ); - _didInstallRustSrcForNightly = true; - } - - static String? executablePath() { - final envPath = Platform.environment['PATH']; - final envPathSeparator = Platform.isWindows ? ';' : ':'; - final home = Platform.isWindows - ? Platform.environment['USERPROFILE'] - : Platform.environment['HOME']; - final paths = [ - if (home != null) path.join(home, '.cargo', 'bin'), - if (envPath != null) ...envPath.split(envPathSeparator), - ]; - for (final p in paths) { - final rustup = Platform.isWindows ? 'rustup.exe' : 'rustup'; - final rustupPath = path.join(p, rustup); - if (File(rustupPath).existsSync()) { - return rustupPath; - } - } - return null; - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:collection/collection.dart'; +import 'package:path/path.dart' as path; + +import 'util.dart'; + +class _Toolchain { + _Toolchain( + this.name, + this.targets, + ); + + final String name; + final List targets; +} + +class Rustup { + List? installedTargets(String toolchain) { + final targets = _installedTargets(toolchain); + return targets != null ? List.unmodifiable(targets) : null; + } + + void installToolchain(String toolchain) { + log.info("Installing Rust toolchain: $toolchain"); + runCommand("rustup", ['toolchain', 'install', toolchain]); + _installedToolchains + .add(_Toolchain(toolchain, _getInstalledTargets(toolchain))); + } + + void installTarget( + String target, { + required String toolchain, + }) { + log.info("Installing Rust target: $target"); + runCommand("rustup", ['target', 'add', '--toolchain', toolchain, target]); + _installedTargets(toolchain)?.add(target); + } + + bool _didInstallZigBuild = false; + + void installZigBuild(String toolchain) { + if (_didInstallZigBuild) { + return; + } + + log.info("Installing Zig build"); + runCommand("rustup", [ + 'run', + toolchain, + 'cargo', + 'install', + '--locked', + 'cargo-zigbuild', + ]); + _didInstallZigBuild = true; + } + + final List<_Toolchain> _installedToolchains; + + Rustup() : _installedToolchains = _getInstalledToolchains(); + + List? _installedTargets(String toolchain) => _installedToolchains + .firstWhereOrNull( + (e) => e.name == toolchain || e.name.startsWith('$toolchain-')) + ?.targets; + + static List<_Toolchain> _getInstalledToolchains() { + String extractToolchainName(String line) { + // ignore (default) after toolchain name + final parts = line.split(' '); + return parts[0]; + } + + final res = runCommand("rustup", ['toolchain', 'list']); + + // To list all non-custom toolchains, we need to filter out lines that + // don't start with "stable", "beta", or "nightly". + Pattern nonCustom = RegExp(r"^(stable|beta|nightly)"); + final lines = res.stdout + .toString() + .split('\n') + .where((e) => e.isNotEmpty && e.startsWith(nonCustom)) + .map(extractToolchainName) + .toList(growable: true); + + return lines + .map( + (name) => _Toolchain( + name, + _getInstalledTargets(name), + ), + ) + .toList(growable: true); + } + + static List _getInstalledTargets(String toolchain) { + final res = runCommand("rustup", [ + 'target', + 'list', + '--toolchain', + toolchain, + '--installed', + ]); + final lines = res.stdout + .toString() + .split('\n') + .where((e) => e.isNotEmpty) + .toList(growable: true); + return lines; + } + + bool _didInstallRustSrcForNightly = false; + + void installRustSrcForNightly() { + if (_didInstallRustSrcForNightly) { + return; + } + // Useful for -Z build-std + runCommand( + "rustup", + ['component', 'add', 'rust-src', '--toolchain', 'nightly'], + ); + _didInstallRustSrcForNightly = true; + } + + static String? executablePath() { + final envPath = Platform.environment['PATH']; + final envPathSeparator = Platform.isWindows ? ';' : ':'; + final home = Platform.isWindows + ? Platform.environment['USERPROFILE'] + : Platform.environment['HOME']; + final paths = [ + if (home != null) path.join(home, '.cargo', 'bin'), + if (envPath != null) ...envPath.split(envPathSeparator), + ]; + for (final p in paths) { + final rustup = Platform.isWindows ? 'rustup.exe' : 'rustup'; + final rustupPath = path.join(p, rustup); + if (File(rustupPath).existsSync()) { + return rustupPath; + } + } + return null; + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/target.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/target.dart index 624504e..3ec9d18 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/target.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/target.dart @@ -1,147 +1,147 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:collection/collection.dart'; - -import 'util.dart'; - -class Target { - Target({ - required this.rust, - this.flutter, - this.android, - this.androidMinSdkVersion, - this.darwinPlatform, - this.darwinArch, - }); - - static final all = [ - Target( - rust: 'armv7-linux-androideabi', - flutter: 'android-arm', - android: 'armeabi-v7a', - androidMinSdkVersion: 16, - ), - Target( - rust: 'aarch64-linux-android', - flutter: 'android-arm64', - android: 'arm64-v8a', - androidMinSdkVersion: 21, - ), - Target( - rust: 'i686-linux-android', - flutter: 'android-x86', - android: 'x86', - androidMinSdkVersion: 16, - ), - Target( - rust: 'x86_64-linux-android', - flutter: 'android-x64', - android: 'x86_64', - androidMinSdkVersion: 21, - ), - Target( - rust: 'x86_64-pc-windows-msvc', - flutter: 'windows-x64', - ), - Target( - rust: 'aarch64-pc-windows-msvc', - flutter: 'windows-arm64', - ), - Target( - rust: 'x86_64-unknown-linux-gnu', - flutter: 'linux-x64', - ), - Target( - rust: 'aarch64-unknown-linux-gnu', - flutter: 'linux-arm64', - ), - Target(rust: 'riscv64gc-unknown-linux-gnu', flutter: 'linux-riscv64'), - Target( - rust: 'x86_64-apple-darwin', - darwinPlatform: 'macosx', - darwinArch: 'x86_64', - ), - Target( - rust: 'aarch64-apple-darwin', - darwinPlatform: 'macosx', - darwinArch: 'arm64', - ), - Target( - rust: 'aarch64-apple-ios', - darwinPlatform: 'iphoneos', - darwinArch: 'arm64', - ), - Target( - rust: 'aarch64-apple-ios-sim', - darwinPlatform: 'iphonesimulator', - darwinArch: 'arm64', - ), - Target( - rust: 'x86_64-apple-ios', - darwinPlatform: 'iphonesimulator', - darwinArch: 'x86_64', - ), - ]; - - static Target? forFlutterName(String flutterName) { - return all.firstWhereOrNull((element) => element.flutter == flutterName); - } - - static Target? forDarwin({ - required String platformName, - required String darwinAarch, - }) { - return all.firstWhereOrNull((element) => // - element.darwinPlatform == platformName && - element.darwinArch == darwinAarch); - } - - static Target? forRustTriple(String triple) { - return all.firstWhereOrNull((element) => element.rust == triple); - } - - static List androidTargets() { - return all - .where((element) => element.android != null) - .toList(growable: false); - } - - /// Returns buildable targets on current host platform ignoring Android targets. - static List buildableTargets() { - if (Platform.isLinux) { - // Right now we don't support cross-compiling on Linux. So we just return - // the host target. - final arch = (runCommand('arch', []).stdout as String).trim(); - if (arch == 'aarch64') { - return [Target.forRustTriple('aarch64-unknown-linux-gnu')!]; - } else if (arch == 'riscv64') { - return [Target.forRustTriple('riscv64gc-unknown-linux-gnu')!]; - } else { - return [Target.forRustTriple('x86_64-unknown-linux-gnu')!]; - } - } - return all.where((target) { - if (Platform.isWindows) { - return target.rust.contains('-windows-'); - } else if (Platform.isMacOS) { - return target.darwinPlatform != null; - } - return false; - }).toList(growable: false); - } - - @override - String toString() { - return rust; - } - - final String? flutter; - final String rust; - final String? android; - final int? androidMinSdkVersion; - final String? darwinPlatform; - final String? darwinArch; -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:collection/collection.dart'; + +import 'util.dart'; + +class Target { + Target({ + required this.rust, + this.flutter, + this.android, + this.androidMinSdkVersion, + this.darwinPlatform, + this.darwinArch, + }); + + static final all = [ + Target( + rust: 'armv7-linux-androideabi', + flutter: 'android-arm', + android: 'armeabi-v7a', + androidMinSdkVersion: 16, + ), + Target( + rust: 'aarch64-linux-android', + flutter: 'android-arm64', + android: 'arm64-v8a', + androidMinSdkVersion: 21, + ), + Target( + rust: 'i686-linux-android', + flutter: 'android-x86', + android: 'x86', + androidMinSdkVersion: 16, + ), + Target( + rust: 'x86_64-linux-android', + flutter: 'android-x64', + android: 'x86_64', + androidMinSdkVersion: 21, + ), + Target( + rust: 'x86_64-pc-windows-msvc', + flutter: 'windows-x64', + ), + Target( + rust: 'aarch64-pc-windows-msvc', + flutter: 'windows-arm64', + ), + Target( + rust: 'x86_64-unknown-linux-gnu', + flutter: 'linux-x64', + ), + Target( + rust: 'aarch64-unknown-linux-gnu', + flutter: 'linux-arm64', + ), + Target(rust: 'riscv64gc-unknown-linux-gnu', flutter: 'linux-riscv64'), + Target( + rust: 'x86_64-apple-darwin', + darwinPlatform: 'macosx', + darwinArch: 'x86_64', + ), + Target( + rust: 'aarch64-apple-darwin', + darwinPlatform: 'macosx', + darwinArch: 'arm64', + ), + Target( + rust: 'aarch64-apple-ios', + darwinPlatform: 'iphoneos', + darwinArch: 'arm64', + ), + Target( + rust: 'aarch64-apple-ios-sim', + darwinPlatform: 'iphonesimulator', + darwinArch: 'arm64', + ), + Target( + rust: 'x86_64-apple-ios', + darwinPlatform: 'iphonesimulator', + darwinArch: 'x86_64', + ), + ]; + + static Target? forFlutterName(String flutterName) { + return all.firstWhereOrNull((element) => element.flutter == flutterName); + } + + static Target? forDarwin({ + required String platformName, + required String darwinAarch, + }) { + return all.firstWhereOrNull((element) => // + element.darwinPlatform == platformName && + element.darwinArch == darwinAarch); + } + + static Target? forRustTriple(String triple) { + return all.firstWhereOrNull((element) => element.rust == triple); + } + + static List androidTargets() { + return all + .where((element) => element.android != null) + .toList(growable: false); + } + + /// Returns buildable targets on current host platform ignoring Android targets. + static List buildableTargets() { + if (Platform.isLinux) { + // Right now we don't support cross-compiling on Linux. So we just return + // the host target. + final arch = (runCommand('arch', []).stdout as String).trim(); + if (arch == 'aarch64') { + return [Target.forRustTriple('aarch64-unknown-linux-gnu')!]; + } else if (arch == 'riscv64') { + return [Target.forRustTriple('riscv64gc-unknown-linux-gnu')!]; + } else { + return [Target.forRustTriple('x86_64-unknown-linux-gnu')!]; + } + } + return all.where((target) { + if (Platform.isWindows) { + return target.rust.contains('-windows-'); + } else if (Platform.isMacOS) { + return target.darwinPlatform != null; + } + return false; + }).toList(growable: false); + } + + @override + String toString() { + return rust; + } + + final String? flutter; + final String rust; + final String? android; + final int? androidMinSdkVersion; + final String? darwinPlatform; + final String? darwinArch; +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/util.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/util.dart index 8bb6a87..4403c2e 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/util.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/util.dart @@ -1,172 +1,172 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:convert'; -import 'dart:io'; - -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as path; - -import 'logging.dart'; -import 'rustup.dart'; - -final log = Logger("process"); - -class CommandFailedException implements Exception { - final String executable; - final List arguments; - final ProcessResult result; - - CommandFailedException({ - required this.executable, - required this.arguments, - required this.result, - }); - - @override - String toString() { - final stdout = result.stdout.toString().trim(); - final stderr = result.stderr.toString().trim(); - return [ - "External Command: $executable ${arguments.map((e) => '"$e"').join(' ')}", - "Returned Exit Code: ${result.exitCode}", - kSeparator, - "STDOUT:", - if (stdout.isNotEmpty) stdout, - kSeparator, - "STDERR:", - if (stderr.isNotEmpty) stderr, - ].join('\n'); - } -} - -class TestRunCommandArgs { - final String executable; - final List arguments; - final String? workingDirectory; - final Map? environment; - final bool includeParentEnvironment; - final bool runInShell; - final Encoding? stdoutEncoding; - final Encoding? stderrEncoding; - - TestRunCommandArgs({ - required this.executable, - required this.arguments, - this.workingDirectory, - this.environment, - this.includeParentEnvironment = true, - this.runInShell = false, - this.stdoutEncoding, - this.stderrEncoding, - }); -} - -class TestRunCommandResult { - TestRunCommandResult({ - this.pid = 1, - this.exitCode = 0, - this.stdout = '', - this.stderr = '', - }); - - final int pid; - final int exitCode; - final String stdout; - final String stderr; -} - -TestRunCommandResult Function(TestRunCommandArgs args)? testRunCommandOverride; - -ProcessResult runCommand( - String executable, - List arguments, { - String? workingDirectory, - Map? environment, - bool includeParentEnvironment = true, - bool runInShell = false, - Encoding? stdoutEncoding = systemEncoding, - Encoding? stderrEncoding = systemEncoding, -}) { - if (testRunCommandOverride != null) { - final result = testRunCommandOverride!(TestRunCommandArgs( - executable: executable, - arguments: arguments, - workingDirectory: workingDirectory, - environment: environment, - includeParentEnvironment: includeParentEnvironment, - runInShell: runInShell, - stdoutEncoding: stdoutEncoding, - stderrEncoding: stderrEncoding, - )); - return ProcessResult( - result.pid, - result.exitCode, - result.stdout, - result.stderr, - ); - } - log.finer('Running command $executable ${arguments.join(' ')}'); - final res = Process.runSync( - _resolveExecutable(executable), - arguments, - workingDirectory: workingDirectory, - environment: environment, - includeParentEnvironment: includeParentEnvironment, - runInShell: runInShell, - stderrEncoding: stderrEncoding, - stdoutEncoding: stdoutEncoding, - ); - if (res.exitCode != 0) { - throw CommandFailedException( - executable: executable, - arguments: arguments, - result: res, - ); - } else { - return res; - } -} - -class RustupNotFoundException implements Exception { - @override - String toString() { - return [ - ' ', - 'rustup not found in PATH.', - ' ', - 'Maybe you need to install Rust? It only takes a minute:', - ' ', - if (Platform.isWindows) 'https://www.rust-lang.org/tools/install', - if (hasHomebrewRustInPath()) ...[ - '\$ brew unlink rust # Unlink homebrew Rust from PATH', - ], - if (!Platform.isWindows) - "\$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh", - ' ', - ].join('\n'); - } - - static bool hasHomebrewRustInPath() { - if (!Platform.isMacOS) { - return false; - } - final envPath = Platform.environment['PATH'] ?? ''; - final paths = envPath.split(':'); - return paths.any((p) { - return p.contains('homebrew') && File(path.join(p, 'rustc')).existsSync(); - }); - } -} - -String _resolveExecutable(String executable) { - if (executable == 'rustup') { - final resolved = Rustup.executablePath(); - if (resolved != null) { - return resolved; - } - throw RustupNotFoundException(); - } else { - return executable; - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:convert'; +import 'dart:io'; + +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as path; + +import 'logging.dart'; +import 'rustup.dart'; + +final log = Logger("process"); + +class CommandFailedException implements Exception { + final String executable; + final List arguments; + final ProcessResult result; + + CommandFailedException({ + required this.executable, + required this.arguments, + required this.result, + }); + + @override + String toString() { + final stdout = result.stdout.toString().trim(); + final stderr = result.stderr.toString().trim(); + return [ + "External Command: $executable ${arguments.map((e) => '"$e"').join(' ')}", + "Returned Exit Code: ${result.exitCode}", + kSeparator, + "STDOUT:", + if (stdout.isNotEmpty) stdout, + kSeparator, + "STDERR:", + if (stderr.isNotEmpty) stderr, + ].join('\n'); + } +} + +class TestRunCommandArgs { + final String executable; + final List arguments; + final String? workingDirectory; + final Map? environment; + final bool includeParentEnvironment; + final bool runInShell; + final Encoding? stdoutEncoding; + final Encoding? stderrEncoding; + + TestRunCommandArgs({ + required this.executable, + required this.arguments, + this.workingDirectory, + this.environment, + this.includeParentEnvironment = true, + this.runInShell = false, + this.stdoutEncoding, + this.stderrEncoding, + }); +} + +class TestRunCommandResult { + TestRunCommandResult({ + this.pid = 1, + this.exitCode = 0, + this.stdout = '', + this.stderr = '', + }); + + final int pid; + final int exitCode; + final String stdout; + final String stderr; +} + +TestRunCommandResult Function(TestRunCommandArgs args)? testRunCommandOverride; + +ProcessResult runCommand( + String executable, + List arguments, { + String? workingDirectory, + Map? environment, + bool includeParentEnvironment = true, + bool runInShell = false, + Encoding? stdoutEncoding = systemEncoding, + Encoding? stderrEncoding = systemEncoding, +}) { + if (testRunCommandOverride != null) { + final result = testRunCommandOverride!(TestRunCommandArgs( + executable: executable, + arguments: arguments, + workingDirectory: workingDirectory, + environment: environment, + includeParentEnvironment: includeParentEnvironment, + runInShell: runInShell, + stdoutEncoding: stdoutEncoding, + stderrEncoding: stderrEncoding, + )); + return ProcessResult( + result.pid, + result.exitCode, + result.stdout, + result.stderr, + ); + } + log.finer('Running command $executable ${arguments.join(' ')}'); + final res = Process.runSync( + _resolveExecutable(executable), + arguments, + workingDirectory: workingDirectory, + environment: environment, + includeParentEnvironment: includeParentEnvironment, + runInShell: runInShell, + stderrEncoding: stderrEncoding, + stdoutEncoding: stdoutEncoding, + ); + if (res.exitCode != 0) { + throw CommandFailedException( + executable: executable, + arguments: arguments, + result: res, + ); + } else { + return res; + } +} + +class RustupNotFoundException implements Exception { + @override + String toString() { + return [ + ' ', + 'rustup not found in PATH.', + ' ', + 'Maybe you need to install Rust? It only takes a minute:', + ' ', + if (Platform.isWindows) 'https://www.rust-lang.org/tools/install', + if (hasHomebrewRustInPath()) ...[ + '\$ brew unlink rust # Unlink homebrew Rust from PATH', + ], + if (!Platform.isWindows) + "\$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh", + ' ', + ].join('\n'); + } + + static bool hasHomebrewRustInPath() { + if (!Platform.isMacOS) { + return false; + } + final envPath = Platform.environment['PATH'] ?? ''; + final paths = envPath.split(':'); + return paths.any((p) { + return p.contains('homebrew') && File(path.join(p, 'rustc')).existsSync(); + }); + } +} + +String _resolveExecutable(String executable) { + if (executable == 'rustup') { + final resolved = Rustup.executablePath(); + if (resolved != null) { + return resolved; + } + throw RustupNotFoundException(); + } else { + return executable; + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/lib/src/verify_binaries.dart b/useragent/rust_builder/cargokit/build_tool/lib/src/verify_binaries.dart index 2366b57..3202cc4 100644 --- a/useragent/rust_builder/cargokit/build_tool/lib/src/verify_binaries.dart +++ b/useragent/rust_builder/cargokit/build_tool/lib/src/verify_binaries.dart @@ -1,84 +1,84 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import 'dart:io'; - -import 'package:ed25519_edwards/ed25519_edwards.dart'; -import 'package:http/http.dart'; - -import 'artifacts_provider.dart'; -import 'cargo.dart'; -import 'crate_hash.dart'; -import 'options.dart'; -import 'precompile_binaries.dart'; -import 'target.dart'; - -class VerifyBinaries { - VerifyBinaries({ - required this.manifestDir, - }); - - final String manifestDir; - - Future run() async { - final crateInfo = CrateInfo.load(manifestDir); - - final config = CargokitCrateOptions.load(manifestDir: manifestDir); - final precompiledBinaries = config.precompiledBinaries; - if (precompiledBinaries == null) { - stdout.writeln('Crate does not support precompiled binaries.'); - } else { - final crateHash = CrateHash.compute(manifestDir); - stdout.writeln('Crate hash: $crateHash'); - - for (final target in Target.all) { - final message = 'Checking ${target.rust}...'; - stdout.write(message.padRight(40)); - stdout.flush(); - - final artifacts = getArtifactNames( - target: target, - libraryName: crateInfo.packageName, - remote: true, - ); - - final prefix = precompiledBinaries.uriPrefix; - - bool ok = true; - - for (final artifact in artifacts) { - final fileName = PrecompileBinaries.fileName(target, artifact); - final signatureFileName = - PrecompileBinaries.signatureFileName(target, artifact); - - final url = Uri.parse('$prefix$crateHash/$fileName'); - final signatureUrl = - Uri.parse('$prefix$crateHash/$signatureFileName'); - - final signature = await get(signatureUrl); - if (signature.statusCode != 200) { - stdout.writeln('MISSING'); - ok = false; - break; - } - final asset = await get(url); - if (asset.statusCode != 200) { - stdout.writeln('MISSING'); - ok = false; - break; - } - - if (!verify(precompiledBinaries.publicKey, asset.bodyBytes, - signature.bodyBytes)) { - stdout.writeln('INVALID SIGNATURE'); - ok = false; - } - } - - if (ok) { - stdout.writeln('OK'); - } - } - } - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import 'dart:io'; + +import 'package:ed25519_edwards/ed25519_edwards.dart'; +import 'package:http/http.dart'; + +import 'artifacts_provider.dart'; +import 'cargo.dart'; +import 'crate_hash.dart'; +import 'options.dart'; +import 'precompile_binaries.dart'; +import 'target.dart'; + +class VerifyBinaries { + VerifyBinaries({ + required this.manifestDir, + }); + + final String manifestDir; + + Future run() async { + final crateInfo = CrateInfo.load(manifestDir); + + final config = CargokitCrateOptions.load(manifestDir: manifestDir); + final precompiledBinaries = config.precompiledBinaries; + if (precompiledBinaries == null) { + stdout.writeln('Crate does not support precompiled binaries.'); + } else { + final crateHash = CrateHash.compute(manifestDir); + stdout.writeln('Crate hash: $crateHash'); + + for (final target in Target.all) { + final message = 'Checking ${target.rust}...'; + stdout.write(message.padRight(40)); + stdout.flush(); + + final artifacts = getArtifactNames( + target: target, + libraryName: crateInfo.packageName, + remote: true, + ); + + final prefix = precompiledBinaries.uriPrefix; + + bool ok = true; + + for (final artifact in artifacts) { + final fileName = PrecompileBinaries.fileName(target, artifact); + final signatureFileName = + PrecompileBinaries.signatureFileName(target, artifact); + + final url = Uri.parse('$prefix$crateHash/$fileName'); + final signatureUrl = + Uri.parse('$prefix$crateHash/$signatureFileName'); + + final signature = await get(signatureUrl); + if (signature.statusCode != 200) { + stdout.writeln('MISSING'); + ok = false; + break; + } + final asset = await get(url); + if (asset.statusCode != 200) { + stdout.writeln('MISSING'); + ok = false; + break; + } + + if (!verify(precompiledBinaries.publicKey, asset.bodyBytes, + signature.bodyBytes)) { + stdout.writeln('INVALID SIGNATURE'); + ok = false; + } + } + + if (ok) { + stdout.writeln('OK'); + } + } + } + } +} diff --git a/useragent/rust_builder/cargokit/build_tool/pubspec.lock b/useragent/rust_builder/cargokit/build_tool/pubspec.lock index 343bdd3..e685451 100644 --- a/useragent/rust_builder/cargokit/build_tool/pubspec.lock +++ b/useragent/rust_builder/cargokit/build_tool/pubspec.lock @@ -1,453 +1,453 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 - url: "https://pub.dev" - source: hosted - version: "64.0.0" - adaptive_number: - dependency: transitive - description: - name: adaptive_number - sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" - url: "https://pub.dev" - source: hosted - version: "6.2.0" - args: - dependency: "direct main" - description: - name: args - sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 - url: "https://pub.dev" - source: hosted - version: "2.4.2" - async: - dependency: transitive - description: - name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - collection: - dependency: "direct main" - description: - name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a - url: "https://pub.dev" - source: hosted - version: "1.18.0" - convert: - dependency: "direct main" - description: - name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" - source: hosted - version: "3.1.1" - coverage: - dependency: transitive - description: - name: coverage - sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" - url: "https://pub.dev" - source: hosted - version: "1.6.3" - crypto: - dependency: "direct main" - description: - name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab - url: "https://pub.dev" - source: hosted - version: "3.0.3" - ed25519_edwards: - dependency: "direct main" - description: - name: ed25519_edwards - sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd" - url: "https://pub.dev" - source: hosted - version: "0.3.1" - file: - dependency: transitive - description: - name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" - url: "https://pub.dev" - source: hosted - version: "6.1.4" - fixnum: - dependency: transitive - description: - name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" - url: "https://pub.dev" - source: hosted - version: "3.2.0" - github: - dependency: "direct main" - description: - name: github - sha256: "9966bc13bf612342e916b0a343e95e5f046c88f602a14476440e9b75d2295411" - url: "https://pub.dev" - source: hosted - version: "9.17.0" - glob: - dependency: transitive - description: - name: glob - sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - hex: - dependency: "direct main" - description: - name: hex - sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - http: - dependency: "direct main" - description: - name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" - source: hosted - version: "4.0.2" - io: - dependency: transitive - description: - name: io - sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" - url: "https://pub.dev" - source: hosted - version: "1.0.4" - js: - dependency: transitive - description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 - url: "https://pub.dev" - source: hosted - version: "4.8.1" - lints: - dependency: "direct dev" - description: - name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - logging: - dependency: "direct main" - description: - name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" - url: "https://pub.dev" - source: hosted - version: "0.12.16" - meta: - dependency: transitive - description: - name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - mime: - dependency: transitive - description: - name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e - url: "https://pub.dev" - source: hosted - version: "1.0.4" - node_preamble: - dependency: transitive - description: - name: node_preamble - sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" - url: "https://pub.dev" - source: hosted - version: "2.0.2" - package_config: - dependency: transitive - description: - name: package_config - sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - path: - dependency: "direct main" - description: - name: path - sha256: "2ad4cddff7f5cc0e2d13069f2a3f7a73ca18f66abd6f5ecf215219cdb3638edb" - url: "https://pub.dev" - source: hosted - version: "1.8.0" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 - url: "https://pub.dev" - source: hosted - version: "5.4.0" - pool: - dependency: transitive - description: - name: pool - sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" - url: "https://pub.dev" - source: hosted - version: "1.5.1" - pub_semver: - dependency: transitive - description: - name: pub_semver - sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - shelf: - dependency: transitive - description: - name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 - url: "https://pub.dev" - source: hosted - version: "1.4.1" - shelf_packages_handler: - dependency: transitive - description: - name: shelf_packages_handler - sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - shelf_static: - dependency: transitive - description: - name: shelf_static - sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e - url: "https://pub.dev" - source: hosted - version: "1.1.2" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" - url: "https://pub.dev" - source: hosted - version: "1.0.4" - source_map_stack_trace: - dependency: transitive - description: - name: source_map_stack_trace - sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - source_maps: - dependency: transitive - description: - name: source_maps - sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" - url: "https://pub.dev" - source: hosted - version: "0.10.12" - source_span: - dependency: "direct main" - description: - name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.dev" - source: hosted - version: "1.10.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" - url: "https://pub.dev" - source: hosted - version: "1.11.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://pub.dev" - source: hosted - version: "2.1.2" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" - source: hosted - version: "1.2.1" - test: - dependency: "direct dev" - description: - name: test - sha256: "9b0dd8e36af4a5b1569029949d50a52cb2a2a2fdaa20cebb96e6603b9ae241f9" - url: "https://pub.dev" - source: hosted - version: "1.24.6" - test_api: - dependency: transitive - description: - name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" - url: "https://pub.dev" - source: hosted - version: "0.6.1" - test_core: - dependency: transitive - description: - name: test_core - sha256: "4bef837e56375537055fdbbbf6dd458b1859881f4c7e6da936158f77d61ab265" - url: "https://pub.dev" - source: hosted - version: "0.5.6" - toml: - dependency: "direct main" - description: - name: toml - sha256: "157c5dca5160fced243f3ce984117f729c788bb5e475504f3dbcda881accee44" - url: "https://pub.dev" - source: hosted - version: "0.14.0" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c - url: "https://pub.dev" - source: hosted - version: "1.3.2" - version: - dependency: "direct main" - description: - name: version - sha256: "2307e23a45b43f96469eeab946208ed63293e8afca9c28cd8b5241ff31c55f55" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "0fae432c85c4ea880b33b497d32824b97795b04cdaa74d270219572a1f50268d" - url: "https://pub.dev" - source: hosted - version: "11.9.0" - watcher: - dependency: transitive - description: - name: watcher - sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b - url: "https://pub.dev" - source: hosted - version: "2.4.0" - webkit_inspection_protocol: - dependency: transitive - description: - name: webkit_inspection_protocol - sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - yaml: - dependency: "direct main" - description: - name: yaml - sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" - url: "https://pub.dev" - source: hosted - version: "3.1.2" -sdks: - dart: ">=3.0.0 <4.0.0" +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 + url: "https://pub.dev" + source: hosted + version: "64.0.0" + adaptive_number: + dependency: transitive + description: + name: adaptive_number + sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" + url: "https://pub.dev" + source: hosted + version: "6.2.0" + args: + dependency: "direct main" + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + collection: + dependency: "direct main" + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + convert: + dependency: "direct main" + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + coverage: + dependency: transitive + description: + name: coverage + sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097" + url: "https://pub.dev" + source: hosted + version: "1.6.3" + crypto: + dependency: "direct main" + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + ed25519_edwards: + dependency: "direct main" + description: + name: ed25519_edwards + sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + github: + dependency: "direct main" + description: + name: github + sha256: "9966bc13bf612342e916b0a343e95e5f046c88f602a14476440e9b75d2295411" + url: "https://pub.dev" + source: hosted + version: "9.17.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + hex: + dependency: "direct main" + description: + name: hex + sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + http: + dependency: "direct main" + description: + name: http + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + lints: + dependency: "direct dev" + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + logging: + dependency: "direct main" + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" + source: hosted + version: "0.12.16" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: "direct main" + description: + name: path + sha256: "2ad4cddff7f5cc0e2d13069f2a3f7a73ca18f66abd6f5ecf215219cdb3638edb" + url: "https://pub.dev" + source: hosted + version: "1.8.0" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" + source: hosted + version: "5.4.0" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e + url: "https://pub.dev" + source: hosted + version: "1.1.2" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" + source_span: + dependency: "direct main" + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test: + dependency: "direct dev" + description: + name: test + sha256: "9b0dd8e36af4a5b1569029949d50a52cb2a2a2fdaa20cebb96e6603b9ae241f9" + url: "https://pub.dev" + source: hosted + version: "1.24.6" + test_api: + dependency: transitive + description: + name: test_api + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + url: "https://pub.dev" + source: hosted + version: "0.6.1" + test_core: + dependency: transitive + description: + name: test_core + sha256: "4bef837e56375537055fdbbbf6dd458b1859881f4c7e6da936158f77d61ab265" + url: "https://pub.dev" + source: hosted + version: "0.5.6" + toml: + dependency: "direct main" + description: + name: toml + sha256: "157c5dca5160fced243f3ce984117f729c788bb5e475504f3dbcda881accee44" + url: "https://pub.dev" + source: hosted + version: "0.14.0" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + version: + dependency: "direct main" + description: + name: version + sha256: "2307e23a45b43f96469eeab946208ed63293e8afca9c28cd8b5241ff31c55f55" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "0fae432c85c4ea880b33b497d32824b97795b04cdaa74d270219572a1f50268d" + url: "https://pub.dev" + source: hosted + version: "11.9.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + yaml: + dependency: "direct main" + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.0.0 <4.0.0" diff --git a/useragent/rust_builder/cargokit/build_tool/pubspec.yaml b/useragent/rust_builder/cargokit/build_tool/pubspec.yaml index 18c61e3..042ca1e 100644 --- a/useragent/rust_builder/cargokit/build_tool/pubspec.yaml +++ b/useragent/rust_builder/cargokit/build_tool/pubspec.yaml @@ -1,33 +1,33 @@ -# This is copied from Cargokit (which is the official way to use it currently) -# Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -name: build_tool -description: Cargokit build_tool. Facilitates the build of Rust crate during Flutter application build. -publish_to: none -version: 1.0.0 - -environment: - sdk: ">=3.0.0 <4.0.0" - -# Add regular dependencies here. -dependencies: - # these are pinned on purpose because the bundle_tool_runner doesn't have - # pubspec.lock. See run_build_tool.sh - logging: 1.2.0 - path: 1.8.0 - version: 3.0.0 - collection: 1.18.0 - ed25519_edwards: 0.3.1 - hex: 0.2.0 - yaml: 3.1.2 - source_span: 1.10.0 - github: 9.17.0 - args: 2.4.2 - crypto: 3.0.3 - convert: 3.1.1 - http: 1.1.0 - toml: 0.14.0 - -dev_dependencies: - lints: ^2.1.0 - test: ^1.24.0 +# This is copied from Cargokit (which is the official way to use it currently) +# Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +name: build_tool +description: Cargokit build_tool. Facilitates the build of Rust crate during Flutter application build. +publish_to: none +version: 1.0.0 + +environment: + sdk: ">=3.0.0 <4.0.0" + +# Add regular dependencies here. +dependencies: + # these are pinned on purpose because the bundle_tool_runner doesn't have + # pubspec.lock. See run_build_tool.sh + logging: 1.2.0 + path: 1.8.0 + version: 3.0.0 + collection: 1.18.0 + ed25519_edwards: 0.3.1 + hex: 0.2.0 + yaml: 3.1.2 + source_span: 1.10.0 + github: 9.17.0 + args: 2.4.2 + crypto: 3.0.3 + convert: 3.1.1 + http: 1.1.0 + toml: 0.14.0 + +dev_dependencies: + lints: ^2.1.0 + test: ^1.24.0 diff --git a/useragent/rust_builder/cargokit/cmake/cargokit.cmake b/useragent/rust_builder/cargokit/cmake/cargokit.cmake index ddd05df..f9b71d0 100644 --- a/useragent/rust_builder/cargokit/cmake/cargokit.cmake +++ b/useragent/rust_builder/cargokit/cmake/cargokit.cmake @@ -1,99 +1,99 @@ -SET(cargokit_cmake_root "${CMAKE_CURRENT_LIST_DIR}/..") - -# Workaround for https://github.com/dart-lang/pub/issues/4010 -get_filename_component(cargokit_cmake_root "${cargokit_cmake_root}" REALPATH) - -if(WIN32) - # REALPATH does not properly resolve symlinks on windows :-/ - execute_process(COMMAND powershell -ExecutionPolicy Bypass -File "${CMAKE_CURRENT_LIST_DIR}/resolve_symlinks.ps1" "${cargokit_cmake_root}" OUTPUT_VARIABLE cargokit_cmake_root OUTPUT_STRIP_TRAILING_WHITESPACE) -endif() - -# Arguments -# - target: CMAKE target to which rust library is linked -# - manifest_dir: relative path from current folder to directory containing cargo manifest -# - lib_name: cargo package name -# - any_symbol_name: name of any exported symbol from the library. -# used on windows to force linking with library. -function(apply_cargokit target manifest_dir lib_name any_symbol_name) - - set(CARGOKIT_LIB_NAME "${lib_name}") - set(CARGOKIT_LIB_FULL_NAME "${CMAKE_SHARED_MODULE_PREFIX}${CARGOKIT_LIB_NAME}${CMAKE_SHARED_MODULE_SUFFIX}") - if (CMAKE_CONFIGURATION_TYPES) - set(CARGOKIT_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/$") - set(OUTPUT_LIB "${CMAKE_CURRENT_BINARY_DIR}/$/${CARGOKIT_LIB_FULL_NAME}") - else() - set(CARGOKIT_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") - set(OUTPUT_LIB "${CMAKE_CURRENT_BINARY_DIR}/${CARGOKIT_LIB_FULL_NAME}") - endif() - set(CARGOKIT_TEMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/cargokit_build") - - if (FLUTTER_TARGET_PLATFORM) - set(CARGOKIT_TARGET_PLATFORM "${FLUTTER_TARGET_PLATFORM}") - else() - set(CARGOKIT_TARGET_PLATFORM "windows-x64") - endif() - - set(CARGOKIT_ENV - "CARGOKIT_CMAKE=${CMAKE_COMMAND}" - "CARGOKIT_CONFIGURATION=$" - "CARGOKIT_MANIFEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/${manifest_dir}" - "CARGOKIT_TARGET_TEMP_DIR=${CARGOKIT_TEMP_DIR}" - "CARGOKIT_OUTPUT_DIR=${CARGOKIT_OUTPUT_DIR}" - "CARGOKIT_TARGET_PLATFORM=${CARGOKIT_TARGET_PLATFORM}" - "CARGOKIT_TOOL_TEMP_DIR=${CARGOKIT_TEMP_DIR}/tool" - "CARGOKIT_ROOT_PROJECT_DIR=${CMAKE_SOURCE_DIR}" - ) - - if (WIN32) - set(SCRIPT_EXTENSION ".cmd") - set(IMPORT_LIB_EXTENSION ".lib") - else() - set(SCRIPT_EXTENSION ".sh") - set(IMPORT_LIB_EXTENSION "") - execute_process(COMMAND chmod +x "${cargokit_cmake_root}/run_build_tool${SCRIPT_EXTENSION}") - endif() - - # Using generators in custom command is only supported in CMake 3.20+ - if (CMAKE_CONFIGURATION_TYPES AND ${CMAKE_VERSION} VERSION_LESS "3.20.0") - foreach(CONFIG IN LISTS CMAKE_CONFIGURATION_TYPES) - add_custom_command( - OUTPUT - "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG}/${CARGOKIT_LIB_FULL_NAME}" - "${CMAKE_CURRENT_BINARY_DIR}/_phony_" - COMMAND ${CMAKE_COMMAND} -E env ${CARGOKIT_ENV} - "${cargokit_cmake_root}/run_build_tool${SCRIPT_EXTENSION}" build-cmake - VERBATIM - ) - endforeach() - else() - add_custom_command( - OUTPUT - ${OUTPUT_LIB} - "${CMAKE_CURRENT_BINARY_DIR}/_phony_" - COMMAND ${CMAKE_COMMAND} -E env ${CARGOKIT_ENV} - "${cargokit_cmake_root}/run_build_tool${SCRIPT_EXTENSION}" build-cmake - VERBATIM - ) - endif() - - - set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/_phony_" PROPERTIES SYMBOLIC TRUE) - - if (TARGET ${target}) - # If we have actual cmake target provided create target and make existing - # target depend on it - add_custom_target("${target}_cargokit" DEPENDS ${OUTPUT_LIB}) - add_dependencies("${target}" "${target}_cargokit") - target_link_libraries("${target}" PRIVATE "${OUTPUT_LIB}${IMPORT_LIB_EXTENSION}") - if(WIN32) - target_link_options(${target} PRIVATE "/INCLUDE:${any_symbol_name}") - endif() - else() - # Otherwise (FFI) just use ALL to force building always - add_custom_target("${target}_cargokit" ALL DEPENDS ${OUTPUT_LIB}) - endif() - - # Allow adding the output library to plugin bundled libraries - set("${target}_cargokit_lib" ${OUTPUT_LIB} PARENT_SCOPE) - -endfunction() +SET(cargokit_cmake_root "${CMAKE_CURRENT_LIST_DIR}/..") + +# Workaround for https://github.com/dart-lang/pub/issues/4010 +get_filename_component(cargokit_cmake_root "${cargokit_cmake_root}" REALPATH) + +if(WIN32) + # REALPATH does not properly resolve symlinks on windows :-/ + execute_process(COMMAND powershell -ExecutionPolicy Bypass -File "${CMAKE_CURRENT_LIST_DIR}/resolve_symlinks.ps1" "${cargokit_cmake_root}" OUTPUT_VARIABLE cargokit_cmake_root OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +# Arguments +# - target: CMAKE target to which rust library is linked +# - manifest_dir: relative path from current folder to directory containing cargo manifest +# - lib_name: cargo package name +# - any_symbol_name: name of any exported symbol from the library. +# used on windows to force linking with library. +function(apply_cargokit target manifest_dir lib_name any_symbol_name) + + set(CARGOKIT_LIB_NAME "${lib_name}") + set(CARGOKIT_LIB_FULL_NAME "${CMAKE_SHARED_MODULE_PREFIX}${CARGOKIT_LIB_NAME}${CMAKE_SHARED_MODULE_SUFFIX}") + if (CMAKE_CONFIGURATION_TYPES) + set(CARGOKIT_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/$") + set(OUTPUT_LIB "${CMAKE_CURRENT_BINARY_DIR}/$/${CARGOKIT_LIB_FULL_NAME}") + else() + set(CARGOKIT_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") + set(OUTPUT_LIB "${CMAKE_CURRENT_BINARY_DIR}/${CARGOKIT_LIB_FULL_NAME}") + endif() + set(CARGOKIT_TEMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/cargokit_build") + + if (FLUTTER_TARGET_PLATFORM) + set(CARGOKIT_TARGET_PLATFORM "${FLUTTER_TARGET_PLATFORM}") + else() + set(CARGOKIT_TARGET_PLATFORM "windows-x64") + endif() + + set(CARGOKIT_ENV + "CARGOKIT_CMAKE=${CMAKE_COMMAND}" + "CARGOKIT_CONFIGURATION=$" + "CARGOKIT_MANIFEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/${manifest_dir}" + "CARGOKIT_TARGET_TEMP_DIR=${CARGOKIT_TEMP_DIR}" + "CARGOKIT_OUTPUT_DIR=${CARGOKIT_OUTPUT_DIR}" + "CARGOKIT_TARGET_PLATFORM=${CARGOKIT_TARGET_PLATFORM}" + "CARGOKIT_TOOL_TEMP_DIR=${CARGOKIT_TEMP_DIR}/tool" + "CARGOKIT_ROOT_PROJECT_DIR=${CMAKE_SOURCE_DIR}" + ) + + if (WIN32) + set(SCRIPT_EXTENSION ".cmd") + set(IMPORT_LIB_EXTENSION ".lib") + else() + set(SCRIPT_EXTENSION ".sh") + set(IMPORT_LIB_EXTENSION "") + execute_process(COMMAND chmod +x "${cargokit_cmake_root}/run_build_tool${SCRIPT_EXTENSION}") + endif() + + # Using generators in custom command is only supported in CMake 3.20+ + if (CMAKE_CONFIGURATION_TYPES AND ${CMAKE_VERSION} VERSION_LESS "3.20.0") + foreach(CONFIG IN LISTS CMAKE_CONFIGURATION_TYPES) + add_custom_command( + OUTPUT + "${CMAKE_CURRENT_BINARY_DIR}/${CONFIG}/${CARGOKIT_LIB_FULL_NAME}" + "${CMAKE_CURRENT_BINARY_DIR}/_phony_" + COMMAND ${CMAKE_COMMAND} -E env ${CARGOKIT_ENV} + "${cargokit_cmake_root}/run_build_tool${SCRIPT_EXTENSION}" build-cmake + VERBATIM + ) + endforeach() + else() + add_custom_command( + OUTPUT + ${OUTPUT_LIB} + "${CMAKE_CURRENT_BINARY_DIR}/_phony_" + COMMAND ${CMAKE_COMMAND} -E env ${CARGOKIT_ENV} + "${cargokit_cmake_root}/run_build_tool${SCRIPT_EXTENSION}" build-cmake + VERBATIM + ) + endif() + + + set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/_phony_" PROPERTIES SYMBOLIC TRUE) + + if (TARGET ${target}) + # If we have actual cmake target provided create target and make existing + # target depend on it + add_custom_target("${target}_cargokit" DEPENDS ${OUTPUT_LIB}) + add_dependencies("${target}" "${target}_cargokit") + target_link_libraries("${target}" PRIVATE "${OUTPUT_LIB}${IMPORT_LIB_EXTENSION}") + if(WIN32) + target_link_options(${target} PRIVATE "/INCLUDE:${any_symbol_name}") + endif() + else() + # Otherwise (FFI) just use ALL to force building always + add_custom_target("${target}_cargokit" ALL DEPENDS ${OUTPUT_LIB}) + endif() + + # Allow adding the output library to plugin bundled libraries + set("${target}_cargokit_lib" ${OUTPUT_LIB} PARENT_SCOPE) + +endfunction() diff --git a/useragent/rust_builder/cargokit/cmake/resolve_symlinks.ps1 b/useragent/rust_builder/cargokit/cmake/resolve_symlinks.ps1 index 2ac593a..e777fa6 100644 --- a/useragent/rust_builder/cargokit/cmake/resolve_symlinks.ps1 +++ b/useragent/rust_builder/cargokit/cmake/resolve_symlinks.ps1 @@ -1,34 +1,34 @@ -function Resolve-Symlinks { - [CmdletBinding()] - [OutputType([string])] - param( - [Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] - [string] $Path - ) - - [string] $separator = '/' - [string[]] $parts = $Path.Split($separator) - - [string] $realPath = '' - foreach ($part in $parts) { - if ($realPath -and !$realPath.EndsWith($separator)) { - $realPath += $separator - } - - $realPath += $part.Replace('\', '/') - - # The slash is important when using Get-Item on Drive letters in pwsh. - if (-not($realPath.Contains($separator)) -and $realPath.EndsWith(':')) { - $realPath += '/' - } - - $item = Get-Item $realPath - if ($item.LinkTarget) { - $realPath = $item.LinkTarget.Replace('\', '/') - } - } - $realPath -} - -$path = Resolve-Symlinks -Path $args[0] -Write-Host $path +function Resolve-Symlinks { + [CmdletBinding()] + [OutputType([string])] + param( + [Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] + [string] $Path + ) + + [string] $separator = '/' + [string[]] $parts = $Path.Split($separator) + + [string] $realPath = '' + foreach ($part in $parts) { + if ($realPath -and !$realPath.EndsWith($separator)) { + $realPath += $separator + } + + $realPath += $part.Replace('\', '/') + + # The slash is important when using Get-Item on Drive letters in pwsh. + if (-not($realPath.Contains($separator)) -and $realPath.EndsWith(':')) { + $realPath += '/' + } + + $item = Get-Item $realPath + if ($item.LinkTarget) { + $realPath = $item.LinkTarget.Replace('\', '/') + } + } + $realPath +} + +$path = Resolve-Symlinks -Path $args[0] +Write-Host $path diff --git a/useragent/rust_builder/cargokit/gradle/plugin.gradle b/useragent/rust_builder/cargokit/gradle/plugin.gradle index 68ff649..0f56a6e 100644 --- a/useragent/rust_builder/cargokit/gradle/plugin.gradle +++ b/useragent/rust_builder/cargokit/gradle/plugin.gradle @@ -1,184 +1,184 @@ -/// This is copied from Cargokit (which is the official way to use it currently) -/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin - -import java.nio.file.Paths -import org.apache.tools.ant.taskdefs.condition.Os - -CargoKitPlugin.file = buildscript.sourceFile - -apply plugin: CargoKitPlugin - -class CargoKitExtension { - String manifestDir; // Relative path to folder containing Cargo.toml - String libname; // Library name within Cargo.toml. Must be a cdylib -} - -abstract class CargoKitBuildTask extends DefaultTask { - - @Input - String buildMode - - @Input - String buildDir - - @Input - String outputDir - - @Input - String ndkVersion - - @Input - String sdkDirectory - - @Input - int compileSdkVersion; - - @Input - int minSdkVersion; - - @Input - String pluginFile - - @Input - List targetPlatforms - - @TaskAction - def build() { - if (project.cargokit.manifestDir == null) { - throw new GradleException("Property 'manifestDir' must be set on cargokit extension"); - } - - if (project.cargokit.libname == null) { - throw new GradleException("Property 'libname' must be set on cargokit extension"); - } - - def executableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "run_build_tool.cmd" : "run_build_tool.sh" - def path = Paths.get(new File(pluginFile).parent, "..", executableName); - - def manifestDir = Paths.get(project.buildscript.sourceFile.parent, project.cargokit.manifestDir) - - def rootProjectDir = project.rootProject.projectDir - - if (!Os.isFamily(Os.FAMILY_WINDOWS)) { - project.exec { - commandLine 'chmod', '+x', path - } - } - - project.exec { - executable path - args "build-gradle" - environment "CARGOKIT_ROOT_PROJECT_DIR", rootProjectDir - environment "CARGOKIT_TOOL_TEMP_DIR", "${buildDir}/build_tool" - environment "CARGOKIT_MANIFEST_DIR", manifestDir - environment "CARGOKIT_CONFIGURATION", buildMode - environment "CARGOKIT_TARGET_TEMP_DIR", buildDir - environment "CARGOKIT_OUTPUT_DIR", outputDir - environment "CARGOKIT_NDK_VERSION", ndkVersion - environment "CARGOKIT_SDK_DIR", sdkDirectory - environment "CARGOKIT_COMPILE_SDK_VERSION", compileSdkVersion - environment "CARGOKIT_MIN_SDK_VERSION", minSdkVersion - environment "CARGOKIT_TARGET_PLATFORMS", targetPlatforms.join(",") - environment "CARGOKIT_JAVA_HOME", System.properties['java.home'] - } - } -} - -class CargoKitPlugin implements Plugin { - - static String file; - - private Plugin findFlutterPlugin(Project rootProject) { - _findFlutterPlugin(rootProject.childProjects) - } - - private Plugin _findFlutterPlugin(Map projects) { - for (project in projects) { - for (plugin in project.value.getPlugins()) { - if (plugin.class.name == "com.flutter.gradle.FlutterPlugin" || plugin.class.name == "FlutterPlugin") { - return plugin; - } - } - def plugin = _findFlutterPlugin(project.value.childProjects); - if (plugin != null) { - return plugin; - } - } - return null; - } - - @Override - void apply(Project project) { - def plugin = findFlutterPlugin(project.rootProject); - - project.extensions.create("cargokit", CargoKitExtension) - - if (plugin == null) { - print("Flutter plugin not found, CargoKit plugin will not be applied.") - return; - } - - def cargoBuildDir = "${project.buildDir}/build" - - // Determine if the project is an application or library - def isApplication = plugin.project.plugins.hasPlugin('com.android.application') - def variants = isApplication ? plugin.project.android.applicationVariants : plugin.project.android.libraryVariants - - variants.all { variant -> - - final buildType = variant.buildType.name - - def cargoOutputDir = "${project.buildDir}/jniLibs/${buildType}"; - def jniLibs = project.android.sourceSets.maybeCreate(buildType).jniLibs; - jniLibs.srcDir(new File(cargoOutputDir)) - - def List platforms - try { - platforms = com.flutter.gradle.FlutterPluginUtils.getTargetPlatforms(project).collect() - } catch (Exception ignored) { - platforms = plugin.getTargetPlatforms().collect() - } - - // Same thing addFlutterDependencies does in flutter.gradle - if (buildType == "debug") { - platforms.add("android-x86") - platforms.add("android-x64") - } - - // The task name depends on plugin properties, which are not available - // at this point - project.getGradle().afterProject { - def taskName = "cargokitCargoBuild${project.cargokit.libname.capitalize()}${buildType.capitalize()}"; - - if (project.tasks.findByName(taskName)) { - return - } - - if (plugin.project.android.ndkVersion == null) { - throw new GradleException("Please set 'android.ndkVersion' in 'app/build.gradle'.") - } - - def task = project.tasks.create(taskName, CargoKitBuildTask.class) { - buildMode = variant.buildType.name - buildDir = cargoBuildDir - outputDir = cargoOutputDir - ndkVersion = plugin.project.android.ndkVersion - sdkDirectory = plugin.project.android.sdkDirectory - minSdkVersion = plugin.project.android.defaultConfig.minSdkVersion.apiLevel as int - compileSdkVersion = plugin.project.android.compileSdkVersion.substring(8) as int - targetPlatforms = platforms - pluginFile = CargoKitPlugin.file - } - def onTask = { newTask -> - if (newTask.name == "merge${buildType.capitalize()}NativeLibs") { - newTask.dependsOn task - // Fix gradle 7.4.2 not picking up JNI library changes - newTask.outputs.upToDateWhen { false } - } - } - project.tasks.each onTask - project.tasks.whenTaskAdded onTask - } - } - } -} +/// This is copied from Cargokit (which is the official way to use it currently) +/// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin + +import java.nio.file.Paths +import org.apache.tools.ant.taskdefs.condition.Os + +CargoKitPlugin.file = buildscript.sourceFile + +apply plugin: CargoKitPlugin + +class CargoKitExtension { + String manifestDir; // Relative path to folder containing Cargo.toml + String libname; // Library name within Cargo.toml. Must be a cdylib +} + +abstract class CargoKitBuildTask extends DefaultTask { + + @Input + String buildMode + + @Input + String buildDir + + @Input + String outputDir + + @Input + String ndkVersion + + @Input + String sdkDirectory + + @Input + int compileSdkVersion; + + @Input + int minSdkVersion; + + @Input + String pluginFile + + @Input + List targetPlatforms + + @TaskAction + def build() { + if (project.cargokit.manifestDir == null) { + throw new GradleException("Property 'manifestDir' must be set on cargokit extension"); + } + + if (project.cargokit.libname == null) { + throw new GradleException("Property 'libname' must be set on cargokit extension"); + } + + def executableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "run_build_tool.cmd" : "run_build_tool.sh" + def path = Paths.get(new File(pluginFile).parent, "..", executableName); + + def manifestDir = Paths.get(project.buildscript.sourceFile.parent, project.cargokit.manifestDir) + + def rootProjectDir = project.rootProject.projectDir + + if (!Os.isFamily(Os.FAMILY_WINDOWS)) { + project.exec { + commandLine 'chmod', '+x', path + } + } + + project.exec { + executable path + args "build-gradle" + environment "CARGOKIT_ROOT_PROJECT_DIR", rootProjectDir + environment "CARGOKIT_TOOL_TEMP_DIR", "${buildDir}/build_tool" + environment "CARGOKIT_MANIFEST_DIR", manifestDir + environment "CARGOKIT_CONFIGURATION", buildMode + environment "CARGOKIT_TARGET_TEMP_DIR", buildDir + environment "CARGOKIT_OUTPUT_DIR", outputDir + environment "CARGOKIT_NDK_VERSION", ndkVersion + environment "CARGOKIT_SDK_DIR", sdkDirectory + environment "CARGOKIT_COMPILE_SDK_VERSION", compileSdkVersion + environment "CARGOKIT_MIN_SDK_VERSION", minSdkVersion + environment "CARGOKIT_TARGET_PLATFORMS", targetPlatforms.join(",") + environment "CARGOKIT_JAVA_HOME", System.properties['java.home'] + } + } +} + +class CargoKitPlugin implements Plugin { + + static String file; + + private Plugin findFlutterPlugin(Project rootProject) { + _findFlutterPlugin(rootProject.childProjects) + } + + private Plugin _findFlutterPlugin(Map projects) { + for (project in projects) { + for (plugin in project.value.getPlugins()) { + if (plugin.class.name == "com.flutter.gradle.FlutterPlugin" || plugin.class.name == "FlutterPlugin") { + return plugin; + } + } + def plugin = _findFlutterPlugin(project.value.childProjects); + if (plugin != null) { + return plugin; + } + } + return null; + } + + @Override + void apply(Project project) { + def plugin = findFlutterPlugin(project.rootProject); + + project.extensions.create("cargokit", CargoKitExtension) + + if (plugin == null) { + print("Flutter plugin not found, CargoKit plugin will not be applied.") + return; + } + + def cargoBuildDir = "${project.buildDir}/build" + + // Determine if the project is an application or library + def isApplication = plugin.project.plugins.hasPlugin('com.android.application') + def variants = isApplication ? plugin.project.android.applicationVariants : plugin.project.android.libraryVariants + + variants.all { variant -> + + final buildType = variant.buildType.name + + def cargoOutputDir = "${project.buildDir}/jniLibs/${buildType}"; + def jniLibs = project.android.sourceSets.maybeCreate(buildType).jniLibs; + jniLibs.srcDir(new File(cargoOutputDir)) + + def List platforms + try { + platforms = com.flutter.gradle.FlutterPluginUtils.getTargetPlatforms(project).collect() + } catch (Exception ignored) { + platforms = plugin.getTargetPlatforms().collect() + } + + // Same thing addFlutterDependencies does in flutter.gradle + if (buildType == "debug") { + platforms.add("android-x86") + platforms.add("android-x64") + } + + // The task name depends on plugin properties, which are not available + // at this point + project.getGradle().afterProject { + def taskName = "cargokitCargoBuild${project.cargokit.libname.capitalize()}${buildType.capitalize()}"; + + if (project.tasks.findByName(taskName)) { + return + } + + if (plugin.project.android.ndkVersion == null) { + throw new GradleException("Please set 'android.ndkVersion' in 'app/build.gradle'.") + } + + def task = project.tasks.create(taskName, CargoKitBuildTask.class) { + buildMode = variant.buildType.name + buildDir = cargoBuildDir + outputDir = cargoOutputDir + ndkVersion = plugin.project.android.ndkVersion + sdkDirectory = plugin.project.android.sdkDirectory + minSdkVersion = plugin.project.android.defaultConfig.minSdkVersion.apiLevel as int + compileSdkVersion = plugin.project.android.compileSdkVersion.substring(8) as int + targetPlatforms = platforms + pluginFile = CargoKitPlugin.file + } + def onTask = { newTask -> + if (newTask.name == "merge${buildType.capitalize()}NativeLibs") { + newTask.dependsOn task + // Fix gradle 7.4.2 not picking up JNI library changes + newTask.outputs.upToDateWhen { false } + } + } + project.tasks.each onTask + project.tasks.whenTaskAdded onTask + } + } + } +} diff --git a/useragent/rust_builder/cargokit/run_build_tool.cmd b/useragent/rust_builder/cargokit/run_build_tool.cmd index c45d0aa..dd8ee90 100755 --- a/useragent/rust_builder/cargokit/run_build_tool.cmd +++ b/useragent/rust_builder/cargokit/run_build_tool.cmd @@ -1,91 +1,91 @@ -@echo off -setlocal - -setlocal ENABLEDELAYEDEXPANSION - -SET BASEDIR=%~dp0 - -if not exist "%CARGOKIT_TOOL_TEMP_DIR%" ( - mkdir "%CARGOKIT_TOOL_TEMP_DIR%" -) -cd /D "%CARGOKIT_TOOL_TEMP_DIR%" - -SET BUILD_TOOL_PKG_DIR=%BASEDIR%build_tool -SET DART=%FLUTTER_ROOT%\bin\cache\dart-sdk\bin\dart - -set BUILD_TOOL_PKG_DIR_POSIX=%BUILD_TOOL_PKG_DIR:\=/% - -( - echo name: build_tool_runner - echo version: 1.0.0 - echo publish_to: none - echo. - echo environment: - echo sdk: '^>=3.0.0 ^<4.0.0' - echo. - echo dependencies: - echo build_tool: - echo path: %BUILD_TOOL_PKG_DIR_POSIX% -) >pubspec.yaml - -if not exist bin ( - mkdir bin -) - -( - echo import 'package:build_tool/build_tool.dart' as build_tool; - echo void main^(List^ args^) ^{ - echo build_tool.runMain^(args^); - echo ^} -) >bin\build_tool_runner.dart - -SET PRECOMPILED=bin\build_tool_runner.dill - -REM To detect changes in package we compare output of DIR /s (recursive) -set PREV_PACKAGE_INFO=.dart_tool\package_info.prev -set CUR_PACKAGE_INFO=.dart_tool\package_info.cur - -DIR "%BUILD_TOOL_PKG_DIR%" /s > "%CUR_PACKAGE_INFO%_orig" - -REM Last line in dir output is free space on harddrive. That is bound to -REM change between invocation so we need to remove it -( - Set "Line=" - For /F "UseBackQ Delims=" %%A In ("%CUR_PACKAGE_INFO%_orig") Do ( - SetLocal EnableDelayedExpansion - If Defined Line Echo !Line! - EndLocal - Set "Line=%%A") -) >"%CUR_PACKAGE_INFO%" -DEL "%CUR_PACKAGE_INFO%_orig" - -REM Compare current directory listing with previous -FC /B "%CUR_PACKAGE_INFO%" "%PREV_PACKAGE_INFO%" > nul 2>&1 - -If %ERRORLEVEL% neq 0 ( - REM Changed - copy current to previous and remove precompiled kernel - if exist "%PREV_PACKAGE_INFO%" ( - DEL "%PREV_PACKAGE_INFO%" - ) - MOVE /Y "%CUR_PACKAGE_INFO%" "%PREV_PACKAGE_INFO%" - if exist "%PRECOMPILED%" ( - DEL "%PRECOMPILED%" - ) -) - -REM There is no CUR_PACKAGE_INFO it was renamed in previous step to %PREV_PACKAGE_INFO% -REM which means we need to do pub get and precompile -if not exist "%PRECOMPILED%" ( - echo Running pub get in "%cd%" - "%DART%" pub get --no-precompile - "%DART%" compile kernel bin/build_tool_runner.dart -) - -"%DART%" "%PRECOMPILED%" %* - -REM 253 means invalid snapshot version. -If %ERRORLEVEL% equ 253 ( - "%DART%" pub get --no-precompile - "%DART%" compile kernel bin/build_tool_runner.dart - "%DART%" "%PRECOMPILED%" %* -) +@echo off +setlocal + +setlocal ENABLEDELAYEDEXPANSION + +SET BASEDIR=%~dp0 + +if not exist "%CARGOKIT_TOOL_TEMP_DIR%" ( + mkdir "%CARGOKIT_TOOL_TEMP_DIR%" +) +cd /D "%CARGOKIT_TOOL_TEMP_DIR%" + +SET BUILD_TOOL_PKG_DIR=%BASEDIR%build_tool +SET DART=%FLUTTER_ROOT%\bin\cache\dart-sdk\bin\dart + +set BUILD_TOOL_PKG_DIR_POSIX=%BUILD_TOOL_PKG_DIR:\=/% + +( + echo name: build_tool_runner + echo version: 1.0.0 + echo publish_to: none + echo. + echo environment: + echo sdk: '^>=3.0.0 ^<4.0.0' + echo. + echo dependencies: + echo build_tool: + echo path: %BUILD_TOOL_PKG_DIR_POSIX% +) >pubspec.yaml + +if not exist bin ( + mkdir bin +) + +( + echo import 'package:build_tool/build_tool.dart' as build_tool; + echo void main^(List^ args^) ^{ + echo build_tool.runMain^(args^); + echo ^} +) >bin\build_tool_runner.dart + +SET PRECOMPILED=bin\build_tool_runner.dill + +REM To detect changes in package we compare output of DIR /s (recursive) +set PREV_PACKAGE_INFO=.dart_tool\package_info.prev +set CUR_PACKAGE_INFO=.dart_tool\package_info.cur + +DIR "%BUILD_TOOL_PKG_DIR%" /s > "%CUR_PACKAGE_INFO%_orig" + +REM Last line in dir output is free space on harddrive. That is bound to +REM change between invocation so we need to remove it +( + Set "Line=" + For /F "UseBackQ Delims=" %%A In ("%CUR_PACKAGE_INFO%_orig") Do ( + SetLocal EnableDelayedExpansion + If Defined Line Echo !Line! + EndLocal + Set "Line=%%A") +) >"%CUR_PACKAGE_INFO%" +DEL "%CUR_PACKAGE_INFO%_orig" + +REM Compare current directory listing with previous +FC /B "%CUR_PACKAGE_INFO%" "%PREV_PACKAGE_INFO%" > nul 2>&1 + +If %ERRORLEVEL% neq 0 ( + REM Changed - copy current to previous and remove precompiled kernel + if exist "%PREV_PACKAGE_INFO%" ( + DEL "%PREV_PACKAGE_INFO%" + ) + MOVE /Y "%CUR_PACKAGE_INFO%" "%PREV_PACKAGE_INFO%" + if exist "%PRECOMPILED%" ( + DEL "%PRECOMPILED%" + ) +) + +REM There is no CUR_PACKAGE_INFO it was renamed in previous step to %PREV_PACKAGE_INFO% +REM which means we need to do pub get and precompile +if not exist "%PRECOMPILED%" ( + echo Running pub get in "%cd%" + "%DART%" pub get --no-precompile + "%DART%" compile kernel bin/build_tool_runner.dart +) + +"%DART%" "%PRECOMPILED%" %* + +REM 253 means invalid snapshot version. +If %ERRORLEVEL% equ 253 ( + "%DART%" pub get --no-precompile + "%DART%" compile kernel bin/build_tool_runner.dart + "%DART%" "%PRECOMPILED%" %* +) diff --git a/useragent/rust_builder/cargokit/run_build_tool.sh b/useragent/rust_builder/cargokit/run_build_tool.sh index 24b0ed8..460cfa4 100755 --- a/useragent/rust_builder/cargokit/run_build_tool.sh +++ b/useragent/rust_builder/cargokit/run_build_tool.sh @@ -1,99 +1,99 @@ -#!/usr/bin/env bash - -set -e - -BASEDIR=$(dirname "$0") - -mkdir -p "$CARGOKIT_TOOL_TEMP_DIR" - -cd "$CARGOKIT_TOOL_TEMP_DIR" - -# Write a very simple bin package in temp folder that depends on build_tool package -# from Cargokit. This is done to ensure that we don't pollute Cargokit folder -# with .dart_tool contents. - -BUILD_TOOL_PKG_DIR="$BASEDIR/build_tool" - -if [[ -z $FLUTTER_ROOT ]]; then # not defined - DART=dart -else - DART="$FLUTTER_ROOT/bin/cache/dart-sdk/bin/dart" -fi - -cat << EOF > "pubspec.yaml" -name: build_tool_runner -version: 1.0.0 -publish_to: none - -environment: - sdk: '>=3.0.0 <4.0.0' - -dependencies: - build_tool: - path: "$BUILD_TOOL_PKG_DIR" -EOF - -mkdir -p "bin" - -cat << EOF > "bin/build_tool_runner.dart" -import 'package:build_tool/build_tool.dart' as build_tool; -void main(List args) { - build_tool.runMain(args); -} -EOF - -# Create alias for `shasum` if it does not exist and `sha1sum` exists -if ! [ -x "$(command -v shasum)" ] && [ -x "$(command -v sha1sum)" ]; then - shopt -s expand_aliases - alias shasum="sha1sum" -fi - -# Dart run will not cache any package that has a path dependency, which -# is the case for our build_tool_runner. So instead we precompile the package -# ourselves. -# To invalidate the cached kernel we use the hash of ls -LR of the build_tool -# package directory. This should be good enough, as the build_tool package -# itself is not meant to have any path dependencies. - -if [[ "$OSTYPE" == "darwin"* ]]; then - PACKAGE_HASH=$(ls -lTR "$BUILD_TOOL_PKG_DIR" | shasum) -else - PACKAGE_HASH=$(ls -lR --full-time "$BUILD_TOOL_PKG_DIR" | shasum) -fi - -PACKAGE_HASH_FILE=".package_hash" - -if [ -f "$PACKAGE_HASH_FILE" ]; then - EXISTING_HASH=$(cat "$PACKAGE_HASH_FILE") - if [ "$PACKAGE_HASH" != "$EXISTING_HASH" ]; then - rm "$PACKAGE_HASH_FILE" - fi -fi - -# Run pub get if needed. -if [ ! -f "$PACKAGE_HASH_FILE" ]; then - "$DART" pub get --no-precompile - "$DART" compile kernel bin/build_tool_runner.dart - echo "$PACKAGE_HASH" > "$PACKAGE_HASH_FILE" -fi - -# Rebuild the tool if it was deleted by Android Studio -if [ ! -f "bin/build_tool_runner.dill" ]; then - "$DART" compile kernel bin/build_tool_runner.dart -fi - -set +e - -"$DART" bin/build_tool_runner.dill "$@" - -exit_code=$? - -# 253 means invalid snapshot version. -if [ $exit_code == 253 ]; then - "$DART" pub get --no-precompile - "$DART" compile kernel bin/build_tool_runner.dart - "$DART" bin/build_tool_runner.dill "$@" - exit_code=$? -fi - -exit $exit_code +#!/usr/bin/env bash + +set -e + +BASEDIR=$(dirname "$0") + +mkdir -p "$CARGOKIT_TOOL_TEMP_DIR" + +cd "$CARGOKIT_TOOL_TEMP_DIR" + +# Write a very simple bin package in temp folder that depends on build_tool package +# from Cargokit. This is done to ensure that we don't pollute Cargokit folder +# with .dart_tool contents. + +BUILD_TOOL_PKG_DIR="$BASEDIR/build_tool" + +if [[ -z $FLUTTER_ROOT ]]; then # not defined + DART=dart +else + DART="$FLUTTER_ROOT/bin/cache/dart-sdk/bin/dart" +fi + +cat << EOF > "pubspec.yaml" +name: build_tool_runner +version: 1.0.0 +publish_to: none + +environment: + sdk: '>=3.0.0 <4.0.0' + +dependencies: + build_tool: + path: "$BUILD_TOOL_PKG_DIR" +EOF + +mkdir -p "bin" + +cat << EOF > "bin/build_tool_runner.dart" +import 'package:build_tool/build_tool.dart' as build_tool; +void main(List args) { + build_tool.runMain(args); +} +EOF + +# Create alias for `shasum` if it does not exist and `sha1sum` exists +if ! [ -x "$(command -v shasum)" ] && [ -x "$(command -v sha1sum)" ]; then + shopt -s expand_aliases + alias shasum="sha1sum" +fi + +# Dart run will not cache any package that has a path dependency, which +# is the case for our build_tool_runner. So instead we precompile the package +# ourselves. +# To invalidate the cached kernel we use the hash of ls -LR of the build_tool +# package directory. This should be good enough, as the build_tool package +# itself is not meant to have any path dependencies. + +if [[ "$OSTYPE" == "darwin"* ]]; then + PACKAGE_HASH=$(ls -lTR "$BUILD_TOOL_PKG_DIR" | shasum) +else + PACKAGE_HASH=$(ls -lR --full-time "$BUILD_TOOL_PKG_DIR" | shasum) +fi + +PACKAGE_HASH_FILE=".package_hash" + +if [ -f "$PACKAGE_HASH_FILE" ]; then + EXISTING_HASH=$(cat "$PACKAGE_HASH_FILE") + if [ "$PACKAGE_HASH" != "$EXISTING_HASH" ]; then + rm "$PACKAGE_HASH_FILE" + fi +fi + +# Run pub get if needed. +if [ ! -f "$PACKAGE_HASH_FILE" ]; then + "$DART" pub get --no-precompile + "$DART" compile kernel bin/build_tool_runner.dart + echo "$PACKAGE_HASH" > "$PACKAGE_HASH_FILE" +fi + +# Rebuild the tool if it was deleted by Android Studio +if [ ! -f "bin/build_tool_runner.dill" ]; then + "$DART" compile kernel bin/build_tool_runner.dart +fi + +set +e + +"$DART" bin/build_tool_runner.dill "$@" + +exit_code=$? + +# 253 means invalid snapshot version. +if [ $exit_code == 253 ]; then + "$DART" pub get --no-precompile + "$DART" compile kernel bin/build_tool_runner.dart + "$DART" bin/build_tool_runner.dill "$@" + exit_code=$? +fi + +exit $exit_code diff --git a/useragent/rust_builder/ios/Classes/dummy_file.c b/useragent/rust_builder/ios/Classes/dummy_file.c index e06dab9..880cc23 100644 --- a/useragent/rust_builder/ios/Classes/dummy_file.c +++ b/useragent/rust_builder/ios/Classes/dummy_file.c @@ -1 +1 @@ -// This is an empty file to force CocoaPods to create a framework. +// This is an empty file to force CocoaPods to create a framework. diff --git a/useragent/rust_builder/ios/rust_lib_arbiter.podspec b/useragent/rust_builder/ios/rust_lib_arbiter.podspec index 2e27d0b..aaeac7a 100644 --- a/useragent/rust_builder/ios/rust_lib_arbiter.podspec +++ b/useragent/rust_builder/ios/rust_lib_arbiter.podspec @@ -1,45 +1,45 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint rust_lib_arbiter.podspec` to validate before publishing. -# -Pod::Spec.new do |s| - s.name = 'rust_lib_arbiter' - s.version = '0.0.1' - s.summary = 'A new Flutter FFI plugin project.' - s.description = <<-DESC -A new Flutter FFI plugin project. - DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - - # This will ensure the source files in Classes/ are included in the native - # builds of apps using this FFI plugin. Podspec does not support relative - # paths, so Classes contains a forwarder C file that relatively imports - # `../src/*` so that the C sources can be shared among all target platforms. - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.dependency 'Flutter' - s.platform = :ios, '11.0' - - # Flutter.framework does not contain a i386 slice. - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } - s.swift_version = '5.0' - - s.script_phase = { - :name => 'Build Rust library', - # First argument is relative path to the `rust` folder, second is name of rust library - :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../../rust rust_lib_arbiter', - :execution_position => :before_compile, - :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], - # Let XCode know that the static library referenced in -force_load below is - # created by this build step. - :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_arbiter.a"], - } - s.pod_target_xcconfig = { - 'DEFINES_MODULE' => 'YES', - # Flutter.framework does not contain a i386 slice. - 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', - 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_arbiter.a', - } +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint rust_lib_arbiter.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'rust_lib_arbiter' + s.version = '0.0.1' + s.summary = 'A new Flutter FFI plugin project.' + s.description = <<-DESC +A new Flutter FFI plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + + # This will ensure the source files in Classes/ are included in the native + # builds of apps using this FFI plugin. Podspec does not support relative + # paths, so Classes contains a forwarder C file that relatively imports + # `../src/*` so that the C sources can be shared among all target platforms. + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'Flutter' + s.platform = :ios, '11.0' + + # Flutter.framework does not contain a i386 slice. + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } + s.swift_version = '5.0' + + s.script_phase = { + :name => 'Build Rust library', + # First argument is relative path to the `rust` folder, second is name of rust library + :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../../rust rust_lib_arbiter', + :execution_position => :before_compile, + :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], + # Let XCode know that the static library referenced in -force_load below is + # created by this build step. + :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_arbiter.a"], + } + s.pod_target_xcconfig = { + 'DEFINES_MODULE' => 'YES', + # Flutter.framework does not contain a i386 slice. + 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', + 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_arbiter.a', + } end \ No newline at end of file diff --git a/useragent/rust_builder/linux/CMakeLists.txt b/useragent/rust_builder/linux/CMakeLists.txt index 15b5dd9..b788bd1 100644 --- a/useragent/rust_builder/linux/CMakeLists.txt +++ b/useragent/rust_builder/linux/CMakeLists.txt @@ -1,19 +1,19 @@ -# The Flutter tooling requires that developers have CMake 3.10 or later -# installed. You should not increase this version, as doing so will cause -# the plugin to fail to compile for some customers of the plugin. -cmake_minimum_required(VERSION 3.10) - -# Project-level configuration. -set(PROJECT_NAME "rust_lib_arbiter") -project(${PROJECT_NAME} LANGUAGES CXX) - -include("../cargokit/cmake/cargokit.cmake") -apply_cargokit(${PROJECT_NAME} ../../rust rust_lib_arbiter "") - -# List of absolute paths to libraries that should be bundled with the plugin. -# This list could contain prebuilt libraries, or libraries created by an -# external build triggered from this build file. -set(rust_lib_arbiter_bundled_libraries - "${${PROJECT_NAME}_cargokit_lib}" - PARENT_SCOPE -) +# The Flutter tooling requires that developers have CMake 3.10 or later +# installed. You should not increase this version, as doing so will cause +# the plugin to fail to compile for some customers of the plugin. +cmake_minimum_required(VERSION 3.10) + +# Project-level configuration. +set(PROJECT_NAME "rust_lib_arbiter") +project(${PROJECT_NAME} LANGUAGES CXX) + +include("../cargokit/cmake/cargokit.cmake") +apply_cargokit(${PROJECT_NAME} ../../rust rust_lib_arbiter "") + +# List of absolute paths to libraries that should be bundled with the plugin. +# This list could contain prebuilt libraries, or libraries created by an +# external build triggered from this build file. +set(rust_lib_arbiter_bundled_libraries + "${${PROJECT_NAME}_cargokit_lib}" + PARENT_SCOPE +) diff --git a/useragent/rust_builder/macos/Classes/dummy_file.c b/useragent/rust_builder/macos/Classes/dummy_file.c index e06dab9..880cc23 100644 --- a/useragent/rust_builder/macos/Classes/dummy_file.c +++ b/useragent/rust_builder/macos/Classes/dummy_file.c @@ -1 +1 @@ -// This is an empty file to force CocoaPods to create a framework. +// This is an empty file to force CocoaPods to create a framework. diff --git a/useragent/rust_builder/macos/rust_lib_arbiter.podspec b/useragent/rust_builder/macos/rust_lib_arbiter.podspec index a623c95..3fc06dc 100644 --- a/useragent/rust_builder/macos/rust_lib_arbiter.podspec +++ b/useragent/rust_builder/macos/rust_lib_arbiter.podspec @@ -1,44 +1,44 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint rust_lib_arbiter.podspec` to validate before publishing. -# -Pod::Spec.new do |s| - s.name = 'rust_lib_arbiter' - s.version = '0.0.1' - s.summary = 'A new Flutter FFI plugin project.' - s.description = <<-DESC -A new Flutter FFI plugin project. - DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - - # This will ensure the source files in Classes/ are included in the native - # builds of apps using this FFI plugin. Podspec does not support relative - # paths, so Classes contains a forwarder C file that relatively imports - # `../src/*` so that the C sources can be shared among all target platforms. - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.dependency 'FlutterMacOS' - - s.platform = :osx, '10.11' - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } - s.swift_version = '5.0' - - s.script_phase = { - :name => 'Build Rust library', - # First argument is relative path to the `rust` folder, second is name of rust library - :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../../rust rust_lib_arbiter', - :execution_position => :before_compile, - :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], - # Let XCode know that the static library referenced in -force_load below is - # created by this build step. - :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_arbiter.a"], - } - s.pod_target_xcconfig = { - 'DEFINES_MODULE' => 'YES', - # Flutter.framework does not contain a i386 slice. - 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', - 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_arbiter.a', - } +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint rust_lib_arbiter.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'rust_lib_arbiter' + s.version = '0.0.1' + s.summary = 'A new Flutter FFI plugin project.' + s.description = <<-DESC +A new Flutter FFI plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + + # This will ensure the source files in Classes/ are included in the native + # builds of apps using this FFI plugin. Podspec does not support relative + # paths, so Classes contains a forwarder C file that relatively imports + # `../src/*` so that the C sources can be shared among all target platforms. + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'FlutterMacOS' + + s.platform = :osx, '10.11' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.swift_version = '5.0' + + s.script_phase = { + :name => 'Build Rust library', + # First argument is relative path to the `rust` folder, second is name of rust library + :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../../rust rust_lib_arbiter', + :execution_position => :before_compile, + :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'], + # Let XCode know that the static library referenced in -force_load below is + # created by this build step. + :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_arbiter.a"], + } + s.pod_target_xcconfig = { + 'DEFINES_MODULE' => 'YES', + # Flutter.framework does not contain a i386 slice. + 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', + 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_arbiter.a', + } end \ No newline at end of file diff --git a/useragent/rust_builder/pubspec.yaml b/useragent/rust_builder/pubspec.yaml index 98ebd2c..99068bf 100644 --- a/useragent/rust_builder/pubspec.yaml +++ b/useragent/rust_builder/pubspec.yaml @@ -1,34 +1,34 @@ -name: rust_lib_arbiter -description: "Utility to build Rust code" -version: 0.0.1 -publish_to: none - -environment: - sdk: '>=3.3.0 <4.0.0' - flutter: '>=3.3.0' - -dependencies: - flutter: - sdk: flutter - plugin_platform_interface: ^2.0.2 - -dev_dependencies: - ffi: ^2.0.2 - ffigen: ^11.0.0 - flutter_test: - sdk: flutter - flutter_lints: ^2.0.0 - -flutter: - plugin: - platforms: - android: - ffiPlugin: true - ios: - ffiPlugin: true - linux: - ffiPlugin: true - macos: - ffiPlugin: true - windows: - ffiPlugin: true +name: rust_lib_arbiter +description: "Utility to build Rust code" +version: 0.0.1 +publish_to: none + +environment: + sdk: '>=3.3.0 <4.0.0' + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.0.2 + +dev_dependencies: + ffi: ^2.0.2 + ffigen: ^11.0.0 + flutter_test: + sdk: flutter + flutter_lints: ^2.0.0 + +flutter: + plugin: + platforms: + android: + ffiPlugin: true + ios: + ffiPlugin: true + linux: + ffiPlugin: true + macos: + ffiPlugin: true + windows: + ffiPlugin: true diff --git a/useragent/rust_builder/windows/.gitignore b/useragent/rust_builder/windows/.gitignore index b3eb2be..808064a 100644 --- a/useragent/rust_builder/windows/.gitignore +++ b/useragent/rust_builder/windows/.gitignore @@ -1,17 +1,17 @@ -flutter/ - -# Visual Studio user-specific files. -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual Studio build-related files. -x64/ -x86/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ +flutter/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/useragent/rust_builder/windows/CMakeLists.txt b/useragent/rust_builder/windows/CMakeLists.txt index 7743fd1..54ce0e8 100644 --- a/useragent/rust_builder/windows/CMakeLists.txt +++ b/useragent/rust_builder/windows/CMakeLists.txt @@ -1,20 +1,20 @@ -# The Flutter tooling requires that developers have a version of Visual Studio -# installed that includes CMake 3.14 or later. You should not increase this -# version, as doing so will cause the plugin to fail to compile for some -# customers of the plugin. -cmake_minimum_required(VERSION 3.14) - -# Project-level configuration. -set(PROJECT_NAME "rust_lib_arbiter") -project(${PROJECT_NAME} LANGUAGES CXX) - -include("../cargokit/cmake/cargokit.cmake") -apply_cargokit(${PROJECT_NAME} ../../../../../../rust rust_lib_arbiter "") - -# List of absolute paths to libraries that should be bundled with the plugin. -# This list could contain prebuilt libraries, or libraries created by an -# external build triggered from this build file. -set(rust_lib_arbiter_bundled_libraries - "${${PROJECT_NAME}_cargokit_lib}" - PARENT_SCOPE -) +# The Flutter tooling requires that developers have a version of Visual Studio +# installed that includes CMake 3.14 or later. You should not increase this +# version, as doing so will cause the plugin to fail to compile for some +# customers of the plugin. +cmake_minimum_required(VERSION 3.14) + +# Project-level configuration. +set(PROJECT_NAME "rust_lib_arbiter") +project(${PROJECT_NAME} LANGUAGES CXX) + +include("../cargokit/cmake/cargokit.cmake") +apply_cargokit(${PROJECT_NAME} ../../../../../../rust rust_lib_arbiter "") + +# List of absolute paths to libraries that should be bundled with the plugin. +# This list could contain prebuilt libraries, or libraries created by an +# external build triggered from this build file. +set(rust_lib_arbiter_bundled_libraries + "${${PROJECT_NAME}_cargokit_lib}" + PARENT_SCOPE +) diff --git a/useragent/test/screens/dashboard/clients/details/client_details_screen_test.dart b/useragent/test/screens/dashboard/clients/details/client_details_screen_test.dart index 64c974d..f58f943 100644 --- a/useragent/test/screens/dashboard/clients/details/client_details_screen_test.dart +++ b/useragent/test/screens/dashboard/clients/details/client_details_screen_test.dart @@ -1,69 +1,69 @@ -import 'package:arbiter/proto/evm.pb.dart'; -import 'package:arbiter/proto/shared/client.pb.dart'; -import 'package:arbiter/proto/user_agent/sdk_client.pb.dart'; -import 'package:arbiter/providers/evm/evm.dart'; -import 'package:arbiter/providers/sdk_clients/list.dart'; -import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; -import 'package:arbiter/screens/dashboard/clients/details/client_details.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; - -class _FakeEvm extends Evm { - _FakeEvm(this.wallets); - - final List wallets; - - @override - Future?> build() async => wallets; -} - -class _FakeWalletAccessRepository implements ClientWalletAccessRepository { - @override - Future> fetchSelectedWalletIds(int clientId) async => {1}; - - @override - Future saveSelectedWalletIds(int clientId, Set walletIds) async {} -} - -void main() { - testWidgets('renders client summary and wallet access controls', ( - tester, - ) async { - final client = Entry( - id: 42, - createdAt: 1, - info: ClientInfo( - name: 'Safe Wallet SDK', - version: '1.3.0', - description: 'Primary signing client', - ), - pubkey: List.filled(32, 17), - ); - - final wallets = [ - WalletEntry(address: List.filled(20, 1)), - WalletEntry(address: List.filled(20, 2)), - ]; - - await tester.pumpWidget( - ProviderScope( - overrides: [ - sdkClientsProvider.overrideWith((ref) async => [client]), - evmProvider.overrideWith(() => _FakeEvm(wallets)), - clientWalletAccessRepositoryProvider.overrideWithValue( - _FakeWalletAccessRepository(), - ), - ], - child: const MaterialApp(home: ClientDetailsScreen(clientId: 42)), - ), - ); - - await tester.pumpAndSettle(); - - expect(find.text('Safe Wallet SDK'), findsOneWidget); - expect(find.text('Wallet access'), findsOneWidget); - expect(find.textContaining('0x0101'), findsOneWidget); - expect(find.widgetWithText(FilledButton, 'Save changes'), findsOneWidget); - }); -} +import 'package:arbiter/proto/evm.pb.dart'; +import 'package:arbiter/proto/shared/client.pb.dart'; +import 'package:arbiter/proto/user_agent/sdk_client.pb.dart'; +import 'package:arbiter/providers/evm/evm.dart'; +import 'package:arbiter/providers/sdk_clients/list.dart'; +import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; +import 'package:arbiter/screens/dashboard/clients/details/client_details.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +class _FakeEvm extends Evm { + _FakeEvm(this.wallets); + + final List wallets; + + @override + Future?> build() async => wallets; +} + +class _FakeWalletAccessRepository implements ClientWalletAccessRepository { + @override + Future> fetchSelectedWalletIds(int clientId) async => {1}; + + @override + Future saveSelectedWalletIds(int clientId, Set walletIds) async {} +} + +void main() { + testWidgets('renders client summary and wallet access controls', ( + tester, + ) async { + final client = Entry( + id: 42, + createdAt: 1, + info: ClientInfo( + name: 'Safe Wallet SDK', + version: '1.3.0', + description: 'Primary signing client', + ), + pubkey: List.filled(32, 17), + ); + + final wallets = [ + WalletEntry(address: List.filled(20, 1)), + WalletEntry(address: List.filled(20, 2)), + ]; + + await tester.pumpWidget( + ProviderScope( + overrides: [ + sdkClientsProvider.overrideWith((ref) async => [client]), + evmProvider.overrideWith(() => _FakeEvm(wallets)), + clientWalletAccessRepositoryProvider.overrideWithValue( + _FakeWalletAccessRepository(), + ), + ], + child: const MaterialApp(home: ClientDetailsScreen(clientId: 42)), + ), + ); + + await tester.pumpAndSettle(); + + expect(find.text('Safe Wallet SDK'), findsOneWidget); + expect(find.text('Wallet access'), findsOneWidget); + expect(find.textContaining('0x0101'), findsOneWidget); + expect(find.widgetWithText(FilledButton, 'Save changes'), findsOneWidget); + }); +} diff --git a/useragent/test/screens/dashboard/clients/details/client_wallet_access_controller_test.dart b/useragent/test/screens/dashboard/clients/details/client_wallet_access_controller_test.dart index d916eab..c415a55 100644 --- a/useragent/test/screens/dashboard/clients/details/client_wallet_access_controller_test.dart +++ b/useragent/test/screens/dashboard/clients/details/client_wallet_access_controller_test.dart @@ -1,105 +1,105 @@ -import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; -import 'package:hooks_riverpod/experimental/mutation.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:flutter_test/flutter_test.dart'; - -class _SuccessRepository implements ClientWalletAccessRepository { - Set? savedWalletIds; - - @override - Future> fetchSelectedWalletIds(int clientId) async => {1}; - - @override - Future saveSelectedWalletIds(int clientId, Set walletIds) async { - savedWalletIds = walletIds; - } -} - -class _FailureRepository implements ClientWalletAccessRepository { - @override - Future> fetchSelectedWalletIds(int clientId) async => const {}; - - @override - Future saveSelectedWalletIds(int clientId, Set walletIds) async { - throw UnsupportedError('Not supported yet: $walletIds'); - } -} - -void main() { - test('save updates the original selection after toggles', () async { - final repository = _SuccessRepository(); - final container = ProviderContainer( - overrides: [ - clientWalletAccessRepositoryProvider.overrideWithValue(repository), - ], - ); - addTearDown(container.dispose); - - final controller = container.read( - clientWalletAccessControllerProvider(42).notifier, - ); - await container.read(clientWalletAccessSelectionProvider(42).future); - controller.toggleWallet(2); - - expect( - container - .read(clientWalletAccessControllerProvider(42)) - .selectedWalletIds, - {1, 2}, - ); - expect( - container.read(clientWalletAccessControllerProvider(42)).hasChanges, - isTrue, - ); - - await executeSaveClientWalletAccess(container, clientId: 42); - - expect(repository.savedWalletIds, {1, 2}); - expect( - container - .read(clientWalletAccessControllerProvider(42)) - .originalWalletIds, - {1, 2}, - ); - expect( - container.read(clientWalletAccessControllerProvider(42)).hasChanges, - isFalse, - ); - }); - - test('save failure preserves edits and exposes a mutation error', () async { - final container = ProviderContainer( - overrides: [ - clientWalletAccessRepositoryProvider.overrideWithValue( - _FailureRepository(), - ), - ], - ); - addTearDown(container.dispose); - - final controller = container.read( - clientWalletAccessControllerProvider(42).notifier, - ); - await container.read(clientWalletAccessSelectionProvider(42).future); - controller.toggleWallet(3); - await expectLater( - executeSaveClientWalletAccess(container, clientId: 42), - throwsUnsupportedError, - ); - - expect( - container - .read(clientWalletAccessControllerProvider(42)) - .selectedWalletIds, - {3}, - ); - expect( - container.read(clientWalletAccessControllerProvider(42)).hasChanges, - isTrue, - ); - expect( - container.read(saveClientWalletAccessMutation(42)), - isA>(), - ); - }); -} +import 'package:arbiter/providers/sdk_clients/wallet_access.dart'; +import 'package:hooks_riverpod/experimental/mutation.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:flutter_test/flutter_test.dart'; + +class _SuccessRepository implements ClientWalletAccessRepository { + Set? savedWalletIds; + + @override + Future> fetchSelectedWalletIds(int clientId) async => {1}; + + @override + Future saveSelectedWalletIds(int clientId, Set walletIds) async { + savedWalletIds = walletIds; + } +} + +class _FailureRepository implements ClientWalletAccessRepository { + @override + Future> fetchSelectedWalletIds(int clientId) async => const {}; + + @override + Future saveSelectedWalletIds(int clientId, Set walletIds) async { + throw UnsupportedError('Not supported yet: $walletIds'); + } +} + +void main() { + test('save updates the original selection after toggles', () async { + final repository = _SuccessRepository(); + final container = ProviderContainer( + overrides: [ + clientWalletAccessRepositoryProvider.overrideWithValue(repository), + ], + ); + addTearDown(container.dispose); + + final controller = container.read( + clientWalletAccessControllerProvider(42).notifier, + ); + await container.read(clientWalletAccessSelectionProvider(42).future); + controller.toggleWallet(2); + + expect( + container + .read(clientWalletAccessControllerProvider(42)) + .selectedWalletIds, + {1, 2}, + ); + expect( + container.read(clientWalletAccessControllerProvider(42)).hasChanges, + isTrue, + ); + + await executeSaveClientWalletAccess(container, clientId: 42); + + expect(repository.savedWalletIds, {1, 2}); + expect( + container + .read(clientWalletAccessControllerProvider(42)) + .originalWalletIds, + {1, 2}, + ); + expect( + container.read(clientWalletAccessControllerProvider(42)).hasChanges, + isFalse, + ); + }); + + test('save failure preserves edits and exposes a mutation error', () async { + final container = ProviderContainer( + overrides: [ + clientWalletAccessRepositoryProvider.overrideWithValue( + _FailureRepository(), + ), + ], + ); + addTearDown(container.dispose); + + final controller = container.read( + clientWalletAccessControllerProvider(42).notifier, + ); + await container.read(clientWalletAccessSelectionProvider(42).future); + controller.toggleWallet(3); + await expectLater( + executeSaveClientWalletAccess(container, clientId: 42), + throwsUnsupportedError, + ); + + expect( + container + .read(clientWalletAccessControllerProvider(42)) + .selectedWalletIds, + {3}, + ); + expect( + container.read(clientWalletAccessControllerProvider(42)).hasChanges, + isTrue, + ); + expect( + container.read(saveClientWalletAccessMutation(42)), + isA>(), + ); + }); +} diff --git a/useragent/test_driver/integration_test.dart b/useragent/test_driver/integration_test.dart index b38629c..2d90b9b 100644 --- a/useragent/test_driver/integration_test.dart +++ b/useragent/test_driver/integration_test.dart @@ -1,3 +1,3 @@ -import 'package:integration_test/integration_test_driver.dart'; - -Future main() => integrationDriver(); +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/useragent/web/index.html b/useragent/web/index.html index 1f09871..f79f247 100644 --- a/useragent/web/index.html +++ b/useragent/web/index.html @@ -1,38 +1,38 @@ - - - - - - - - - - - - - - - - - - - - useragent - - - - - - + + + + + + + + + + + + + + + + + + + + useragent + + + + + + diff --git a/useragent/web/manifest.json b/useragent/web/manifest.json index a50a793..44405dd 100644 --- a/useragent/web/manifest.json +++ b/useragent/web/manifest.json @@ -1,35 +1,35 @@ -{ - "name": "useragent", - "short_name": "useragent", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "icons/Icon-maskable-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "icons/Icon-maskable-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ] -} +{ + "name": "useragent", + "short_name": "useragent", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/useragent/windows/.gitignore b/useragent/windows/.gitignore index d492d0d..ec4098a 100644 --- a/useragent/windows/.gitignore +++ b/useragent/windows/.gitignore @@ -1,17 +1,17 @@ -flutter/ephemeral/ - -# Visual Studio user-specific files. -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual Studio build-related files. -x64/ -x86/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/useragent/windows/CMakeLists.txt b/useragent/windows/CMakeLists.txt index f41a1a4..496881d 100644 --- a/useragent/windows/CMakeLists.txt +++ b/useragent/windows/CMakeLists.txt @@ -1,108 +1,108 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.14) -project(useragent LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "useragent") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(VERSION 3.14...3.25) - -# Define build configuration option. -get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() -# Define settings for the Profile build mode. -set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") -set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") -set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") -set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") - -# Use Unicode for all projects. -add_definitions(-DUNICODE -D_UNICODE) - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# Support files are copied into place next to the executable, so that it can -# run in place. This is done instead of making a separate bundle (as on Linux) -# so that building and running from within Visual Studio will work. -set(BUILD_BUNDLE_DIR "$") -# Make the "install" step default, as it's required to run. -set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(useragent LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "useragent") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/useragent/windows/flutter/CMakeLists.txt b/useragent/windows/flutter/CMakeLists.txt index 903f489..efb62eb 100644 --- a/useragent/windows/flutter/CMakeLists.txt +++ b/useragent/windows/flutter/CMakeLists.txt @@ -1,109 +1,109 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.14) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. -set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") - -# Set fallback configurations for older versions of the flutter tool. -if (NOT DEFINED FLUTTER_TARGET_PLATFORM) - set(FLUTTER_TARGET_PLATFORM "windows-x64") -endif() - -# === Flutter Library === -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" - "flutter_texture_registrar.h" -) -list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") -add_dependencies(flutter flutter_assemble) - -# === Wrapper === -list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") - -# Wrapper sources needed for a plugin. -add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} -) -apply_standard_settings(flutter_wrapper_plugin) -set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) -set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) -target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_plugin flutter_assemble) - -# Wrapper sources needed for the runner. -add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} -) -apply_standard_settings(flutter_wrapper_app) -target_link_libraries(flutter_wrapper_app PUBLIC flutter) -target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_app flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") -set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - ${FLUTTER_TARGET_PLATFORM} $ - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} -) +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/useragent/windows/flutter/generated_plugin_registrant.cc b/useragent/windows/flutter/generated_plugin_registrant.cc index 5664626..a91c326 100644 --- a/useragent/windows/flutter/generated_plugin_registrant.cc +++ b/useragent/windows/flutter/generated_plugin_registrant.cc @@ -1,26 +1,26 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include -#include -#include -#include -#include - -void RegisterPlugins(flutter::PluginRegistry* registry) { - BiometricSignaturePluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("BiometricSignaturePlugin")); - FlutterSecureStorageWindowsPluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); - RiveNativePluginRegisterWithRegistrar( - registry->GetRegistrarForPlugin("RiveNativePlugin")); - SharePlusWindowsPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); - UrlLauncherWindowsRegisterWithRegistrar( - registry->GetRegistrarForPlugin("UrlLauncherWindows")); -} +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + BiometricSignaturePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("BiometricSignaturePlugin")); + FlutterSecureStorageWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); + RiveNativePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("RiveNativePlugin")); + SharePlusWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/useragent/windows/flutter/generated_plugin_registrant.h b/useragent/windows/flutter/generated_plugin_registrant.h index dc139d8..99f8f84 100644 --- a/useragent/windows/flutter/generated_plugin_registrant.h +++ b/useragent/windows/flutter/generated_plugin_registrant.h @@ -1,15 +1,15 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void RegisterPlugins(flutter::PluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/useragent/windows/flutter/generated_plugins.cmake b/useragent/windows/flutter/generated_plugins.cmake index 834220c..9ad5e93 100644 --- a/useragent/windows/flutter/generated_plugins.cmake +++ b/useragent/windows/flutter/generated_plugins.cmake @@ -1,29 +1,29 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - biometric_signature - flutter_secure_storage_windows - rive_native - share_plus - url_launcher_windows -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST - rust_lib_arbiter -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + biometric_signature + flutter_secure_storage_windows + rive_native + share_plus + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST + rust_lib_arbiter +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/useragent/windows/runner/CMakeLists.txt b/useragent/windows/runner/CMakeLists.txt index 394917c..2041a04 100644 --- a/useragent/windows/runner/CMakeLists.txt +++ b/useragent/windows/runner/CMakeLists.txt @@ -1,40 +1,40 @@ -cmake_minimum_required(VERSION 3.14) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the build version. -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") - -# Disable Windows macros that collide with C++ standard library functions. -target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") - -# Add dependency libraries and include directories. Add any application-specific -# dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) -target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/useragent/windows/runner/Runner.rc b/useragent/windows/runner/Runner.rc index bdaac96..597d384 100644 --- a/useragent/windows/runner/Runner.rc +++ b/useragent/windows/runner/Runner.rc @@ -1,121 +1,121 @@ -// Microsoft Visual C++ generated resource script. -// -#pragma code_page(65001) -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_APP_ICON ICON "resources\\app_icon.ico" - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) -#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD -#else -#define VERSION_AS_NUMBER 1,0,0,0 -#endif - -#if defined(FLUTTER_VERSION) -#define VERSION_AS_STRING FLUTTER_VERSION -#else -#define VERSION_AS_STRING "1.0.0" -#endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "com.example" "\0" - VALUE "FileDescription", "useragent" "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "useragent" "\0" - VALUE "LegalCopyright", "Copyright (C) 2026 com.example. All rights reserved." "\0" - VALUE "OriginalFilename", "useragent.exe" "\0" - VALUE "ProductName", "useragent" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "useragent" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "useragent" "\0" + VALUE "LegalCopyright", "Copyright (C) 2026 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "useragent.exe" "\0" + VALUE "ProductName", "useragent" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/useragent/windows/runner/flutter_window.cpp b/useragent/windows/runner/flutter_window.cpp index 955ee30..c819cb0 100644 --- a/useragent/windows/runner/flutter_window.cpp +++ b/useragent/windows/runner/flutter_window.cpp @@ -1,71 +1,71 @@ -#include "flutter_window.h" - -#include - -#include "flutter/generated_plugin_registrant.h" - -FlutterWindow::FlutterWindow(const flutter::DartProject& project) - : project_(project) {} - -FlutterWindow::~FlutterWindow() {} - -bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } - - RECT frame = GetClientArea(); - - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - - flutter_controller_->engine()->SetNextFrameCallback([&]() { - this->Show(); - }); - - // Flutter can complete the first frame before the "show window" callback is - // registered. The following call ensures a frame is pending to ensure the - // window is shown. It is a no-op if the first frame hasn't completed yet. - flutter_controller_->ForceRedraw(); - - return true; -} - -void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - flutter_controller_ = nullptr; - } - - Win32Window::OnDestroy(); -} - -LRESULT -FlutterWindow::MessageHandler(HWND hwnd, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opportunity to handle window messages. - if (flutter_controller_) { - std::optional result = - flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, - lparam); - if (result) { - return *result; - } - } - - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } - - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); -} +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/useragent/windows/runner/flutter_window.h b/useragent/windows/runner/flutter_window.h index 6da0652..28c2383 100644 --- a/useragent/windows/runner/flutter_window.h +++ b/useragent/windows/runner/flutter_window.h @@ -1,33 +1,33 @@ -#ifndef RUNNER_FLUTTER_WINDOW_H_ -#define RUNNER_FLUTTER_WINDOW_H_ - -#include -#include - -#include - -#include "win32_window.h" - -// A window that does nothing but host a Flutter view. -class FlutterWindow : public Win32Window { - public: - // Creates a new FlutterWindow hosting a Flutter view running |project|. - explicit FlutterWindow(const flutter::DartProject& project); - virtual ~FlutterWindow(); - - protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; - - private: - // The project to run. - flutter::DartProject project_; - - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; -}; - -#endif // RUNNER_FLUTTER_WINDOW_H_ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/useragent/windows/runner/main.cpp b/useragent/windows/runner/main.cpp index c33ff6c..5380bee 100644 --- a/useragent/windows/runner/main.cpp +++ b/useragent/windows/runner/main.cpp @@ -1,43 +1,43 @@ -#include -#include -#include - -#include "flutter_window.h" -#include "utils.h" - -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - flutter::DartProject project(L"data"); - - std::vector command_line_arguments = - GetCommandLineArguments(); - - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); - - FlutterWindow window(project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.Create(L"useragent", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - ::MSG msg; - while (::GetMessage(&msg, nullptr, 0, 0)) { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - } - - ::CoUninitialize(); - return EXIT_SUCCESS; -} +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"useragent", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/useragent/windows/runner/resource.h b/useragent/windows/runner/resource.h index 66a65d1..ddc7f3e 100644 --- a/useragent/windows/runner/resource.h +++ b/useragent/windows/runner/resource.h @@ -1,16 +1,16 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Runner.rc -// -#define IDI_APP_ICON 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/useragent/windows/runner/runner.exe.manifest b/useragent/windows/runner/runner.exe.manifest index 153653e..4b962bb 100644 --- a/useragent/windows/runner/runner.exe.manifest +++ b/useragent/windows/runner/runner.exe.manifest @@ -1,14 +1,14 @@ - - - - - PerMonitorV2 - - - - - - - - - + + + + + PerMonitorV2 + + + + + + + + + diff --git a/useragent/windows/runner/utils.cpp b/useragent/windows/runner/utils.cpp index 3a0b465..259d85b 100644 --- a/useragent/windows/runner/utils.cpp +++ b/useragent/windows/runner/utils.cpp @@ -1,65 +1,65 @@ -#include "utils.h" - -#include -#include -#include -#include - -#include - -void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); - } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } -} - -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } - - std::vector command_line_arguments; - - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } - - ::LocalFree(argv); - - return command_line_arguments; -} - -std::string Utf8FromUtf16(const wchar_t* utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - unsigned int target_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr) - -1; // remove the trailing null character - int input_length = (int)wcslen(utf16_string); - std::string utf8_string; - if (target_length == 0 || target_length > utf8_string.max_size()) { - return utf8_string; - } - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - input_length, utf8_string.data(), target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; -} +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + unsigned int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/useragent/windows/runner/utils.h b/useragent/windows/runner/utils.h index 3879d54..3f0e05c 100644 --- a/useragent/windows/runner/utils.h +++ b/useragent/windows/runner/utils.h @@ -1,19 +1,19 @@ -#ifndef RUNNER_UTILS_H_ -#define RUNNER_UTILS_H_ - -#include -#include - -// Creates a console for the process, and redirects stdout and stderr to -// it for both the runner and the Flutter library. -void CreateAndAttachConsole(); - -// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string -// encoded in UTF-8. Returns an empty std::string on failure. -std::string Utf8FromUtf16(const wchar_t* utf16_string); - -// Gets the command line arguments passed in as a std::vector, -// encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); - -#endif // RUNNER_UTILS_H_ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/useragent/windows/runner/win32_window.cpp b/useragent/windows/runner/win32_window.cpp index 60608d0..b5ba2a0 100644 --- a/useragent/windows/runner/win32_window.cpp +++ b/useragent/windows/runner/win32_window.cpp @@ -1,288 +1,288 @@ -#include "win32_window.h" - -#include -#include - -#include "resource.h" - -namespace { - -/// Window attribute that enables dark mode window decorations. -/// -/// Redefined in case the developer's machine has a Windows SDK older than -/// version 10.0.22000.0. -/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute -#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE -#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 -#endif - -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; - -/// Registry key for app theme preference. -/// -/// A value of 0 indicates apps should use dark mode. A non-zero or missing -/// value indicates apps should use light mode. -constexpr const wchar_t kGetPreferredBrightnessRegKey[] = - L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; -constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; - -// The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; - -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); - -// Scale helper to convert logical scaler values to physical using passed in -// scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} - -// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. -// This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { - return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - } - FreeLibrary(user32_module); -} - -} // namespace - -// Manages the Win32Window's window class registration. -class WindowClassRegistrar { - public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registrar instance. - static WindowClassRegistrar* GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); - } - return instance_; - } - - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t* GetWindowClass(); - - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); - - private: - WindowClassRegistrar() = default; - - static WindowClassRegistrar* instance_; - - bool class_registered_ = false; -}; - -WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; - -const wchar_t* WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; -} - -void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; -} - -Win32Window::Win32Window() { - ++g_active_window_count; -} - -Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); -} - -bool Win32Window::Create(const std::wstring& title, - const Point& origin, - const Size& size) { - Destroy(); - - const wchar_t* window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); - - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; - - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); - - if (!window) { - return false; - } - - UpdateTheme(window); - - return OnCreate(); -} - -bool Win32Window::Show() { - return ShowWindow(window_handle_, SW_SHOWNORMAL); -} - -// static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } - - return DefWindowProc(window, message, wparam, lparam); -} - -LRESULT -Win32Window::MessageHandler(HWND hwnd, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } - - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - - case WM_DWMCOLORIZATIONCOLORCHANGED: - UpdateTheme(hwnd); - return 0; - } - - return DefWindowProc(window_handle_, message, wparam, lparam); -} - -void Win32Window::Destroy() { - OnDestroy(); - - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } -} - -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); -} - -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); - - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); - - SetFocus(child_content_); -} - -RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; -} - -HWND Win32Window::GetHandle() { - return window_handle_; -} - -void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; -} - -bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; -} - -void Win32Window::OnDestroy() { - // No-op; provided for subclasses. -} - -void Win32Window::UpdateTheme(HWND const window) { - DWORD light_mode; - DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); - - if (result == ERROR_SUCCESS) { - BOOL enable_dark_mode = light_mode == 0; - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable_dark_mode, sizeof(enable_dark_mode)); - } -} +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/useragent/windows/runner/win32_window.h b/useragent/windows/runner/win32_window.h index e901dde..49b847f 100644 --- a/useragent/windows/runner/win32_window.h +++ b/useragent/windows/runner/win32_window.h @@ -1,102 +1,102 @@ -#ifndef RUNNER_WIN32_WINDOW_H_ -#define RUNNER_WIN32_WINDOW_H_ - -#include - -#include -#include -#include - -// A class abstraction for a high DPI-aware Win32 Window. Intended to be -// inherited from by classes that wish to specialize with custom -// rendering and input handling -class Win32Window { - public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates a win32 window with |title| that is positioned and sized using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size this function will scale the inputted width and height as - // as appropriate for the default monitor. The window is invisible until - // |Show| is called. Returns true if the window was created successfully. - bool Create(const std::wstring& title, const Point& origin, const Size& size); - - // Show the current window. Returns true if the window was successfully shown. - bool Show(); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); - - protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); - - // Called when Destroy is called. - virtual void OnDestroy(); - - private: - friend class WindowClassRegistrar; - - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; - - // Update the window frame's theme to match the system theme. - static void UpdateTheme(HWND const window); - - bool quit_on_close_ = false; - - // window handle for top level window. - HWND window_handle_ = nullptr; - - // window handle for hosted content. - HWND child_content_ = nullptr; -}; - -#endif // RUNNER_WIN32_WINDOW_H_ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_