From 8d64209507212c47cbe6c9248c20d4981f5d5998 Mon Sep 17 00:00:00 2001 From: Fedi CI Date: Sat, 12 Oct 2024 07:06:55 +0200 Subject: [PATCH] Sync with fedibtc/fedi b0c5ce39cf227d67ff856d1a590edfb1f1d03405 --- .config/flakebox/shellHook.sh | 0 .github/ISSUE_TEMPLATE/custom.md | 34 + .github/workflows/bump-version-native-ui.yml | 2 +- .../deploy-to-gp-internal-testing-nightly.yml | 18 +- .../deploy-to-gp-internal-testing.yml | 18 +- .../deploy-to-testflight-nightly.yml | 2 + .github/workflows/deploy-to-testflight.yml | 2 + .github/workflows/nix.yml | 6 + .github/workflows/upload-android-apk.yml | 8 + Cargo.lock | 2767 ++++++++--------- Cargo.toml | 66 +- SECURITY.md | 3 +- bridge/.gitignore | 2 + bridge/fedi-android/lib/build.gradle.kts | 9 +- bridge/fedi-ffi/Cargo.toml | 12 +- bridge/fedi-ffi/src/api.rs | 2 +- bridge/fedi-ffi/src/bridge.rs | 106 +- bridge/fedi-ffi/src/community/mod.rs | 2 +- bridge/fedi-ffi/src/device_registration.rs | 5 +- bridge/fedi-ffi/src/error.rs | 6 + .../src/federation_v2/backup_service.rs | 3 +- bridge/fedi-ffi/src/federation_v2/dev.rs | 3 +- bridge/fedi-ffi/src/federation_v2/meta.rs | 93 + bridge/fedi-ffi/src/federation_v2/mod.rs | 728 +++-- bridge/fedi-ffi/src/fedi_fee.rs | 36 +- bridge/fedi-ffi/src/logging.rs | 3 +- bridge/fedi-ffi/src/matrix.rs | 2 +- bridge/fedi-ffi/src/rpc.rs | 124 +- bridge/fedi-ffi/src/types.rs | 72 +- bridge/fedi-wasm/src/db.rs | 4 + devi/Cargo.toml | 3 - devi/src/main.rs | 129 +- fedi-api-types/Cargo.toml | 6 +- fedi-api-types/src/invoice_generator.rs | 10 +- fedimintd/src/main.rs | 3 +- flake.lock | 88 +- flake.nix | 17 +- justfile.fedi | 6 - misc/fedimintd-container-entrypoint.sh | 0 modules/fedi-social/client/Cargo.toml | 1 + modules/fedi-social/client/src/api.rs | 42 +- modules/fedi-social/client/src/client.rs | 28 +- modules/fedi-social/client/src/lib.rs | 9 +- modules/fedi-social/common/src/common.rs | 17 +- modules/fedi-social/server/src/lib.rs | 12 +- modules/stability-pool/client/Cargo.toml | 3 +- modules/stability-pool/client/src/lib.rs | 51 +- modules/stability-pool/server/Cargo.toml | 2 - modules/stability-pool/server/src/lib.rs | 9 +- modules/stability-pool/tests/tests/tests.rs | 22 +- nix/cargo-wrapper/cargo | 24 + nix/flakebox.nix | 17 +- scripts/bridge/build-bridge-android.sh | 5 +- scripts/ci/run-in-fs-dir-cache.sh | 2 +- scripts/ci/verify-bridge-hash.sh | 29 + scripts/common.sh | 0 scripts/test-bridge-current.sh | 2 +- scripts/ui/bump-version-native.sh | 8 +- scripts/ui/deploy-to-testflight.sh | 3 + scripts/ui/start-ios.sh | 57 +- ui/.eslintrc.js | 2 + ui/.prettierrc.js | 1 + ui/common/.prettierignore | 1 + ui/common/hooks/amount.ts | 85 +- ui/common/hooks/chat.ts | 81 +- ui/common/hooks/federation.ts | 19 +- ui/common/hooks/matrix.ts | 8 +- ui/common/hooks/pay.ts | 5 +- ui/common/hooks/recovery.ts | 14 +- ui/common/hooks/redux.ts | 2 +- ui/common/hooks/toast.ts | 2 +- ui/common/hooks/transactions.ts | 135 +- ui/common/localization/am/common.json | 2 +- ui/common/localization/ar/common.json | 2 +- ui/common/localization/ara/common.json | 2 +- ui/common/localization/en/common.json | 11 +- ui/common/localization/es/common.json | 4 +- ui/common/localization/fr/common.json | 4 +- ui/common/localization/id/common.json | 4 +- ui/common/localization/index.ts | 4 + ui/common/localization/pt/common.json | 4 +- ui/common/localization/rn/common.json | 2 +- ui/common/localization/rw/common.json | 2 +- ui/common/localization/so/common.json | 2 +- ui/common/localization/sw/common.json | 2 +- ui/common/localization/tl/common.json | 724 +++++ ui/common/redux/chat.ts | 16 +- ui/common/redux/currency.ts | 16 +- ui/common/redux/federation.ts | 112 +- ui/common/redux/index.ts | 2 +- ui/common/redux/matrix.ts | 65 +- ui/common/redux/mod.ts | 158 +- ui/common/redux/storage.ts | 2 +- ui/common/redux/transactions.ts | 8 +- ui/common/redux/wallet.ts | 73 +- ui/common/tests/utils/AmountUtils.test.ts | 84 +- ui/common/tests/utils/matrix.test.ts | 2 +- ui/common/types/bindings.ts | 26 +- ui/common/types/fedimint.ts | 20 +- ui/common/types/index.ts | 8 +- ui/common/types/storage.ts | 14 +- ui/common/utils/AmountUtils.ts | 4 +- ui/common/utils/FederationUtils.ts | 35 +- ui/common/utils/MatrixChatClient.ts | 18 +- ui/common/utils/csv.ts | 6 +- ui/common/utils/fedimint.ts | 23 +- ui/common/utils/fedimods.ts | 11 + ui/common/utils/lnurl.ts | 2 - ui/common/utils/parser.ts | 14 +- ui/common/utils/redux.ts | 40 + ui/common/utils/storage.ts | 65 +- ui/common/utils/wallet.ts | 10 +- ui/injections/src/index.ts | 4 +- ui/injections/src/injectables/fediInternal.ts | 2 +- ui/injections/src/injectables/webln.ts | 4 +- ui/native/Router.tsx | 4 +- ui/native/android/app/build.gradle | 2 +- .../android/app/src/main/AndroidManifest.xml | 5 +- ui/native/android/build.gradle | 19 +- ui/native/assets/images/svgs.ts | 42 +- ui/native/bridge.ts | 1 - .../components/FediBridgeInitializer.tsx | 7 +- .../components/feature/admin/SettingsItem.tsx | 2 +- .../feature/backup/BackupVideoRecorder.tsx | 1 - .../components/feature/backup/RecordVideo.tsx | 2 +- .../components/feature/backup/ReviewVideo.tsx | 2 +- .../feature/chat/ChatConnectionBadge.tsx | 4 +- .../feature/chat/ChatConversation.tsx | 2 +- .../feature/chat/ChatConversationHeader.tsx | 7 +- .../feature/chat/ChatPaymentEvent.tsx | 2 +- .../feature/chat/ChatPreviewConversation.tsx | 2 +- .../feature/chat/ChatRoomActions.tsx | 9 +- .../feature/chat/ChatRoomActionsOverlay.tsx | 2 +- .../feature/chat/ChatSettingsAvatar.tsx | 3 +- .../components/feature/chat/ChatTile.tsx | 2 +- .../components/feature/chat/ChatsList.tsx | 6 +- .../feature/chat/DirectChatHeader.tsx | 2 +- .../feature/chat/EmbeddedJoinGroupButton.tsx | 2 +- .../components/feature/chat/GroupHeader.tsx | 2 +- .../components/feature/chat/GroupIcon.tsx | 5 +- .../feature/chat/LegacyChatTile.tsx | 4 +- .../components/feature/chat/MessageInput.tsx | 19 +- .../components/feature/chat/MessagesList.tsx | 2 +- .../feature/federations/CommunityTile.tsx | 1 - .../federations/FederationSelector.tsx | 2 +- .../federations/PopupFederationCountdown.tsx | 6 +- .../feature/fedimods/AuthOverlay.tsx | 7 +- .../feature/fedimods/FediModBrowserHeader.tsx | 5 + .../feature/fedimods/GenerateEcashoverlay.tsx | 22 +- .../feature/fedimods/MakeInvoiceOverlay.tsx | 4 +- .../feature/fedimods/NostrSignOverlay.tsx | 7 +- .../feature/fedimods/SendPaymentOverlay.tsx | 20 +- .../feature/home/CommunityChatTile.tsx | 1 - .../components/feature/home/ShortcutTile.tsx | 2 +- .../components/feature/home/ShortcutsList.tsx | 2 +- .../feature/omni/OmniConfirmation.tsx | 5 +- .../components/feature/omni/OmniInput.tsx | 2 +- .../components/feature/omni/OmniQrScanner.tsx | 3 +- .../feature/onboarding/FederationPreview.tsx | 70 +- ui/native/components/feature/pin/PinDot.tsx | 2 +- .../feature/receive/OnchainDepositInfo.tsx | 33 + .../components/feature/receive/ReceiveQr.tsx | 30 +- .../feature/recovery/RecoveryInProgress.tsx | 2 +- .../scan/AnimatedQrCodeScannerLegacy.tsx | 4 +- .../components/feature/scan/QrCodeScanner.tsx | 2 +- .../feature/scan/QrCodeScannerLegacy.tsx | 2 +- .../feature/scan/RequestCameraAccess.tsx | 3 +- .../feature/send/FederationWalletSelector.tsx | 37 +- .../feature/stabilitypool/CurrencyAvatar.tsx | 2 +- .../StabilityTransactionsList.tsx | 1 - .../feature/stabilitypool/StabilityWallet.tsx | 3 +- .../stabilitypool/StabilityWalletTitle.tsx | 3 +- .../components/feature/wallet/FiatAmount.tsx | 1 - .../feature/wallet/NetworkBanner.tsx | 2 +- .../feature/wallet/StabilityBitcoinBanner.tsx | 2 +- .../feature/wallet/WalletButtons.tsx | 12 +- .../feature/wallet/WalletHeader.tsx | 3 +- ui/native/components/ui/AmountInput.tsx | 17 +- ui/native/components/ui/BubbleView.tsx | 3 +- ui/native/components/ui/CenterOverlay.tsx | 4 +- ui/native/components/ui/CustomOverlay.tsx | 8 +- ui/native/components/ui/Pressable.tsx | 4 +- ui/native/components/ui/ToastManager.tsx | 10 +- ui/native/constants.ts | 2 +- ui/native/index.js | 2 +- ui/native/ios/.xcode.env | 2 +- ui/native/ios/FediNightly-Info.plist | 2 +- .../xcschemes/Fedi Release Build.xcscheme | 88 + ui/native/ios/FediReactNative/Info.plist | 2 +- ui/native/ios/FediReactNativeTests/Info.plist | 2 +- ui/native/ios/Podfile.lock | 2 +- ui/native/package.json | 2 +- ui/native/screens/AddFediMod.tsx | 4 +- ui/native/screens/BitcoinRequest.tsx | 2 +- ui/native/screens/BugReport.tsx | 7 +- ui/native/screens/ChatRoomConversation.tsx | 4 - ui/native/screens/ChatRoomMembers.tsx | 2 +- ui/native/screens/ChatUserConversation.tsx | 5 - ui/native/screens/CompleteRecoveryAssist.tsx | 4 +- ui/native/screens/CompleteSocialBackup.tsx | 6 +- ui/native/screens/ConfirmJoinPublicGroup.tsx | 2 +- ui/native/screens/ConfirmReceiveOffline.tsx | 6 +- ui/native/screens/ConfirmSendChatPayment.tsx | 13 +- ui/native/screens/ConfirmSendEcash.tsx | 13 +- ui/native/screens/ConfirmSendLightning.tsx | 9 +- ui/native/screens/ConfirmSendOnChain.tsx | 25 +- ui/native/screens/CurrencySettings.tsx | 2 +- ui/native/screens/DeveloperSettings.tsx | 21 +- ui/native/screens/DirectChat.tsx | 2 +- ui/native/screens/EnterDisplayName.tsx | 2 +- ui/native/screens/ErrorScreen.tsx | 2 +- ui/native/screens/FeatureLockScreen.tsx | 4 +- ui/native/screens/FediModBrowser.tsx | 23 +- ui/native/screens/FediModSettings.tsx | 88 +- ui/native/screens/JoinFederation.tsx | 10 +- ui/native/screens/LanguageSettings.tsx | 1 + ui/native/screens/LockScreen.tsx | 4 +- ui/native/screens/MainNavigator.tsx | 8 +- ui/native/screens/Mods.tsx | 38 +- ui/native/screens/ReceiveLightning.tsx | 4 +- ui/native/screens/RoomSettings.tsx | 232 ++ ui/native/screens/ScanSocialRecoveryCode.tsx | 14 +- ui/native/screens/SendOfflineAmount.tsx | 3 +- ui/native/screens/SendOnChainAmount.tsx | 33 +- ui/native/screens/SocialBackupCloudUpload.tsx | 6 +- ui/native/screens/SocialBackupProcessing.tsx | 6 +- ui/native/screens/StabilityConfirmDeposit.tsx | 24 +- .../screens/StabilityConfirmWithdraw.tsx | 3 +- .../screens/StabilityDepositInitiated.tsx | 3 +- ui/native/screens/StabilityHome.tsx | 3 +- ui/native/screens/StabilityWithdraw.tsx | 3 +- .../screens/StabilityWithdrawInitiated.tsx | 3 +- ui/native/screens/TabsNavigator.tsx | 2 +- ui/native/screens/UploadAvatarImage.tsx | 2 +- ui/native/scripts/build-android.sh | 0 ui/native/scripts/run-detox-tests-android.sh | 0 ui/native/scripts/run-detox-tests-ios.sh | 0 ui/native/state/contexts/PinContext.tsx | 6 +- ui/native/state/hooks/index.ts | 29 +- ui/native/state/navigation.ts | 2 +- ui/native/state/store.ts | 5 + ui/native/styles/theme.ts | 3 + ui/native/types/index.ts | 10 +- ui/native/types/navigation.ts | 4 +- ui/native/utils/device-info.ts | 24 + ui/native/utils/hooks/index.ts | 10 +- ui/native/utils/hooks/notifications.ts | 2 +- ui/native/utils/linking.ts | 2 +- ui/native/utils/log.ts | 191 ++ ui/package.json | 3 +- ui/web/src/components/BugReport/index.tsx | 2 +- ui/web/src/components/ChatConversation.tsx | 2 +- ui/web/src/components/ChatListItem.tsx | 5 +- .../src/components/ChatRoomSettingsDialog.tsx | 2 +- .../src/components/FediBridgeInitializer.tsx | 10 +- .../components/HistoryList/HistoryIcon.tsx | 2 +- ui/web/src/components/InviteMemberDialog.tsx | 6 +- .../components/OmniInput/OmniConfirmation.tsx | 8 +- .../Onboarding/FederationTermsPreview.tsx | 2 +- .../components/Onboarding/JoinFederation.tsx | 2 +- .../components/Onboarding/TermsOfService.tsx | 5 +- .../components/PaperEcash/PaperEcashForm.tsx | 2 +- ui/web/src/components/QRScanner.tsx | 2 +- ui/web/src/components/SettingsMenu.tsx | 3 +- ui/web/src/components/ShadowScroller.tsx | 2 +- .../SocialBackup/SocialBackupUpload.tsx | 3 +- .../Template/PopupFederationCountdown.tsx | 2 +- ui/web/src/components/Text.tsx | 2 +- ui/web/src/hooks/store.ts | 4 +- ui/web/src/hooks/util.ts | 2 +- ui/web/src/lib/bridge/wasm.worker.ts | 2 +- ui/web/src/pages/_app.tsx | 2 +- ui/web/src/pages/_document.tsx | 3 +- .../api/bug-report/generate-upload-url.ts | 2 +- ui/web/src/pages/api/bug-report/submit.ts | 4 +- ui/web/src/pages/index.tsx | 1 - ui/web/src/pages/settings/backup/index.tsx | 1 - ui/web/src/pages/settings/backup/personal.tsx | 2 +- ui/web/src/pages/settings/backup/social.tsx | 2 - ui/web/src/pages/settings/currency.tsx | 2 +- ui/web/src/pages/settings/developer.tsx | 4 +- ui/web/src/pages/settings/edit-profile.tsx | 2 +- ui/web/src/pages/settings/index.tsx | 2 +- ui/web/src/pages/settings/language.tsx | 1 - ui/web/src/pages/settings/recover/index.tsx | 1 - .../src/pages/settings/recover/personal.tsx | 2 +- ui/web/src/styles/index.ts | 2 +- ui/web/src/utils/qrcode.ts | 22 +- ui/yarn.lock | 5 + 289 files changed, 5306 insertions(+), 3089 deletions(-) mode change 100755 => 100644 .config/flakebox/shellHook.sh create mode 100644 .github/ISSUE_TEMPLATE/custom.md create mode 100644 bridge/fedi-ffi/src/federation_v2/meta.rs mode change 100755 => 100644 misc/fedimintd-container-entrypoint.sh create mode 100644 scripts/ci/verify-bridge-hash.sh mode change 100755 => 100644 scripts/common.sh create mode 100644 ui/common/localization/tl/common.json create mode 100644 ui/native/components/feature/receive/OnchainDepositInfo.tsx create mode 100644 ui/native/ios/FediReactNative.xcodeproj/xcshareddata/xcschemes/Fedi Release Build.xcscheme create mode 100644 ui/native/screens/RoomSettings.tsx mode change 100755 => 100644 ui/native/scripts/build-android.sh mode change 100755 => 100644 ui/native/scripts/run-detox-tests-android.sh mode change 100755 => 100644 ui/native/scripts/run-detox-tests-ios.sh create mode 100644 ui/native/utils/log.ts diff --git a/.config/flakebox/shellHook.sh b/.config/flakebox/shellHook.sh old mode 100755 new mode 100644 diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md new file mode 100644 index 0000000..d4329f7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -0,0 +1,34 @@ +--- +name: Bug Report Template +about: For reporting any bugs/issues with the Fedi app +title: '' +labels: '' +assignees: '' + +--- + + +_Please fill in as many fields as you can so we can swiftly investigate_ +#### Detailed Description: + + +#### Context +_Federation_: +_Phone OS_: +_User Name_" + +#### How to reproduce: +- A +- B +- C + +#### Expected Behavior: + + +#### Actual Behavior: + + +#### Logs: + + +#### Screenshots/Videos: diff --git a/.github/workflows/bump-version-native-ui.yml b/.github/workflows/bump-version-native-ui.yml index b602e5c..719f890 100644 --- a/.github/workflows/bump-version-native-ui.yml +++ b/.github/workflows/bump-version-native-ui.yml @@ -16,7 +16,7 @@ jobs: contents: write pull-requests: write name: Update version to match release branch - runs-on: [self-hosted, linux] + runs-on: [self-hosted, macos, arm64] if: contains(github.ref, 'release/') steps: - name: Checkout repo diff --git a/.github/workflows/deploy-to-gp-internal-testing-nightly.yml b/.github/workflows/deploy-to-gp-internal-testing-nightly.yml index c932164..9f2ca2e 100644 --- a/.github/workflows/deploy-to-gp-internal-testing-nightly.yml +++ b/.github/workflows/deploy-to-gp-internal-testing-nightly.yml @@ -6,6 +6,7 @@ on: jobs: release-android: name: Build Android AAB & Upload to Google Play Dev Console + timeout-minutes: 80 runs-on: [self-hosted, linux] steps: - name: Checkout repo @@ -20,12 +21,6 @@ jobs: name: fedibtc authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - name: Build bridge - run: nix develop -c env BUILD_ALL_BRIDGE_TARGETS=1 CARGO_PROFILE=release scripts/ci/run-in-fs-dir-cache.sh build-bridge-android ./scripts/bridge/build-bridge-android.sh - - - name: Build UI dependencies - run: nix develop -c ./scripts/ui/build-deps.sh - - name: Generate release credentials env: ANDROID_KEYSTORE_FILE_ENCODED: ${{ secrets.ANDROID_KEYSTORE_FILE_ENCODED }} @@ -34,9 +29,12 @@ jobs: run: nix develop -c ./scripts/ci/make-android-release-creds.sh - name: Execute Fastlane command + timeout-minutes: 60 env: FLAVOR: 'nightly' - # Consider: should we even have separate steps above for this? - BUILD_BRIDGE: 0 - BUILD_UI_DEPS: 0 - run: nix develop -c ./scripts/ui/deploy-to-google-play.sh + BUILD_BRIDGE: 1 + BUILD_UI_DEPS: 1 + run: | + nix develop -c \ + env BUILD_ALL_BRIDGE_TARGETS=1 CARGO_PROFILE=release scripts/ci/run-in-fs-dir-cache.sh build-bridge-android \ + ./scripts/ui/deploy-to-google-play.sh diff --git a/.github/workflows/deploy-to-gp-internal-testing.yml b/.github/workflows/deploy-to-gp-internal-testing.yml index 66f900c..2b00126 100644 --- a/.github/workflows/deploy-to-gp-internal-testing.yml +++ b/.github/workflows/deploy-to-gp-internal-testing.yml @@ -6,6 +6,7 @@ on: jobs: release-android: name: Build Android AAB & Upload to Google Play Dev Console + timeout-minutes: 80 runs-on: [self-hosted, linux] steps: - name: Checkout repo @@ -20,12 +21,6 @@ jobs: name: fedibtc authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - name: Build bridge - run: nix develop -c env BUILD_ALL_BRIDGE_TARGETS=1 CARGO_PROFILE=release scripts/ci/run-in-fs-dir-cache.sh build-bridge-android ./scripts/bridge/build-bridge-android.sh - - - name: Build UI dependencies - run: nix develop -c ./scripts/ui/build-deps.sh - - name: Generate release credentials env: ANDROID_KEYSTORE_FILE_ENCODED: ${{ secrets.ANDROID_KEYSTORE_FILE_ENCODED }} @@ -34,8 +29,11 @@ jobs: run: nix develop -c ./scripts/ci/make-android-release-creds.sh - name: Execute Fastlane command + timeout-minutes: 60 env: - # Consider: should we even have separate steps above for this? - BUILD_BRIDGE: 0 - BUILD_UI_DEPS: 0 - run: nix develop -c ./scripts/ui/deploy-to-google-play.sh + BUILD_BRIDGE: 1 + BUILD_UI_DEPS: 1 + run: | + nix develop -c \ + env BUILD_ALL_BRIDGE_TARGETS=1 CARGO_PROFILE=release scripts/ci/run-in-fs-dir-cache.sh build-bridge-android \ + ./scripts/ui/deploy-to-google-play.sh diff --git a/.github/workflows/deploy-to-testflight-nightly.yml b/.github/workflows/deploy-to-testflight-nightly.yml index 07d6ed7..89f5de0 100644 --- a/.github/workflows/deploy-to-testflight-nightly.yml +++ b/.github/workflows/deploy-to-testflight-nightly.yml @@ -6,6 +6,7 @@ on: jobs: release-ios: name: Build iOS app and upload to TestFlight + timeout-minutes: 60 runs-on: [self-hosted, macos, arm64] steps: - name: Checkout repo @@ -37,6 +38,7 @@ jobs: run: nix develop -c ./scripts/ci/make-testflight-creds.sh - name: Execute fastlane beta lane for CI + timeout-minutes: 40 env: GH_PAT_FEDI_FETCH_IOS_CERTS: ${{ secrets.GH_PAT_FEDI_FETCH_IOS_CERTS }} MATCH_KEYCHAIN_NAME: ${{ secrets.APP_STORE_CONNECT_KEYCHAIN_NAME }} diff --git a/.github/workflows/deploy-to-testflight.yml b/.github/workflows/deploy-to-testflight.yml index 2683e41..8fb45dd 100644 --- a/.github/workflows/deploy-to-testflight.yml +++ b/.github/workflows/deploy-to-testflight.yml @@ -16,6 +16,7 @@ jobs: startsWith(github.head_ref, 'release/') ) name: Build iOS app and upload to TestFlight + timeout-minutes: 60 runs-on: [self-hosted, macos, arm64] steps: - name: Checkout repo @@ -47,6 +48,7 @@ jobs: run: nix develop -c ./scripts/ci/make-testflight-creds.sh - name: Execute fastlane beta lane for CI + timeout-minutes: 40 env: GH_PAT_FEDI_FETCH_IOS_CERTS: ${{ secrets.GH_PAT_FEDI_FETCH_IOS_CERTS }} MATCH_KEYCHAIN_NAME: ${{ secrets.APP_STORE_CONNECT_KEYCHAIN_NAME }} diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 40c7528..82656cb 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -162,6 +162,9 @@ jobs: name: fedibtc authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' + - name: Build fedi-api-types + run: nix build -L .#ci.fedi-api-types + - name: Build fedi-fedimint-pkgs run: nix build -L .#ci.fedi-fedimint-pkgs @@ -171,6 +174,9 @@ jobs: - name: Build fedi-fedimint-cli run: nix build -L .#ci.fedi-fedimint-cli + - name: Build fedi-api-types + run: nix build -L .#ci.fedi-api-types + - name: Build fedi-wasm run: nix build -L .#wasm32-unknown.ci.fedi-wasm diff --git a/.github/workflows/upload-android-apk.yml b/.github/workflows/upload-android-apk.yml index 26f65be..0446c39 100644 --- a/.github/workflows/upload-android-apk.yml +++ b/.github/workflows/upload-android-apk.yml @@ -57,6 +57,14 @@ jobs: BUILD_UI_DEPS: 0 run: nix develop -c ./scripts/ui/build-production-apk.sh + - name: Verify bridge hash + env: + APK_PATH: ${{ steps.prep-apk.outputs.APK_PATH }} + run: | + set -euo pipefail + + bash ./scripts/ci/verify-bridge-hash.sh "$APK_PATH" "${{ github.sha }}" + - name: Create draft GitHub release with APK uses: softprops/action-gh-release@v2 with: diff --git a/Cargo.lock b/Cargo.lock index ed0cde7..b043627 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,21 +10,21 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "accessory" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "850bb534b9dc04744fbbb71d30ad6d25a7e4cf6dc33e223c81ef3a92ebab4e0b" +checksum = "87537f9ae7cfa78d5b8ebd1a1db25959f5e737126be4d8eb44a5452fc4b63cde" dependencies = [ "macroific", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -58,15 +58,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" - -[[package]] -name = "ahash" -version = "0.8.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "once_cell", @@ -76,18 +70,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.4" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "aleph-bft-crypto" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de73b5bd99955d8728d2cce8199b02f938c2b44f2d2b738e6bea287a70500bad" +checksum = "7fdf0c124883ef234a6262e43b9ed1d214e9f9c8744a88f1f2451c2b6efe4290" dependencies = [ "async-trait", "bit-vec", @@ -98,11 +92,12 @@ dependencies = [ [[package]] name = "aleph-bft-rmc" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4470671c60202933de1945c7208125accd42f2cbd45fc8dcb5dd15d1d053ddd2" +checksum = "5e9a4418a90817c8c4929d55019eeb2bdf1d4a6030d557f17b3f580723ab40f8" dependencies = [ "aleph-bft-crypto", + "aleph-bft-types 0.12.0", "async-trait", "futures", "futures-timer", @@ -112,22 +107,33 @@ dependencies = [ [[package]] name = "aleph-bft-types" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d898329af9530cc10526b212eaa4365a4f199257e85ca712e959a24cb67fc" +checksum = "7afbf87383e06ccfe9386cda59e57ac9d899267cc765fee654d921e4ba779f92" +dependencies = [ + "aleph-bft-crypto", + "async-trait", + "futures", + "parity-scale-codec", +] + +[[package]] +name = "aleph-bft-types" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bca9d19f587215da2b6c50b5e71f9addbf2305153f850dad3f9496ed67e28bb" dependencies = [ "aleph-bft-crypto", "async-trait", "futures", - "log", "parity-scale-codec", ] [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -146,47 +152,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.12" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.2" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -194,9 +201,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" dependencies = [ "backtrace", ] @@ -218,7 +225,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -235,9 +242,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" [[package]] name = "arrayvec" @@ -256,9 +263,9 @@ checksum = "f38fa22307249f86fb7fad906fcae77f2564caeb56d7209103c551cd1cf4798f" [[package]] name = "askama" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47cbc3cf73fa8d9833727bbee4835ba5c421a0d65b72daf9a7b5d0e0f9cfb57e" +checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28" dependencies = [ "askama_derive", "askama_escape", @@ -266,18 +273,18 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.12.1" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22fbe0413545c098358e56966ff22cdd039e10215ae213cfbd65032b119fc94" +checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83" dependencies = [ + "askama_parser", "basic-toml", "mime", "mime_guess", - "nom", "proc-macro2", "quote", "serde", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -286,6 +293,15 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" +[[package]] +name = "askama_parser" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0" +dependencies = [ + "nom", +] + [[package]] name = "assert-json-diff" version = "2.0.2" @@ -296,12 +312,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "assert_matches" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" - [[package]] name = "assign" version = "1.1.1" @@ -315,16 +325,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ "concurrent-queue", - "event-listener-strategy 0.5.2", + "event-listener-strategy", "futures-core", "pin-project-lite", ] [[package]] name = "async-compression" -version = "0.4.6" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a116f46a969224200a0a97f29cfd4c50e7534e4b4826bd23ea2c3c533039c82c" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" dependencies = [ "flate2", "futures-core", @@ -335,12 +345,12 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy 0.4.0", + "event-listener", + "event-listener-strategy", "pin-project-lite", ] @@ -352,13 +362,13 @@ checksum = "9338790e78aa95a416786ec8389546c4b6a1dfc3dc36071ed9518a9413a542eb" [[package]] name = "async-recursion" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -390,18 +400,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "async-trait" -version = "0.1.78" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -410,11 +420,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "834eee9ce518130a3b4d5af09ecc43e9d6b57ee76613f227a1ddd6b77c7a62bc" +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" @@ -427,9 +443,9 @@ dependencies = [ "bitflags 1.3.2", "bytes", "futures-util", - "http 0.2.9", - "http-body 0.4.5", - "hyper 0.14.27", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.30", "itoa", "matchit", "memchr", @@ -446,18 +462,18 @@ dependencies = [ [[package]] name = "axum" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core 0.4.3", "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", - "hyper 1.2.0", + "hyper 1.4.1", "hyper-util", "itoa", "matchit", @@ -470,7 +486,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "tokio", "tower", "tower-layer", @@ -487,8 +503,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 0.2.9", - "http-body 0.4.5", + "http 0.2.12", + "http-body 0.4.6", "mime", "rustversion", "tower-layer", @@ -505,7 +521,7 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -525,7 +541,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -544,9 +560,9 @@ dependencies = [ [[package]] name = "backon" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c491fa80d69c03084223a4e73c378dd9f9a1e612eb54051213f88b2d5249b458" +checksum = "d67782c3f868daa71d3533538e98a8e13713231969def7536e8039606fc46bf0" dependencies = [ "fastrand", "futures-core", @@ -556,9 +572,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -570,16 +586,16 @@ dependencies = [ ] [[package]] -name = "base64" -version = "0.13.1" +name = "base16ct" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" -version = "0.20.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" @@ -594,12 +610,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "base64-compat" -version = "1.0.0" +name = "base64-url" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a8d4d2746f89841e49230dd26917df1876050f95abafafbe34f47cb534b88d7" +checksum = "38e2b6c78c06f7288d5e3c3d683bde35a79531127c83b087e5d0d77c974b4b28" dependencies = [ - "byteorder", + "base64 0.22.1", ] [[package]] @@ -610,9 +626,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-toml" -version = "0.1.4" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6" +checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" dependencies = [ "serde", ] @@ -624,13 +640,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" [[package]] -name = "beef" -version = "0.5.2" +name = "bech32" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" -dependencies = [ - "serde", -] +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" [[package]] name = "bincode" @@ -647,18 +660,18 @@ version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.12.1", "lazy_static", "lazycell", "proc-macro2", "quote", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -686,10 +699,8 @@ version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0694ea59225b0c5f3cb405ff3f670e4828358ed26aec49dc352f730f0cb1a8a3" dependencies = [ - "bech32", + "bech32 0.9.1", "bitcoin_hashes 0.11.0", - "core2", - "hashbrown 0.8.2", "secp256k1 0.24.3", "serde", ] @@ -700,14 +711,21 @@ version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1945a5048598e4189e239d3f809b19bdad4845c4b2ba400d304d2dcf26d2c462" dependencies = [ - "bech32", + "bech32 0.9.1", "bitcoin-private", "bitcoin_hashes 0.12.0", + "core2", "hex_lit", "secp256k1 0.27.0", "serde", ] +[[package]] +name = "bitcoin-internals" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f9997f8650dd818369931b5672a18dbef95324d0513aa99aae758de8ce86e5b" + [[package]] name = "bitcoin-private" version = "0.1.0" @@ -720,7 +738,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" dependencies = [ - "core2", "serde", ] @@ -731,15 +748,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d7066118b13d4b20b23645932dfb3a81ce7e29f95726c2036fa33cd7b092501" dependencies = [ "bitcoin-private", + "core2", "serde", ] [[package]] name = "bitcoincore-rpc" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0261b2bb7617e0c91b452a837bbd1291fd34ad6990cb8e3ffc28239cc045b5ca" +checksum = "9d6c0ee9354e3dac217db4cb1dd31941073a87fe53c86bcf3eb2b8bc97f00a08" dependencies = [ + "bitcoin-private", "bitcoincore-rpc-json", "jsonrpc", "log", @@ -749,11 +768,12 @@ dependencies = [ [[package]] name = "bitcoincore-rpc-json" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c231bea28e314879c5aef240f6052e8a72a369e3c9f9b20d9bfbb33ad18029b2" +checksum = "d30ce6f40fb0a2e8d98522796219282504b7a4b14e2b4c26139a7bea6aec6586" dependencies = [ - "bitcoin 0.29.2", + "bitcoin 0.30.2", + "bitcoin-private", "serde", "serde_json", ] @@ -766,18 +786,18 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] [[package]] name = "bitmaps" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703642b98a00b3b90513279a8ede3fcfa479c126c5fb46e78f3051522f021403" +checksum = "a1d084b0137aaa901caf9f1e8b21daa6aa24d41cd806e111335541eff9683bd6" [[package]] name = "bitvec" @@ -797,14 +817,14 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] name = "blake3" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210" dependencies = [ "arrayref", "arrayvec", @@ -813,15 +833,6 @@ dependencies = [ "constant_time_eq", ] -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.10.4" @@ -842,9 +853,9 @@ dependencies = [ [[package]] name = "bls12_381" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3c196a77437e7cc2fb515ce413a6401291578b5afc8ecb29a3c7ab957f05941" +checksum = "d7bc6d6292be3a19e6379786dac800f551e5865a5bb51ebbe3064ab80433f403" dependencies = [ "ff", "group", @@ -856,18 +867,18 @@ dependencies = [ [[package]] name = "bs58" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ "tinyvec", ] [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-slice-cast" @@ -877,15 +888,15 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "bytesize" @@ -906,18 +917,18 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -947,12 +958,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "5fb8dd288a69fc53a1996d7ecfbf4a20d59065bff137ce7e56bbd620de191189" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -972,9 +984,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" @@ -1002,9 +1014,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1012,7 +1024,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -1028,9 +1040,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -1039,9 +1051,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.4" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc" dependencies = [ "clap_builder", "clap_derive", @@ -1049,42 +1061,42 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim", ] [[package]] name = "clap_complete" -version = "4.5.1" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c" +checksum = "9c677cd0126f3026d8b093fa29eae5d812fde5c05bc66dbb29d0374eea95113a" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "cln-plugin" @@ -1104,11 +1116,29 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "cln-rpc" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "974dac6f40275b7b828087f4f9973c39658f9b4a46cc589c083a2c6c27cf67cb" +dependencies = [ + "anyhow", + "bitcoin 0.30.2", + "bytes", + "futures-util", + "hex", + "log", + "serde", + "serde_json", + "tokio", + "tokio-util", +] + [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "colored" @@ -1131,22 +1161,22 @@ dependencies = [ [[package]] name = "console-api" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd326812b3fd01da5bb1af7d340d0d555fd3d4b641e7f1dfcf5962a902952787" +checksum = "a257c22cd7e487dd4a13d413beabc512c5052f0bc048db0da6a84c3d8a6142fd" dependencies = [ "futures-core", "prost", "prost-types", - "tonic 0.10.2", + "tonic 0.11.0", "tracing-core", ] [[package]] name = "console-subscriber" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7481d4c57092cd1c19dd541b92bdce883de840df30aa5d03fd48a3935c01842e" +checksum = "31c4cc54bae66f7d9188996404abdf7fdfa23034ef8e43478c8810828abad758" dependencies = [ "console-api", "crossbeam-channel", @@ -1154,13 +1184,14 @@ dependencies = [ "futures-task", "hdrhistogram", "humantime", + "prost", "prost-types", "serde", "serde_json", "thread_local", "tokio", "tokio-stream", - "tonic 0.10.2", + "tonic 0.11.0", "tracing", "tracing-core", "tracing-subscriber", @@ -1212,9 +1243,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core2" @@ -1227,40 +1258,36 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -1290,16 +1317,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "digest 0.10.7", + "digest", "fiat-crypto", - "platforms", "rustc_version", "serde", "subtle", @@ -1314,14 +1340,14 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "darling" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -1329,27 +1355,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.71", + "strsim", + "syn 2.0.74", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -1373,9 +1399,9 @@ dependencies = [ [[package]] name = "deadpool-runtime" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63dfa964fe2a66f3fde91fc70b267fe193d822c7e603e2a675a49a7f46ad3f49" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" dependencies = [ "tokio", ] @@ -1409,14 +1435,14 @@ dependencies = [ "macroific", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "der_derive", @@ -1426,13 +1452,13 @@ dependencies = [ [[package]] name = "der_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -1458,15 +1484,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.74", ] [[package]] @@ -1476,30 +1502,32 @@ dependencies = [ "anyhow", "clap", "devimint", - "fedi-core", - "futures", "tokio", - "tracing", ] [[package]] name = "devimint" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", - "axum 0.7.4", + "axum 0.7.5", "bitcoincore-rpc", "clap", + "cln-rpc", + "esplora-client", "fedimint-aead", + "fedimint-api-client", "fedimint-bitcoind", "fedimint-build", - "fedimint-cli", "fedimint-client", - "fedimint-cln-rpc", "fedimint-core", + "fedimint-ln-client", "fedimint-ln-gateway", "fedimint-ln-server", + "fedimint-lnv2-client", + "fedimint-lnv2-common", + "fedimint-lnv2-server", "fedimint-logging", "fedimint-meta-server", "fedimint-mint-server", @@ -1514,8 +1542,8 @@ dependencies = [ "fs-lock", "futures", "hex", - "lazy_static", "nix", + "once_cell", "rand", "semver", "serde", @@ -1527,22 +1555,13 @@ dependencies = [ "url", ] -[[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", + "block-buffer", "crypto-common", "subtle", ] @@ -1596,21 +1615,22 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "electrum-client" -version = "0.12.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e1e1e452aef3ee772d19cc6272ef642f22ce0f4a9fb715ffe98010934e2ae1" +checksum = "6bc133f1c8d829d254f013f946653cbeb2b08674b960146361d1e9b67733ad19" dependencies = [ - "bitcoin 0.29.2", + "bitcoin 0.30.2", + "bitcoin-private", "byteorder", "libc", "log", - "rustls 0.20.8", + "rustls 0.21.12", "serde", "serde_json", "webpki", @@ -1620,27 +1640,27 @@ dependencies = [ [[package]] name = "email_address" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112" +checksum = "c1019fa28f600f5b581b7a603d515c3f1635da041ca211b5055804788673abfe" dependencies = [ "serde", ] [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -1657,18 +1677,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "erased-serde" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b73807008a3c7f171cc40312f37d95ef0396e048b5848d775f54b1a4dd4a0d3" +checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d" dependencies = [ "serde", + "typeid", ] [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1676,27 +1697,17 @@ dependencies = [ [[package]] name = "esplora-client" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e11244e7fd8b0beee0a3c62137c4bd9f756fe2c492ccf93171f81467b59200" +checksum = "0cb1f7f2489cce83bc3bd92784f9ba5271eeb6e729b975895fc541f78cbfcdca" dependencies = [ - "bitcoin 0.29.2", + "bitcoin 0.30.2", + "bitcoin-internals", "log", "reqwest 0.11.27", "serde", ] -[[package]] -name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - [[package]] name = "event-listener" version = "5.3.1" @@ -1708,31 +1719,21 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener 4.0.3", - "pin-project-lite", -] - [[package]] name = "event-listener-strategy" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 5.3.1", + "event-listener", "pin-project-lite", ] [[package]] name = "eyeball" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42482893d982111055ce4b24234d6250396d3785767c6b04cedd84612a0b80fb" +checksum = "d93bd0ebf93d61d6332d3c09a96e97975968a44e19a64c947bde06e6baff383f" dependencies = [ "futures-core", "readlock", @@ -1741,12 +1742,12 @@ dependencies = [ [[package]] name = "eyeball-im" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021fab29d9670be5867b16d56a95c29a12c3c1bb654e7d589010a028716d625d" +checksum = "9326c8d9f6d59d18935412608b4514cc661e4e068011bb2f523f6c8b1cfa3bd4" dependencies = [ "futures-core", - "imbl", + "imbl 2.0.3", "tokio", "tokio-util", "tracing", @@ -1761,7 +1762,7 @@ dependencies = [ "arrayvec", "eyeball-im", "futures-core", - "imbl", + "imbl 2.0.3", "pin-project-lite", "smallvec", ] @@ -1780,25 +1781,25 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fancy_constructor" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71f317e4af73b2f8f608fac190c52eac4b1879d2145df1db2fe48881ca69435" +checksum = "07b19d0e43eae2bfbafe4931b5e79c73fb1a849ca15cd41a761a7b8587f9a1a2" dependencies = [ "macroific", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fedi-api-types" -version = "0.3.0" +version = "0.4.0" dependencies = [ "anyhow", "chrono", @@ -1867,9 +1868,8 @@ dependencies = [ "anyhow", "async-recursion", "async-trait", - "base64 0.20.0", "bip39", - "bitcoin 0.29.2", + "bitcoin 0.30.2", "devimint", "eyeball", "eyeball-im", @@ -1878,6 +1878,7 @@ dependencies = [ "fedi-db-dump", "fedi-social-client", "fedimint-aead", + "fedimint-api-client", "fedimint-bip39", "fedimint-build", "fedimint-client", @@ -1892,7 +1893,7 @@ dependencies = [ "fedimint-wallet-client", "futures", "hex", - "imbl", + "imbl 2.0.3", "lazy_static", "lightning-invoice", "macro_rules_attribute 0.1.3", @@ -1901,8 +1902,8 @@ dependencies = [ "mime", "mockito", "rand", - "reqwest 0.11.27", - "ring 0.17.8", + "reqwest 0.12.5", + "ring", "rolling-file", "rusqlite", "serde", @@ -1939,22 +1940,23 @@ dependencies = [ "anyhow", "async-trait", "bincode", - "bitcoin 0.29.2", - "bitcoin_hashes 0.11.0", + "bitcoin 0.30.2", + "bitcoin_hashes 0.12.0", "erased-serde", "fedi-social-common", "fedimint-aead", + "fedimint-api-client", "fedimint-client", "fedimint-core", "fedimint-derive-secret", "fedimint-threshold-crypto", "futures", "hex", - "impl-tools 0.6.2", - "itertools 0.10.5", + "impl-tools", + "itertools 0.12.1", "rand", - "ring 0.17.8", - "secp256k1 0.24.3", + "ring", + "secp256k1 0.27.0", "secp256k1-zkp", "serde", "serde_json", @@ -1971,17 +1973,17 @@ dependencies = [ "anyhow", "async-trait", "bincode", - "bitcoin_hashes 0.11.0", + "bitcoin_hashes 0.12.0", "erased-serde", "fedimint-aead", "fedimint-core", "fedimint-threshold-crypto", "futures", "hex", - "impl-tools 0.6.2", - "itertools 0.10.5", + "impl-tools", + "itertools 0.12.1", "rand", - "secp256k1 0.24.3", + "secp256k1 0.27.0", "secp256k1-zkp", "serde", "strum 0.24.1", @@ -1998,7 +2000,7 @@ dependencies = [ "anyhow", "async-trait", "bincode", - "bitcoin_hashes 0.11.0", + "bitcoin_hashes 0.12.0", "erased-serde", "fedi-social-common", "fedimint-aead", @@ -2007,10 +2009,10 @@ dependencies = [ "fedimint-threshold-crypto", "futures", "hex", - "impl-tools 0.6.2", - "itertools 0.10.5", + "impl-tools", + "itertools 0.12.1", "rand", - "secp256k1 0.24.3", + "secp256k1 0.27.0", "secp256k1-zkp", "serde", "strum 0.24.1", @@ -2032,7 +2034,7 @@ dependencies = [ "fedimint-core", "futures", "gloo-file", - "imbl", + "imbl 2.0.3", "js-sys", "rexie", "serde", @@ -2048,30 +2050,30 @@ dependencies = [ [[package]] name = "fedimint-aead" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "argon2", "hex", "rand", - "ring 0.17.8", + "ring", ] [[package]] name = "fedimint-aleph-bft" -version = "0.30.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b6d7cad3a5af85956e9f1739fb8e27668652f523ccf3b8aeb20ed788a98c2a" +checksum = "8b21015ab681cdddedd866fe4af9169901012e9a8bd4745da8423131cccae025" dependencies = [ "aleph-bft-rmc", - "aleph-bft-types", + "aleph-bft-types 0.13.0", "anyhow", "async-trait", "derivative", "futures", "futures-timer", - "itertools 0.11.0", + "itertools 0.12.1", "log", "parity-scale-codec", "parking_lot", @@ -2080,9 +2082,41 @@ dependencies = [ ] [[package]] -name = "fedimint-bip39" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +name = "fedimint-api-client" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" +dependencies = [ + "anyhow", + "async-lock", + "async-trait", + "base64 0.22.1", + "bitcoin 0.30.2", + "fedimint-core", + "fedimint-logging", + "futures", + "getrandom", + "gloo-timers 0.3.0", + "itertools 0.12.1", + "js-sys", + "jsonrpsee-core", + "jsonrpsee-wasm-client", + "jsonrpsee-ws-client", + "lru", + "rustls-pki-types", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-rustls 0.26.0", + "tracing", + "wasm-bindgen-futures", + "webpki-roots 0.26.3", +] + +[[package]] +name = "fedimint-bip39" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "bip39", "fedimint-client", @@ -2092,19 +2126,19 @@ dependencies = [ [[package]] name = "fedimint-bitcoind" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-trait", - "bitcoin 0.29.2", - "bitcoin_hashes 0.11.0", + "bitcoin 0.30.2", "bitcoincore-rpc", "electrum-client", "esplora-client", "fedimint-core", "fedimint-logging", - "lazy_static", + "hex", + "once_cell", "rand", "serde", "serde_json", @@ -2114,32 +2148,33 @@ dependencies = [ [[package]] name = "fedimint-build" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "serde_json", ] [[package]] name = "fedimint-cli" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-trait", "base64 0.22.1", "bip39", - "bitcoin 0.29.2", - "bitcoin_hashes 0.11.0", + "bitcoin 0.30.2", "clap", "clap_complete", "fedimint-aead", + "fedimint-api-client", "fedimint-bip39", "fedimint-build", "fedimint-client", "fedimint-core", "fedimint-ln-client", "fedimint-ln-common", + "fedimint-lnv2-client", "fedimint-logging", "fedimint-meta-client", "fedimint-meta-common", @@ -2150,11 +2185,11 @@ dependencies = [ "fedimint-wallet-client", "fs-lock", "futures", + "hex", "itertools 0.12.1", "lightning-invoice", - "lnurl-rs", "rand", - "reqwest 0.11.27", + "reqwest 0.12.5", "serde", "serde_json", "thiserror", @@ -2167,16 +2202,16 @@ dependencies = [ [[package]] name = "fedimint-client" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "aquamarine", "async-stream", "async-trait", - "bitcoin 0.29.2", - "bitcoin_hashes 0.11.0", + "bitcoin 0.30.2", "fedimint-aead", + "fedimint-api-client", "fedimint-build", "fedimint-core", "fedimint-derive-secret", @@ -2185,40 +2220,22 @@ dependencies = [ "itertools 0.12.1", "rand", "reqwest 0.12.5", - "ring 0.17.8", + "ring", "secp256k1-zkp", "serde", "serde_json", - "strum 0.26.2", - "strum_macros 0.26.2", + "strum 0.26.3", + "strum_macros 0.26.4", "thiserror", "tokio", "tokio-stream", "tracing", ] -[[package]] -name = "fedimint-cln-rpc" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9681acca141623ecceaae10f8e730efdd61fdeb1542df5bdea61a42da5fb8518" -dependencies = [ - "anyhow", - "bitcoin 0.29.2", - "bytes", - "futures-util", - "hex", - "log", - "serde", - "serde_json", - "tokio", - "tokio-util", -] - [[package]] name = "fedimint-core" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-lock", @@ -2226,45 +2243,44 @@ dependencies = [ "async-trait", "backon", "backtrace", - "bech32", + "base64-url", + "bech32 0.11.0", "bincode", "bitcoin 0.29.2", "bitcoin 0.30.2", - "bitcoin_hashes 0.11.0", + "bitcoin_hashes 0.12.0", "bitvec", + "bls12_381", "erased-serde", "fedimint-derive", "fedimint-logging", - "fedimint-tbs", "fedimint-threshold-crypto", "futures", "futures-util", "getrandom", "gloo-timers 0.3.0", "hex", - "imbl", + "imbl 3.0.0", "itertools 0.12.1", "js-sys", "jsonrpsee-core", - "jsonrpsee-types", "jsonrpsee-wasm-client", - "jsonrpsee-ws-client", "lightning", "lightning-invoice", - "lru", "macro_rules_attribute 0.2.0", - "miniscript 10.0.0", + "miniscript", "parity-scale-codec", "rand", + "secp256k1 0.27.0", "secp256k1-zkp", "serde", "serde_json", - "sha3", - "strum 0.26.2", - "strum_macros 0.26.2", + "serdect", + "strum 0.26.3", + "strum_macros 0.26.4", "thiserror", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls 0.24.1", "tracing", "url", "wasm-bindgen-futures", @@ -2272,182 +2288,133 @@ dependencies = [ [[package]] name = "fedimint-derive" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "fedimint-derive-secret" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", + "bitcoin_hashes 0.11.0", + "bls12_381", "fedimint-core", "fedimint-hkdf", - "fedimint-tbs", - "ring 0.17.8", + "ring", "secp256k1-zkp", ] -[[package]] -name = "fedimint-dummy-client" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" -dependencies = [ - "anyhow", - "async-trait", - "erased-serde", - "fedimint-client", - "fedimint-core", - "fedimint-dummy-common", - "fedimint-threshold-crypto", - "futures", - "rand", - "secp256k1 0.24.3", - "serde", - "strum 0.26.2", - "strum_macros 0.26.2", - "thiserror", - "tracing", -] - -[[package]] -name = "fedimint-dummy-common" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" -dependencies = [ - "anyhow", - "async-trait", - "bitcoin_hashes 0.11.0", - "erased-serde", - "fedimint-core", - "fedimint-threshold-crypto", - "futures", - "rand", - "secp256k1 0.24.3", - "serde", - "strum 0.26.2", - "strum_macros 0.26.2", - "thiserror", - "tracing", -] - [[package]] name = "fedimint-hkdf" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ - "bitcoin_hashes 0.11.0", + "bitcoin_hashes 0.12.0", ] [[package]] name = "fedimint-ln-client" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "aquamarine", "async-stream", "async-trait", - "bincode", - "bitcoin 0.29.2", - "bitcoin_hashes 0.11.0", + "bitcoin 0.30.2", + "clap", "erased-serde", + "fedimint-api-client", "fedimint-client", "fedimint-core", "fedimint-ln-common", - "fedimint-threshold-crypto", + "fedimint-logging", "futures", "itertools 0.12.1", "lightning-invoice", + "lnurl-rs", "rand", - "reqwest 0.11.27", - "secp256k1 0.24.3", - "secp256k1-zkp", + "reqwest 0.12.5", + "secp256k1 0.27.0", "serde", "serde_json", - "strum 0.26.2", - "strum_macros 0.26.2", + "strum 0.26.3", + "strum_macros 0.26.4", "thiserror", "tokio", "tracing", - "url", ] [[package]] name = "fedimint-ln-common" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", - "aquamarine", - "async-trait", - "bitcoin 0.29.2", - "bitcoin_hashes 0.11.0", - "erased-serde", + "bitcoin 0.30.2", + "bitcoin_hashes 0.12.0", "fedimint-client", "fedimint-core", "fedimint-threshold-crypto", - "futures", - "itertools 0.12.1", "lightning", "lightning-invoice", - "rand", - "secp256k1 0.24.3", + "secp256k1 0.27.0", "serde", "serde-big-array", "serde_json", - "strum 0.26.2", - "strum_macros 0.26.2", "thiserror", "tracing", - "url", ] [[package]] name = "fedimint-ln-gateway" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "aquamarine", "async-stream", "async-trait", - "axum 0.7.4", + "axum 0.7.5", "axum-macros", - "bitcoin 0.29.2", - "bitcoin_hashes 0.11.0", + "bitcoin 0.30.2", + "bitcoin_hashes 0.12.0", "clap", "cln-plugin", + "cln-rpc", "erased-serde", + "fedimint-api-client", "fedimint-build", "fedimint-client", - "fedimint-cln-rpc", "fedimint-core", - "fedimint-dummy-client", "fedimint-ln-client", "fedimint-ln-common", + "fedimint-lnv2-client", + "fedimint-lnv2-common", "fedimint-logging", "fedimint-mint-client", "fedimint-rocksdb", "fedimint-tonic-lnd", + "fedimint-tpe", "fedimint-wallet-client", "futures", + "hex", "lightning-invoice", "prost", "rand", - "reqwest 0.11.27", - "secp256k1 0.24.3", + "reqwest 0.12.5", "secp256k1-zkp", "serde", "serde_json", - "strum 0.26.2", - "strum_macros 0.26.2", + "strum 0.26.3", + "strum_macros 0.26.4", "thiserror", "tokio", "tokio-stream", @@ -2460,13 +2427,12 @@ dependencies = [ [[package]] name = "fedimint-ln-server" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-trait", - "bincode", - "bitcoin_hashes 0.11.0", + "bitcoin_hashes 0.12.0", "erased-serde", "fedimint-bitcoind", "fedimint-core", @@ -2475,114 +2441,162 @@ dependencies = [ "fedimint-server", "fedimint-threshold-crypto", "futures", + "once_cell", + "rand", + "secp256k1 0.27.0", + "serde", + "strum 0.26.3", + "strum_macros 0.26.4", + "tokio", + "tracing", +] + +[[package]] +name = "fedimint-lnv2-client" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" +dependencies = [ + "anyhow", + "aquamarine", + "async-stream", + "async-trait", + "bitcoin 0.30.2", + "clap", + "erased-serde", + "fedimint-api-client", + "fedimint-client", + "fedimint-core", + "fedimint-lnv2-common", + "fedimint-tpe", + "futures", "itertools 0.12.1", - "lightning", "lightning-invoice", "rand", - "secp256k1 0.24.3", + "reqwest 0.12.5", + "secp256k1 0.27.0", "serde", "serde_json", - "strum 0.26.2", - "strum_macros 0.26.2", "thiserror", - "tokio", "tracing", - "url", +] + +[[package]] +name = "fedimint-lnv2-common" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" +dependencies = [ + "anyhow", + "bitcoin 0.30.2", + "bitcoin_hashes 0.12.0", + "fedimint-client", + "fedimint-core", + "fedimint-ln-common", + "fedimint-tpe", + "group", + "secp256k1 0.27.0", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "fedimint-lnv2-server" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" +dependencies = [ + "anyhow", + "async-trait", + "bls12_381", + "erased-serde", + "fedimint-bitcoind", + "fedimint-core", + "fedimint-lnv2-common", + "fedimint-server", + "fedimint-tpe", + "futures", + "group", + "rand", + "serde", + "strum 0.26.3", + "strum_macros 0.26.4", ] [[package]] name = "fedimint-logging" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "console-subscriber", + "opentelemetry 0.23.0", "opentelemetry-jaeger", - "tracing-chrome", "tracing-opentelemetry", "tracing-subscriber", ] [[package]] name = "fedimint-meta-client" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-trait", "clap", "erased-serde", + "fedimint-api-client", "fedimint-client", "fedimint-core", "fedimint-meta-common", - "fedimint-threshold-crypto", "futures", - "hex", - "rand", - "secp256k1 0.24.3", "serde", "serde_json", - "strum 0.24.1", - "strum_macros 0.24.3", + "strum 0.26.3", + "strum_macros 0.26.4", "thiserror", "tracing", ] [[package]] name = "fedimint-meta-common" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", - "async-trait", - "bitcoin_hashes 0.11.0", - "erased-serde", "fedimint-core", - "fedimint-threshold-crypto", - "futures", "hex", - "rand", - "secp256k1 0.24.3", "serde", "serde_json", - "strum 0.24.1", - "strum_macros 0.24.3", "thiserror", - "tracing", ] [[package]] name = "fedimint-meta-server" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-trait", - "bitcoin_hashes 0.11.0", "erased-serde", "fedimint-core", "fedimint-logging", "fedimint-meta-common", "futures", "rand", - "secp256k1 0.24.3", "serde", - "strum 0.24.1", - "strum_macros 0.24.3", - "thiserror", - "tokio", + "strum 0.26.3", + "strum_macros 0.26.4", "tracing", ] [[package]] name = "fedimint-metrics" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", - "axum 0.7.4", + "axum 0.7.5", "fedimint-core", - "lazy_static", + "once_cell", "prometheus", "tokio", "tracing", @@ -2590,17 +2604,21 @@ dependencies = [ [[package]] name = "fedimint-mint-client" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "aquamarine", "async-stream", "async-trait", "base64 0.22.1", + "base64-url", "bincode", - "bitcoin_hashes 0.11.0", + "bitcoin_hashes 0.12.0", + "bls12_381", + "clap", "erased-serde", + "fedimint-api-client", "fedimint-client", "fedimint-core", "fedimint-derive-secret", @@ -2609,15 +2627,15 @@ dependencies = [ "fedimint-tbs", "fedimint-threshold-crypto", "futures", + "hex", "itertools 0.12.1", - "rand", - "secp256k1 0.24.3", "secp256k1-zkp", "serde", "serde-big-array", "serde_json", - "strum 0.26.2", - "strum_macros 0.26.2", + "serdect", + "strum 0.26.3", + "strum_macros 0.26.4", "thiserror", "tokio", "tracing", @@ -2625,40 +2643,30 @@ dependencies = [ [[package]] name = "fedimint-mint-common" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", - "async-trait", "bincode", - "bitcoin_hashes 0.11.0", + "bitcoin_hashes 0.12.0", "fedimint-core", "fedimint-tbs", - "fedimint-threshold-crypto", - "futures", - "itertools 0.12.1", - "rand", - "secp256k1 0.24.3", "secp256k1-zkp", "serde", - "strum 0.26.2", - "strum_macros 0.26.2", "thiserror", "tracing", ] [[package]] name = "fedimint-mint-server" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", - "assert_matches", "async-trait", - "bincode", - "bitcoin_hashes 0.11.0", "erased-serde", "fedimint-core", + "fedimint-logging", "fedimint-metrics", "fedimint-mint-common", "fedimint-server", @@ -2666,20 +2674,19 @@ dependencies = [ "fedimint-threshold-crypto", "futures", "itertools 0.12.1", + "once_cell", "rand", - "secp256k1 0.24.3", "secp256k1-zkp", "serde", - "strum 0.26.2", - "strum_macros 0.26.2", - "thiserror", + "strum 0.26.3", + "strum_macros 0.26.4", "tracing", ] [[package]] name = "fedimint-portalloc" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "dirs", @@ -2693,8 +2700,8 @@ dependencies = [ [[package]] name = "fedimint-rocksdb" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-trait", @@ -2707,21 +2714,22 @@ dependencies = [ [[package]] name = "fedimint-server" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ - "aleph-bft-types", + "aleph-bft-types 0.13.0", "anyhow", "async-channel", "async-trait", + "base64 0.22.1", "bincode", - "bitcoin 0.29.2", "bitcoin 0.30.2", - "bitcoin_hashes 0.11.0", "bitcoin_hashes 0.12.0", + "bls12_381", "bytes", "fedimint-aead", "fedimint-aleph-bft", + "fedimint-api-client", "fedimint-build", "fedimint-core", "fedimint-logging", @@ -2730,24 +2738,25 @@ dependencies = [ "fedimint-threshold-crypto", "futures", "hex", + "hyper 1.4.1", "itertools 0.12.1", "jsonrpsee", - "lazy_static", + "once_cell", "parity-scale-codec", "pin-project", "rand", "rand_chacha", "rcgen", - "secp256k1-zkp", "serde", "serde_json", "sha3", - "strum 0.26.2", - "strum_macros 0.26.2", + "strum 0.26.3", + "strum_macros 0.26.4", + "subtle", "tar", "thiserror", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls 0.24.1", "tokio-stream", "tokio-util", "tower", @@ -2758,13 +2767,13 @@ dependencies = [ [[package]] name = "fedimint-tbs" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ - "bitcoin_hashes 0.11.0", "bls12_381", - "ff", + "fedimint-core", "group", + "hex", "rand", "rand_chacha", "serde", @@ -2773,19 +2782,20 @@ dependencies = [ [[package]] name = "fedimint-testing" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-stream", "async-trait", - "bitcoin 0.29.2", + "bitcoin 0.30.2", "bitcoincore-rpc", "clap", + "fedimint-api-client", "fedimint-bitcoind", "fedimint-client", - "fedimint-cln-rpc", "fedimint-core", + "fedimint-ln-common", "fedimint-ln-gateway", "fedimint-logging", "fedimint-portalloc", @@ -2794,15 +2804,13 @@ dependencies = [ "fedimint-tonic-lnd", "fs-lock", "futures", - "lazy_static", "lightning-invoice", "rand", - "secp256k1 0.24.3", "secp256k1-zkp", "serde", "tempfile", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls 0.24.1", "tokio-stream", "tracing", "url", @@ -2810,9 +2818,9 @@ dependencies = [ [[package]] name = "fedimint-threshold-crypto" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2930eda59c029045497a7ef03799d01eaba6091a03713bef5366bd79aab423" +checksum = "3e5f0913eb5fb65f83e6b503794f2eba124b542b9bdbb5cf941bc12bc7b0ea67" dependencies = [ "bls12_381", "byteorder", @@ -2837,12 +2845,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df03ca33b5116de3051c1e233fe341e23b04c4913c7b16042497924559bc2a2e" dependencies = [ "hex", - "http-body 0.4.5", - "hyper 0.14.27", - "hyper-rustls 0.24.1", + "http-body 0.4.6", + "hyper 0.14.30", + "hyper-rustls 0.24.2", "prost", - "rustls 0.21.8", - "rustls-pemfile 1.0.3", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", "tokio", "tokio-stream", "tonic 0.10.2", @@ -2850,138 +2858,130 @@ dependencies = [ "tower", ] +[[package]] +name = "fedimint-tpe" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" +dependencies = [ + "bitcoin_hashes 0.12.0", + "bls12_381", + "fedimint-core", + "group", + "rand", + "rand_chacha", + "serde", + "serde-big-array", +] + [[package]] name = "fedimint-unknown-common" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", - "async-trait", - "bitcoin_hashes 0.11.0", - "erased-serde", "fedimint-core", - "futures", - "rand", "serde", "thiserror", - "tracing", ] [[package]] name = "fedimint-unknown-server" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-trait", "erased-serde", "fedimint-core", "fedimint-unknown-common", - "futures", - "rand", - "serde", - "strum 0.26.2", - "strum_macros 0.26.2", - "thiserror", - "tokio", - "tracing", + "strum 0.26.3", + "strum_macros 0.26.4", ] [[package]] name = "fedimint-wallet-client" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "aquamarine", "async-stream", "async-trait", - "bitcoin 0.29.2", + "bitcoin 0.30.2", + "clap", "erased-serde", + "fedimint-api-client", "fedimint-bitcoind", "fedimint-client", "fedimint-core", + "fedimint-logging", "fedimint-wallet-common", "futures", - "impl-tools 0.10.0", - "miniscript 10.0.0", "rand", - "secp256k1 0.24.3", + "secp256k1 0.27.0", "serde", "serde_json", - "strum 0.26.2", - "strum_macros 0.26.2", - "thiserror", + "strum 0.26.3", + "strum_macros 0.26.4", "tokio", "tracing", - "url", - "validator", ] [[package]] name = "fedimint-wallet-common" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", - "async-trait", - "bitcoin 0.29.2", - "erased-serde", + "bitcoin 0.30.2", "fedimint-core", - "futures", - "impl-tools 0.10.0", - "miniscript 10.0.0", - "miniscript 9.0.2", - "rand", - "secp256k1 0.24.3", + "hex", + "impl-tools", + "miniscript", + "secp256k1 0.27.0", "serde", - "strum 0.26.2", - "strum_macros 0.26.2", "thiserror", "tracing", - "url", - "validator", ] [[package]] name = "fedimint-wallet-server" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-trait", - "bitcoin 0.29.2", + "bitcoin 0.30.2", "erased-serde", "fedimint-bitcoind", "fedimint-core", + "fedimint-logging", "fedimint-metrics", "fedimint-server", "fedimint-wallet-common", "futures", - "impl-tools 0.10.0", - "miniscript 10.0.0", - "miniscript 9.0.2", + "hex", + "miniscript", + "once_cell", "rand", - "secp256k1 0.24.3", + "secp256k1 0.27.0", "serde", - "strum 0.26.2", - "strum_macros 0.26.2", - "thiserror", + "strum 0.26.3", + "strum_macros 0.26.4", + "tokio", "tracing", - "url", - "validator", ] [[package]] name = "fedimintd" -version = "0.3.2-rc.0" -source = "git+https://github.com/fedibtc/fedimint?tag=v0.3.2-rc.0-fed1#2ea651c2da20a0380062109428b43d4702a47bae" +version = "0.4.2-rc.1" +source = "git+https://github.com/fedibtc/fedimint?tag=v0.4.2-rc.1-fed-3#bc288b405705b3477f840cd2e5e03ff35174d084" dependencies = [ "anyhow", "async-trait", - "axum 0.7.4", + "axum 0.7.5", "bincode", - "bitcoin 0.29.2", + "bitcoin 0.30.2", "bytes", "clap", "console-subscriber", @@ -2991,6 +2991,8 @@ dependencies = [ "fedimint-core", "fedimint-ln-common", "fedimint-ln-server", + "fedimint-lnv2-common", + "fedimint-lnv2-server", "fedimint-logging", "fedimint-meta-server", "fedimint-metrics", @@ -3004,20 +3006,20 @@ dependencies = [ "fedimint-wallet-server", "futures", "http 1.1.0", - "http-body 1.0.0", - "hyper 1.2.0", + "http-body 1.0.1", + "hyper 1.4.1", "itertools 0.12.1", "jsonrpsee", + "once_cell", "rand", "rcgen", - "ring 0.17.8", - "secp256k1-zkp", + "ring", "serde", "serde_json", "sha3", "thiserror", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls 0.24.1", "tokio-util", "tower", "tracing", @@ -3026,9 +3028,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "bitvec", "rand_core", @@ -3044,20 +3046,20 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] @@ -3068,15 +3070,15 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flagset" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdeb3aa5e95cf9aabc17f060cfa0ced7b83f042390760ca53bf09df9968acaa1" +checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec" [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", "miniz_oxide", @@ -3099,15 +3101,18 @@ dependencies = [ [[package]] name = "fs-err" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] [[package]] name = "fs-lock" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4f2e18078ea3b2c89f718dd7dad6850e29d74330b37665bea259e5987be9301" +checksum = "1ef0f3b20f39ca3e3d4e6ce75b576ac7658272d2af8646509c4ee84f494f69ab" dependencies = [ "fs4", ] @@ -3124,9 +3129,9 @@ dependencies = [ [[package]] name = "fs4" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b1e34e369d7f0151309821497440bd0266b86c77ccd69717c3b67e5eaeffe4" +checksum = "e8c6b3bd49c37d2aa3f3f2220233b29a7cd23f79d1fe70e5337d25fb390793de" dependencies = [ "rustix", "windows-sys 0.52.0", @@ -3204,7 +3209,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -3221,9 +3226,9 @@ checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" dependencies = [ "gloo-timers 0.2.6", "send_wrapper", @@ -3281,9 +3286,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "glob" @@ -3315,15 +3320,15 @@ dependencies = [ [[package]] name = "gloo-net" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43aaa242d1239a8822c15c645f02166398da4f8b5c4bae795c1f5b44e9eee173" +checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" dependencies = [ "futures-channel", "futures-core", "futures-sink", "gloo-utils", - "http 0.2.9", + "http 1.1.0", "js-sys", "pin-project", "serde", @@ -3384,9 +3389,9 @@ dependencies = [ [[package]] name = "group" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", "rand_core", @@ -3407,17 +3412,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http 0.2.9", - "indexmap 2.2.5", + "http 0.2.12", + "indexmap 2.4.0", "slab", "tokio", "tokio-util", @@ -3426,17 +3431,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http 1.1.0", - "indexmap 2.2.5", + "indexmap 2.4.0", "slab", "tokio", "tokio-util", @@ -3445,27 +3450,23 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.8.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25" -dependencies = [ - "ahash 0.3.8", - "autocfg", -] +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.7", + "ahash", "allocator-api2", ] @@ -3475,16 +3476,16 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] name = "hdrhistogram" -version = "7.5.2" +version = "7.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" dependencies = [ - "base64 0.13.1", + "base64 0.21.7", "byteorder", "flate2", "nom", @@ -3505,9 +3506,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -3518,6 +3519,12 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + [[package]] name = "hex_fmt" version = "0.3.0" @@ -3545,7 +3552,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.7", + "digest", ] [[package]] @@ -3559,14 +3566,14 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -3586,20 +3593,20 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http 0.2.9", + "http 0.2.12", "pin-project-lite", ] [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http 1.1.0", @@ -3607,22 +3614,22 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -3638,22 +3645,22 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", - "h2 0.3.24", - "http 0.2.9", - "http-body 0.4.5", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2", "tokio", "tower-service", "tracing", @@ -3662,16 +3669,16 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.3", + "h2 0.4.5", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -3683,14 +3690,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http 0.2.9", - "hyper 0.14.27", - "rustls 0.21.8", + "http 0.2.12", + "hyper 0.14.30", + "rustls 0.21.12", "tokio", "tokio-rustls 0.24.1", ] @@ -3703,14 +3710,14 @@ checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.2.0", + "hyper 1.4.1", "hyper-util", - "rustls 0.23.7", + "rustls 0.23.12", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", "tower-service", - "webpki-roots 0.26.1", + "webpki-roots 0.26.3", ] [[package]] @@ -3719,7 +3726,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.27", + "hyper 0.14.30", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -3727,18 +3734,18 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.0", - "hyper 1.2.0", + "http-body 1.0.1", + "hyper 1.4.1", "pin-project-lite", - "socket2 0.5.6", + "socket2", "tokio", "tower", "tower-service", @@ -3747,16 +3754,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -3799,24 +3806,25 @@ dependencies = [ ] [[package]] -name = "imbl-sized-chunks" -version = "0.1.1" +name = "imbl" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6957ea0b2541c5ca561d3ef4538044af79f8a05a1eb3a3b148936aaceaa1076" +checksum = "bc3be8d8cd36f33a46b1849f31f837c44d9fa87223baee3b4bd96b8f11df81eb" dependencies = [ "bitmaps", + "imbl-sized-chunks", + "rand_core", + "rand_xoshiro", + "version_check", ] [[package]] -name = "impl-tools" -version = "0.6.2" +name = "imbl-sized-chunks" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b38b9422e043c070fb8f1de132599768b8057328fc6d7587d770ec27181f504a" +checksum = "144006fb58ed787dcae3f54575ff4349755b00ccc99f4b4873860b654be1ed63" dependencies = [ - "autocfg", - "impl-tools-lib 0.7.1", - "proc-macro-error", - "syn 1.0.109", + "bitmaps", ] [[package]] @@ -3826,21 +3834,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d82c305b1081f1a99fda262883c788e50ab57d36c00830bdd7e0a82894ad965c" dependencies = [ "autocfg", - "impl-tools-lib 0.10.0", + "impl-tools-lib", "proc-macro-error", - "syn 2.0.71", -] - -[[package]] -name = "impl-tools-lib" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d872c7f79f16a8acfe1e99d16ed1a126dea85d9d9eb895fd4922f88a4a75a0c0" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", + "syn 2.0.74", ] [[package]] @@ -3852,7 +3848,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -3868,18 +3864,18 @@ dependencies = [ [[package]] name = "include_dir" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" dependencies = [ "include_dir_macros", ] [[package]] name = "include_dir_macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" dependencies = [ "proc-macro2", "quote", @@ -3887,9 +3883,9 @@ dependencies = [ [[package]] name = "indexed_db_futures" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cc2083760572ee02385ab8b7c02c20925d2dd1f97a1a25a8737a238608f1152" +checksum = "0704b71f13f81b5933d791abf2de26b33c40935143985220299a357721166706" dependencies = [ "accessory", "cfg-if", @@ -3915,12 +3911,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "serde", ] @@ -3936,9 +3932,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", "js-sys", @@ -3954,35 +3950,32 @@ checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ "hermit-abi", - "rustix", - "windows-sys 0.48.0", + "libc", + "windows-sys 0.52.0", ] [[package]] -name = "itertools" -version = "0.10.5" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" -version = "0.11.0" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] @@ -3998,15 +3991,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.26" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] @@ -4040,21 +4033,20 @@ dependencies = [ [[package]] name = "jsonrpc" -version = "0.12.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f8423b78fc94d12ef1a4a9d13c348c9a78766dda0cc18817adf0faf77e670c8" +checksum = "8128f36b47411cd3f044be8c1f5cc0c9e24d1d1bfdc45f0a57897b32513053f2" dependencies = [ - "base64-compat", + "base64 0.13.1", "serde", - "serde_derive", "serde_json", ] [[package]] name = "jsonrpsee" -version = "0.22.3" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cdbb7cb6f3ba28f5b212dd250ab4483105efc3e381f5c8bb90340f14f0a2cc3" +checksum = "5ec465b607a36dc5dd45d48b7689bc83f679f66a3ac6b6b21cc787a11e0f8685" dependencies = [ "jsonrpsee-core", "jsonrpsee-server", @@ -4064,44 +4056,46 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.22.3" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab2e14e727d2faf388c99d9ca5210566ed3b044f07d92c29c3611718d178380" +checksum = "90f0977f9c15694371b8024c35ab58ca043dbbf4b51ccb03db8858a021241df1" dependencies = [ + "base64 0.22.1", "futures-channel", "futures-util", "gloo-net", - "http 0.2.9", + "http 1.1.0", "jsonrpsee-core", "pin-project", + "rustls 0.23.12", "rustls-pki-types", "soketto", "thiserror", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tokio-util", "tracing", "url", - "webpki-roots 0.26.1", ] [[package]] name = "jsonrpsee-core" -version = "0.22.4" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "274d68152c24aa78977243bb56f28d7946e6aa309945b37d33174a3f92d89a3a" +checksum = "e942c55635fbf5dc421938b8558a8141c7e773720640f4f1dbe1f4164ca4e221" dependencies = [ - "anyhow", "async-trait", - "beef", + "bytes", "futures-timer", "futures-util", - "hyper 0.14.27", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", "jsonrpsee-types", "parking_lot", "pin-project", "rand", - "rustc-hash", + "rustc-hash 2.0.0", "serde", "serde_json", "thiserror", @@ -4113,13 +4107,16 @@ dependencies = [ [[package]] name = "jsonrpsee-server" -version = "0.22.3" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4882e640e70c2553e3d9487e6f4dddd5fd11918f25e40fa45218f9fe29ed2152" +checksum = "038fb697a709bec7134e9ccbdbecfea0e2d15183f7140254afef7c5610a3f488" dependencies = [ "futures-util", - "http 0.2.9", - "hyper 0.14.27", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-util", "jsonrpsee-core", "jsonrpsee-types", "pin-project", @@ -4137,12 +4134,11 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.22.4" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dc828e537868d6b12bbb07ec20324909a22ced6efca0057c825c3e1126b2c6d" +checksum = "23b67d6e008164f027afbc2e7bb79662650158d26df200040282d2aa1cbb093b" dependencies = [ - "anyhow", - "beef", + "http 1.1.0", "serde", "serde_json", "thiserror", @@ -4150,9 +4146,9 @@ dependencies = [ [[package]] name = "jsonrpsee-wasm-client" -version = "0.22.3" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae2c3f2411052b4a831cb7a34cd1498e0d8b9309bd49fca67567634ff64023d" +checksum = "0470d0ae043ffcb0cd323797a631e637fb4b55fe3eaa6002934819458bba62a7" dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", @@ -4161,11 +4157,11 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.22.3" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8a07ab8da9a283b906f6735ddd17d3680158bb72259e853441d1dd0167079ec" +checksum = "992bf67d1132f88edf4a4f8cff474cf01abb2be203004a2b8e11c2b20795b99e" dependencies = [ - "http 0.2.9", + "http 1.1.0", "jsonrpsee-client-transport", "jsonrpsee-core", "jsonrpsee-types", @@ -4174,18 +4170,18 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] [[package]] name = "konst" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d712a8c49d4274f8d8a5cf61368cb5f3c143d149882b1a2918129e53395fdb0" +checksum = "50a0ba6de5f7af397afff922f22c149ff605c766cd3269cf6c1cd5e466dbe3b9" dependencies = [ "const_panic", "konst_kernel", @@ -4194,18 +4190,18 @@ dependencies = [ [[package]] name = "konst_kernel" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac6ea8c376b6e208a81cf39b8e82bebf49652454d98a4829e907dac16ef1790" +checksum = "be0a455a1719220fd6adf756088e1c69a85bf14b6a9e24537a5cc04f503edb2b" dependencies = [ "typewit", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -4221,12 +4217,29 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "winapi", + "windows-targets 0.52.6", +] + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall", ] [[package]] @@ -4258,9 +4271,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.12" +version = "1.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" +checksum = "fdc53a7799a7496ebc9fd29f31f7df80e83c9bda5299768af5f9e59eeea74647" dependencies = [ "cc", "pkg-config", @@ -4269,50 +4282,51 @@ dependencies = [ [[package]] name = "lightning" -version = "0.0.118" +version = "0.0.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cec5fa9382154fe9671e8df93095b800c7d77abc66e2a5ef839d672521c5e" +checksum = "5fd92d4aa159374be430c7590e169b4a6c0fb79018f5bc4ea1bffde536384db3" dependencies = [ - "bitcoin 0.29.2", + "bitcoin 0.30.2", "core2", - "hashbrown 0.8.2", + "hashbrown 0.13.2", + "hex-conservative", + "libm", + "possiblyrandom", ] [[package]] name = "lightning-invoice" -version = "0.26.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb24878b0f4ef75f020976c886d9ad1503867802329cc963e0ab4623ea3b25c" +checksum = "26d07d01cf197bf2184b929b7dc94aa70d935aac6df896c256a3a9475b7e9d40" dependencies = [ - "bech32", - "bitcoin 0.29.2", - "bitcoin_hashes 0.11.0", + "bech32 0.9.1", + "bitcoin 0.30.2", "lightning", - "num-traits", - "secp256k1 0.24.3", + "secp256k1 0.27.0", "serde", ] [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lnurl-rs" -version = "0.4.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29742339d2d88bd3ea1f4305e11b22d3efada9f86010ccbd7b6646837cc57e85" +checksum = "86f2347f6764fedbb74482d88f472dc3e2c7613304bfea31ce1b7ee8e1ebbf8c" dependencies = [ "aes", "anyhow", - "base64 0.13.1", - "bech32", + "base64 0.22.1", + "bech32 0.11.0", "bitcoin 0.30.2", "cbc", "email_address", - "reqwest 0.11.27", + "reqwest 0.12.5", "serde", "serde_json", "url", @@ -4320,9 +4334,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -4330,24 +4344,24 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] name = "lz4-sys" -version = "1.9.4" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +checksum = "109de74d5d2353660401699a4174a4ff23fcc649caf553df71933c7fb45ad868" dependencies = [ "cc", "libc", @@ -4411,7 +4425,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -4422,7 +4436,7 @@ checksum = "13198c120864097a565ccb3ff947672d969932b7975ebd4085732c9f09435e55" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -4435,7 +4449,7 @@ dependencies = [ "macroific_core", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -4469,9 +4483,9 @@ dependencies = [ [[package]] name = "matchit" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "matrix-pickle" @@ -4493,7 +4507,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -4510,15 +4524,15 @@ dependencies = [ "backoff", "bytes", "bytesize", - "event-listener 5.3.1", + "event-listener", "eyeball", "eyeball-im", "futures-core", "futures-util", "gloo-timers 0.3.0", "http 1.1.0", - "imbl", - "indexmap 2.2.5", + "imbl 2.0.3", + "indexmap 2.4.0", "js_int", "matrix-sdk-base", "matrix-sdk-common", @@ -4550,7 +4564,7 @@ source = "git+https://github.com/fedibtc/matrix-rust-sdk?tag=fedi-0.1#0caa17f8e6 dependencies = [ "as_variant", "async-trait", - "bitflags 2.4.0", + "bitflags 2.6.0", "eyeball", "eyeball-im", "futures-util", @@ -4721,8 +4735,8 @@ dependencies = [ "fuzzy-matcher", "gloo-timers 0.3.0", "growable-bloom-filter", - "imbl", - "indexmap 2.2.5", + "imbl 2.0.3", + "indexmap 2.4.0", "itertools 0.12.1", "matrix-sdk", "matrix-sdk-base", @@ -4740,9 +4754,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -4758,9 +4772,9 @@ checksum = "a1a85a5069ebd40e64b1985773cc81addbe9d90d7ecf60e7b5475a57ad584c70" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -4774,18 +4788,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniscript" -version = "9.0.2" +version = "10.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5b106477a0709e2da253e5559ba4ab20a272f8577f1eefff72f3a905b5d35f5" -dependencies = [ - "bitcoin 0.29.2", -] - -[[package]] -name = "miniscript" -version = "10.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eb102b66b2127a872dbcc73095b7b47aeb9d92f7b03c2b2298253ffc82c7594" +checksum = "d371924f9eb7aa860ab395baaaa0bcdfa81a32f330b538c4e2c04617b2722fe3" dependencies = [ "bitcoin 0.30.2", "bitcoin-private", @@ -4794,34 +4799,40 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.10" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "mockito" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f6e023aa5bdf392aa06c78e4a4e6d498baab5138d0c993503350ebbc37bf1e" +checksum = "09b34bd91b9e5c5b06338d392463e1318d683cf82ec3d3af4014609be6e2108d" dependencies = [ "assert-json-diff", + "bytes", "colored", - "futures-core", - "hyper 0.14.27", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-util", "log", "rand", "regex", @@ -4833,23 +4844,23 @@ dependencies = [ [[package]] name = "multimap" -version = "0.8.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "new_debug_unreachable" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.6.0", "cfg-if", "cfg_aliases", "libc", @@ -4883,9 +4894,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -4902,9 +4913,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.0" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -4923,9 +4934,9 @@ checksum = "6c548d5c78976f6955d72d0ced18c48ca07030f7a1d4024529fedd7c1c01b29c" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "opentelemetry" @@ -4942,6 +4953,20 @@ dependencies = [ "urlencoding", ] +[[package]] +name = "opentelemetry" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b69a91d4893e713e06f724597ad630f1fa76057a5e1026c0ca67054a9032a76" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", +] + [[package]] name = "opentelemetry-jaeger" version = "0.21.0" @@ -4951,7 +4976,7 @@ dependencies = [ "async-trait", "futures-core", "futures-util", - "opentelemetry", + "opentelemetry 0.22.0", "opentelemetry-semantic-conventions", "opentelemetry_sdk", "thrift", @@ -4976,8 +5001,8 @@ dependencies = [ "futures-util", "glob", "once_cell", - "opentelemetry", - "ordered-float 4.2.0", + "opentelemetry 0.22.0", + "ordered-float 4.2.2", "percent-encoding", "rand", "thiserror", @@ -5000,9 +5025,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "4.2.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +checksum = "4a91171844676f8c7990ce64959210cd2eaef32c2612c50f9fae9f8aaa6065a6" dependencies = [ "num-traits", ] @@ -5015,9 +5040,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "pairing" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135590d8bdba2b31346f9cd1fb2a912329f5135e832a4f422942eb6ead8b6b3b" +checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" dependencies = [ "group", ] @@ -5056,9 +5081,9 @@ checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -5066,15 +5091,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -5090,9 +5115,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbkdf2" @@ -5100,17 +5125,17 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" dependencies = [ - "digest 0.10.7", + "digest", "hmac", ] [[package]] name = "pem" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "serde", ] @@ -5122,12 +5147,12 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.2.5", + "indexmap 2.4.0", ] [[package]] @@ -5180,7 +5205,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -5218,14 +5243,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -5256,9 +5281,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plain" @@ -5266,12 +5291,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" -[[package]] -name = "platforms" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" - [[package]] name = "poly1305" version = "0.8.0" @@ -5283,6 +5302,15 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "possiblyrandom" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b122a615d72104fb3d8b26523fdf9232cd8ee06949fb37e4ce3ff964d15dffd" +dependencies = [ + "getrandom", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -5291,9 +5319,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "precomputed-hash" @@ -5303,12 +5334,12 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "prettyplease" -version = "0.2.12" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -5355,9 +5386,9 @@ dependencies = [ [[package]] name = "prometheus" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ "cfg-if", "fnv", @@ -5380,13 +5411,13 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.12.1" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bdf592881d821b83d471f8af290226c8d51402259e9bb5be7f9f8bdebbb11ac" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.4.1", - "itertools 0.10.5", + "heck 0.5.0", + "itertools 0.12.1", "log", "multimap", "once_cell", @@ -5395,9 +5426,8 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.71", + "syn 2.0.74", "tempfile", - "which", ] [[package]] @@ -5407,17 +5437,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "prost-types" -version = "0.12.1" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e081b29f63d83a4bc75cfc9f3fe424f9156cf92d8a4f0c9407cce9a1b67327cf" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ "prost", ] @@ -5430,16 +5460,17 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "quinn" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +checksum = "b22d8e7369034b9a7132bc2008cac12f2013c8132b45e0554e6e20e2617f2156" dependencies = [ "bytes", "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", - "rustls 0.23.7", + "rustc-hash 2.0.0", + "rustls 0.23.12", + "socket2", "thiserror", "tokio", "tracing", @@ -5447,15 +5478,15 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +checksum = "ba92fb39ec7ad06ca2582c0ca834dfeadcaf06ddfc8e635c80aa7e1c05315fdd" dependencies = [ "bytes", "rand", - "ring 0.17.8", - "rustc-hash", - "rustls 0.23.7", + "ring", + "rustc-hash 2.0.0", + "rustls 0.23.12", "slab", "thiserror", "tinyvec", @@ -5464,22 +5495,22 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" dependencies = [ "libc", "once_cell", - "socket2 0.5.6", + "socket2", "tracing", "windows-sys 0.52.0", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -5531,70 +5562,53 @@ dependencies = [ [[package]] name = "rcgen" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48406db8ac1f3cbc7dcdb56ec355343817958a356ff430259bb07baf7607e1e1" +checksum = "54077e1872c46788540de1ea3d7f4ccb1983d12f9aa909b234468676c1a36779" dependencies = [ "pem", - "ring 0.17.8", + "ring", + "rustls-pki-types", "time", "yasna", ] [[package]] -name = "readlock" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7b323e7196daa571c8584de958be19e92941c41f845776fe06babfe8fa280a2" - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] +name = "readlock" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "072cfe5b1d2dcd38d20e18f85e9c9978b6cc08f0b373e9f1fff1541335622974" + +[[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.3" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.6", - "regex-syntax 0.7.4", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -5608,13 +5622,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.4", + "regex-syntax 0.8.4", ] [[package]] @@ -5625,9 +5639,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" @@ -5640,11 +5654,11 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.3.24", - "http 0.2.9", - "http-body 0.4.5", - "hyper 0.14.27", - "hyper-rustls 0.24.1", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.30", + "hyper-rustls 0.24.2", "ipnet", "js-sys", "log", @@ -5652,8 +5666,8 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.8", - "rustls-pemfile 1.0.3", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", @@ -5667,7 +5681,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.25.2", + "webpki-roots 0.25.4", "winreg 0.50.0", ] @@ -5683,9 +5697,9 @@ dependencies = [ "futures-core", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", - "hyper 1.2.0", + "hyper 1.4.1", "hyper-rustls 0.27.2", "hyper-util", "ipnet", @@ -5696,8 +5710,8 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.7", - "rustls-pemfile 2.1.1", + "rustls 0.23.12", + "rustls-pemfile 2.1.3", "rustls-pki-types", "serde", "serde_json", @@ -5705,6 +5719,7 @@ dependencies = [ "sync_wrapper 1.0.1", "tokio", "tokio-rustls 0.26.0", + "tokio-socks", "tokio-util", "tower-service", "url", @@ -5712,7 +5727,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.26.1", + "webpki-roots 0.26.3", "winreg 0.52.0", ] @@ -5737,19 +5752,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "git+https://github.com/fedibtc/ring?tag=fedi-0.1#5493e7e76d0d8fb1d3cbb0be9c4944700741b802" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "winapi", -] - [[package]] name = "ring" version = "0.17.8" @@ -5760,16 +5762,16 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin 0.9.8", - "untrusted 0.9.0", + "spin", + "untrusted", "windows-sys 0.52.0", ] [[package]] name = "rmp" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" dependencies = [ "byteorder", "num-traits", @@ -5778,9 +5780,9 @@ dependencies = [ [[package]] name = "rmp-serde" -version = "1.1.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" dependencies = [ "byteorder", "rmp", @@ -5862,7 +5864,7 @@ dependencies = [ "form_urlencoded", "getrandom", "http 1.1.0", - "indexmap 2.2.5", + "indexmap 2.4.0", "js-sys", "js_int", "konst", @@ -5889,7 +5891,7 @@ version = "0.28.1" source = "git+https://github.com/fedibtc/ruma?tag=ruma-fedi-0.1#4c3b29be87d412ef25dd1148dac014d09fa3b1e0" dependencies = [ "as_variant", - "indexmap 2.2.5", + "indexmap 2.4.0", "js_int", "js_option", "percent-encoding", @@ -5950,8 +5952,8 @@ dependencies = [ "quote", "ruma-identifiers-validation", "serde", - "syn 2.0.71", - "toml 0.8.2", + "syn 2.0.74", + "toml 0.8.19", ] [[package]] @@ -5970,9 +5972,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -5980,6 +5982,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "rustc_version" version = "0.4.0" @@ -5991,11 +5999,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -6004,80 +6012,69 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" -dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", -] - -[[package]] -name = "rustls" -version = "0.21.8" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-webpki 0.101.7", "sct", ] [[package]] name = "rustls" -version = "0.22.2" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", - "ring 0.17.8", + "ring", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki 0.102.6", "subtle", "zeroize", ] [[package]] name = "rustls" -version = "0.23.7" +version = "0.23.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ + "log", "once_cell", - "ring 0.17.8", + "ring", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki 0.102.6", "subtle", "zeroize", ] [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ "base64 0.21.7", ] [[package]] name = "rustls-pemfile" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.3.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" @@ -6085,32 +6082,32 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.102.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" dependencies = [ - "ring 0.17.8", + "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scoped-tls" @@ -6141,17 +6138,17 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "ring", + "untrusted", ] [[package]] @@ -6198,29 +6195,32 @@ dependencies = [ [[package]] name = "secp256k1-zkp" -version = "0.7.0" -source = "git+https://github.com/fedibtc/rust-secp256k1-zkp/?tag=fedi-0.1#f29b1b8c442d4b8a42547ce36d3987aaedf94224" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "026efcdacb95ee6aae5cc19144dc1549973eac36a4972700c28493de1ee5d69f" dependencies = [ + "bitcoin-private", "rand", - "secp256k1 0.24.3", + "secp256k1 0.27.0", "secp256k1-zkp-sys", "serde", ] [[package]] name = "secp256k1-zkp-sys" -version = "0.7.0" -source = "git+https://github.com/fedibtc/rust-secp256k1-zkp/?tag=fedi-0.1#f29b1b8c442d4b8a42547ce36d3987aaedf94224" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d03ab1ca75a18e1899e8d9b8d28b5998ae1ddcb42fec5956769718543293c723" dependencies = [ "cc", - "secp256k1-sys 0.6.1", + "secp256k1-sys 0.8.1", ] [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -6233,9 +6233,9 @@ checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.207" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" dependencies = [ "serde_derive", ] @@ -6262,32 +6262,32 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.207" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "serde_html_form" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50437e6a58912eecc08865e35ea2e8d365fbb2db0debb1c8bb43bf1faf055f25" +checksum = "8de514ef58196f1fc96dcaef80fe6170a1ce6215df9687a93fe8300e773fefc5" dependencies = [ "form_urlencoded", - "indexmap 2.2.5", + "indexmap 2.4.0", "itoa", "ryu", "serde", @@ -6295,21 +6295,22 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.4.0", "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_path_to_error" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", "serde", @@ -6317,9 +6318,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -6338,15 +6339,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.7.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.5", + "indexmap 2.4.0", "serde", "serde_derive", "serde_json", @@ -6356,27 +6357,35 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.7.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] -name = "sha-1" -version = "0.9.8" +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "block-buffer 0.9.0", "cfg-if", "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "digest", ] [[package]] @@ -6387,7 +6396,7 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -6396,15 +6405,15 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.7", + "digest", "keccak", ] [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -6417,9 +6426,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -6435,9 +6444,9 @@ dependencies = [ [[package]] name = "similar" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" [[package]] name = "siphasher" @@ -6456,9 +6465,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smawk" @@ -6468,19 +6477,9 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -6488,26 +6487,20 @@ dependencies = [ [[package]] name = "soketto" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +checksum = "37468c595637c10857701c990f93a40ce0e357cedb0953d1c26c8d8027f9bb53" dependencies = [ - "base64 0.13.1", + "base64 0.22.1", "bytes", "futures", - "http 0.2.9", + "http 1.1.0", "httparse", "log", "rand", - "sha-1", + "sha1", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -6531,8 +6524,9 @@ dependencies = [ "anyhow", "async-stream", "async-trait", - "bitcoin 0.29.2", + "bitcoin 0.30.2", "erased-serde", + "fedimint-api-client", "fedimint-client", "fedimint-core", "futures", @@ -6541,8 +6535,6 @@ dependencies = [ "serde", "serde_json", "stability-pool-common", - "strum 0.24.1", - "strum_macros 0.24.3", "tokio", "tracing", ] @@ -6552,7 +6544,7 @@ name = "stability-pool-common" version = "0.3.0" dependencies = [ "anyhow", - "bitcoin 0.29.2", + "bitcoin 0.30.2", "fedimint-core", "secp256k1-zkp", "serde", @@ -6567,20 +6559,18 @@ version = "0.3.0" dependencies = [ "anyhow", "async-trait", - "bitcoin 0.29.2", + "bitcoin 0.30.2", "erased-serde", "fedimint-core", "futures", - "itertools 0.10.5", + "itertools 0.12.1", "rand", - "reqwest 0.11.27", - "ring 0.17.8", + "reqwest 0.12.5", + "ring", "secp256k1-zkp", "serde", "serde_json", "stability-pool-common", - "strum 0.24.1", - "strum_macros 0.24.3", "tokio", "tracing", ] @@ -6631,15 +6621,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -6649,9 +6633,9 @@ checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" [[package]] name = "strum_macros" @@ -6668,22 +6652,22 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -6698,9 +6682,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.71" +version = "2.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" dependencies = [ "proc-macro2", "quote", @@ -6748,9 +6732,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" +checksum = "cb797dad5fb5b76fcf519e702f4a589483b5ef06567f160c392832c1f5e44909" dependencies = [ "filetime", "libc", @@ -6759,14 +6743,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6782,18 +6767,18 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" dependencies = [ "smawk", "unicode-linebreak", @@ -6817,14 +6802,14 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -6894,9 +6879,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -6909,22 +6894,21 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.6", + "socket2", "tokio-macros", "tracing", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -6939,24 +6923,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", -] - -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.8", - "tokio", - "webpki", + "syn 2.0.74", ] [[package]] @@ -6965,7 +6938,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.8", + "rustls 0.21.12", "tokio", ] @@ -6975,7 +6948,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.22.2", + "rustls 0.22.4", "rustls-pki-types", "tokio", ] @@ -6986,16 +6959,16 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.7", + "rustls 0.23.12", "rustls-pki-types", "tokio", ] [[package]] name = "tokio-socks" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" dependencies = [ "either", "futures-util", @@ -7005,9 +6978,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -7017,9 +6990,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", @@ -7027,7 +7000,6 @@ dependencies = [ "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -7041,47 +7013,47 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.20.2", + "toml_edit 0.22.20", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.5", - "serde", - "serde_spanned", + "indexmap 2.4.0", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.4.0", + "serde", + "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.18", ] [[package]] @@ -7095,16 +7067,16 @@ dependencies = [ "axum 0.6.20", "base64 0.21.7", "bytes", - "h2 0.3.24", - "http 0.2.9", - "http-body 0.4.5", - "hyper 0.14.27", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.30", "hyper-timeout", "percent-encoding", "pin-project", "prost", - "rustls 0.21.8", - "rustls-pemfile 1.0.3", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", "tokio", "tokio-rustls 0.24.1", "tokio-stream", @@ -7125,15 +7097,15 @@ dependencies = [ "axum 0.6.20", "base64 0.21.7", "bytes", - "h2 0.3.24", - "http 0.2.9", - "http-body 0.4.5", - "hyper 0.14.27", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.30", "hyper-timeout", "percent-encoding", "pin-project", "prost", - "rustls-pemfile 2.1.1", + "rustls-pemfile 2.1.3", "rustls-pki-types", "tokio", "tokio-rustls 0.25.0", @@ -7154,7 +7126,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -7167,7 +7139,7 @@ dependencies = [ "proc-macro2", "prost-build", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -7197,10 +7169,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "base64 0.21.7", - "bitflags 2.4.0", + "bitflags 2.6.0", "bytes", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", @@ -7210,15 +7182,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -7234,11 +7206,12 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", + "thiserror", "time", "tracing-subscriber", ] @@ -7251,18 +7224,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", -] - -[[package]] -name = "tracing-chrome" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496b3cd5447f7ff527bbbf19b071ad542a000adf297d4127078b4dfdb931f41a" -dependencies = [ - "serde_json", - "tracing-core", - "tracing-subscriber", + "syn 2.0.74", ] [[package]] @@ -7294,7 +7256,7 @@ checksum = "a9be14ba1bbe4ab79e9229f7f89fab8d120b865859f10527f31c033e599d2284" dependencies = [ "js-sys", "once_cell", - "opentelemetry", + "opentelemetry 0.22.0", "opentelemetry_sdk", "smallvec", "tracing", @@ -7348,9 +7310,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "ts-rs" @@ -7369,15 +7331,21 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", "termcolor", ] +[[package]] +name = "typeid" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "059d83cc991e7a42fc37bd50941885db0888e34209f8cfd9aab07ddec03bc9cf" + [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "typewit" @@ -7396,9 +7364,9 @@ checksum = "e36a83ea2b3c704935a01b4642946aadd445cea40b10935e3f8bd8052b8193d6" [[package]] name = "ulid" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34778c17965aa2a08913b57e1f34db9b4a63f5de31768b55bf20d2795f921259" +checksum = "04f903f293d11f31c0c29e4148f6dc0d033a7f80cebc0282bea147611667d289" dependencies = [ "getrandom", "rand", @@ -7416,15 +7384,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-linebreak" @@ -7443,9 +7411,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "uniffi" @@ -7501,7 +7469,7 @@ version = "0.25.3" source = "git+https://github.com/mozilla/uniffi-rs?rev=f5fc9d7e9aa08889aedc45dd81ae9b4d3ec4cbe8#f5fc9d7e9aa08889aedc45dd81ae9b4d3ec4cbe8" dependencies = [ "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] @@ -7531,7 +7499,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.71", + "syn 2.0.74", "toml 0.5.11", "uniffi_build", "uniffi_meta", @@ -7582,12 +7550,6 @@ dependencies = [ "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" @@ -7596,9 +7558,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -7620,50 +7582,20 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", "wasm-bindgen", ] -[[package]] -name = "validator" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da339118f018cc70ebf01fafc103360528aad53717e4bf311db929cb01cb9345" -dependencies = [ - "idna", - "once_cell", - "regex", - "serde", - "serde_derive", - "serde_json", - "url", - "validator_derive", -] - -[[package]] -name = "validator_derive" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e88ea23b8f5e59230bff8a2f03c0ee0054a61d5b8343a38946bcd406fe624c" -dependencies = [ - "darling", - "proc-macro-error", - "proc-macro2", - "quote", - "regex", - "syn 2.0.71", -] - [[package]] name = "valuable" version = "0.1.0" @@ -7678,9 +7610,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vodozemac" @@ -7747,7 +7679,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", "wasm-bindgen-shared", ] @@ -7781,7 +7713,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7794,9 +7726,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-bindgen-test" -version = "0.3.36" +version = "0.3.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e636f3a428ff62b3742ebc3c70e254dfe12b8c2b469d688ea59cdd4abcf502" +checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b" dependencies = [ "console_error_panic_hook", "js-sys", @@ -7808,12 +7740,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.36" +version = "0.3.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f18c1fad2f7c4958e7bcce014fa212f59a65d5e3721d0f77e6c0b27ede936ba3" +checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" dependencies = [ "proc-macro2", "quote", + "syn 2.0.74", ] [[package]] @@ -7831,9 +7764,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -7855,8 +7788,8 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.8", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -7870,15 +7803,15 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.2" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.26.1" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" dependencies = [ "rustls-pki-types", ] @@ -7891,22 +7824,11 @@ dependencies = [ "nom", ] -[[package]] -name = "which" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" -dependencies = [ - "either", - "libc", - "once_cell", -] - [[package]] name = "wildmatch" -version = "2.3.1" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "017f0a8ed8331210d91b7a4c30d4edef8f21a65c02f2540496e2e79725f6d8a8" +checksum = "3928939971918220fed093266b809d1ee4ec6c1a2d72692ff6876898f3b16c19" [[package]] name = "winapi" @@ -7926,11 +7848,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -7940,12 +7862,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -7963,7 +7885,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.3", + "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]] @@ -7983,17 +7914,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.3" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.3", - "windows_aarch64_msvc 0.52.3", - "windows_i686_gnu 0.52.3", - "windows_i686_msvc 0.52.3", - "windows_x86_64_gnu 0.52.3", - "windows_x86_64_gnullvm 0.52.3", - "windows_x86_64_msvc 0.52.3", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -8004,9 +7936,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.3" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -8016,9 +7948,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.3" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -8028,9 +7960,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.3" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -8040,9 +7978,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.3" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -8052,9 +7990,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.3" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -8064,9 +8002,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.3" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -8076,15 +8014,24 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.3" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] [[package]] name = "winnow" -version = "0.5.18" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176b6138793677221d420fd2f0aeeced263f197688b36484660da767bca2fa32" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -8154,9 +8101,9 @@ dependencies = [ [[package]] name = "xxhash-rust" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63658493314859b4dfdf3fb8c1defd61587839def09582db50b8a4e93afca6bb" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" [[package]] name = "yasna" @@ -8169,29 +8116,30 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -8204,16 +8152,15 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", + "syn 2.0.74", ] [[package]] name = "zstd-sys" -version = "2.0.8+zstd.1.5.5" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", - "libc", "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index cca5a3c..0f44f25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,13 +17,14 @@ members = [ "modules/stability-pool/tests", "fedi-db-dump", "devi", + "fedi-api-types", "fedi-core", "fedi-debug", - "fedi-api-types", ] default-members = [ "fedimintd", "fedimint-cli", + "fedi-api-types", "modules/fedi-social/common", "modules/fedi-social/server", "modules/fedi-social/client", @@ -34,7 +35,6 @@ default-members = [ "modules/stability-pool/server", "modules/stability-pool/tests", "devi", - "fedi-api-types", ] resolver = "2" @@ -60,32 +60,33 @@ license-file = "LICENSE" keywords = ["bitcoin", "lightning", "chaumian", "e-cash", "federated"] [workspace.dependencies] -bitcoin = { version = "0.29.2", features = ["rand", "serde"] } -fedi-api-types = { path = "./fedi-api-types" } +bitcoin = { version = "0.30", features = ["rand", "serde"] } fedi-social-client = { path = "./modules/fedi-social/client" } serde = { version = "1.0.149", features = ["derive"] } serde_json = { version = "1" } subtle = "2.5.0" ring = "0.17.5" fedi-core = { path = "./fedi-core" } -anyhow = "1.0.66" +fedi-api-types = { path = "./fedi-api-types" } + +anyhow = "1" async-stream = "0.3.5" async-trait = "0.1" bincode = "1.3.1" -bitcoin_hashes = "0.11" -clap = "4.4.18" +bitcoin_hashes = "0.12" +clap = "4" erased-serde = "0.4" futures = "0.3" hex = { version = "0.4.2" } -impl-tools = "0.6.1" -itertools = "0.10.5" +impl-tools = "0.10.0" +itertools = "0.12.1" rand = "0.8" -reqwest = { version = "0.11.14", features = [ +reqwest = { version = "0.12", features = [ "json", "rustls-tls", ], default-features = false } -secp256k1 = "0.24.2" -secp256k1-zkp = "0.7.0" +secp256k1 = "0.27.0" +secp256k1-zkp = "0.9.2" strum = "0.24" strum_macros = "0.24" thiserror = "1.0.37" @@ -93,26 +94,27 @@ tokio = "1" tracing = "0.1.37" tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } -fedimint_threshold_crypto = { version = "0.1", package = "fedimint-threshold-crypto" } +fedimint_threshold_crypto = { version = "0.2.1", package = "fedimint-threshold-crypto" } -fedimintd = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-cli = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-build = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-core = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-server = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-client = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-derive-secret = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-mint-client = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-wallet-client = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-ln-client = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-ln-common = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-client-legacy = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-aead = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-rocksdb = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-bip39 = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -fedimint-logging = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -devimint = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } -ln-gateway = { git = "https://github.com/fedibtc/fedimint", tag = "v0.3.2-rc.0-fed1" } +fedimintd = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-cli = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-build = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-core = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-server = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-client = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-api-client = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-derive-secret = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-mint-client = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-wallet-client = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-ln-client = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-ln-common = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-client-legacy = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-aead = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-rocksdb = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-bip39 = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +fedimint-logging = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +devimint = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } +ln-gateway = { git = "https://github.com/fedibtc/fedimint", tag = "v0.4.2-rc.1-fed-3" } # Uncomment these to use local fedimint v2 @@ -177,7 +179,5 @@ debug = false debug = false [patch.crates-io] -secp256k1-zkp = { git = "https://github.com/fedibtc/rust-secp256k1-zkp/", tag = "fedi-0.1" } -ring = { git = "https://github.com/fedibtc/ring", tag = "fedi-0.1" } # https://github.com/mozilla/uniffi-rs/issues/1938 uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "f5fc9d7e9aa08889aedc45dd81ae9b4d3ec4cbe8" } diff --git a/SECURITY.md b/SECURITY.md index d453685..d757f3f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,7 +4,8 @@ | Version | Supported | | ------- | ------------------ | -| 1.18.0 | :white_check_mark: | +| 1.19.0+ | :white_check_mark: | +| 1.18.0+ | :white_check_mark: | | < 1.17 | :x: | ## Reporting a Vulnerability diff --git a/bridge/.gitignore b/bridge/.gitignore index 25902a9..f91e70c 100644 --- a/bridge/.gitignore +++ b/bridge/.gitignore @@ -1,11 +1,13 @@ target +# android/kotlin .idea/ fedi-bindings.iml libfediffi.so fedi.kt local.properties .DS_Store +artifacts # swift related /.build diff --git a/bridge/fedi-android/lib/build.gradle.kts b/bridge/fedi-android/lib/build.gradle.kts index da34885..3375686 100644 --- a/bridge/fedi-android/lib/build.gradle.kts +++ b/bridge/fedi-android/lib/build.gradle.kts @@ -61,9 +61,16 @@ afterEvaluate { pom { name.set("fedi-android") description.set("Fedi Kotlin language bindings.") - url.set("https://fedi.org") + url.set("https://fedi.xyz") } } } + repositories { + val androidBridgeArtifacts = System.getenv("ANDROID_BRIDGE_ARTIFACTS") ?: error("BRIDGE_ANDROID_ARTIFACTS environment variable must be set") + maven { + name = "fediAndroid" + url = uri("file://$androidBridgeArtifacts") + } + } } } \ No newline at end of file diff --git a/bridge/fedi-ffi/Cargo.toml b/bridge/fedi-ffi/Cargo.toml index cd83c66..847c4bd 100644 --- a/bridge/fedi-ffi/Cargo.toml +++ b/bridge/fedi-ffi/Cargo.toml @@ -8,13 +8,13 @@ crate-type = ["staticlib", "cdylib", "rlib"] name = "fediffi" [dependencies] -fedi-api-types = { path = "../../fedi-api-types" } - +fedi-api-types = { workspace = true } fedi-core = { workspace = true } fedimint-core = { workspace = true } fedimint-client = { workspace = true } fedimint-mint-client = { workspace = true } fedimint-ln-client = { workspace = true } +fedimint-api-client = { workspace = true } fedimint-ln-common = { workspace = true } fedimint-wallet-client = { workspace = true } fedi-social-client = { workspace = true } @@ -33,7 +33,7 @@ serde_json = { workspace = true } rand = { workspace = true } bitcoin = { workspace = true } lazy_static = "1.4.0" -lightning-invoice = "0.26.0" +lightning-invoice = "0.31.0" futures = "0.3" tracing = { workspace = true } tracing-serde = "0.1.3" @@ -43,7 +43,6 @@ macro_rules_attribute = "0.1.3" mime = "0.3.17" ts-rs = { git = "https://github.com/fedibtc/ts-rs", tag = "fedi-0.1" } async-trait = { workspace = true } -base64 = "0.20.0" tokio = { workspace = true, features = ["time", "macros"] } url = "2.3.1" reqwest = { workspace = true } @@ -77,6 +76,11 @@ uniffi = { version = "0.25.3" } matrix-sdk = { version = "0.7.1", git = "https://github.com/fedibtc/matrix-rust-sdk", tag = "fedi-0.1", default-features = false, features = [ "sqlite", ] } +rusqlite = { version = "*" } + +# we don't have an easy way to get static sqlite for android targets +# so we enable bundled feature when compiling for it +[target.'cfg(target_os = "android")'.dependencies] rusqlite = { version = "*", features = ["bundled"] } [build-dependencies] diff --git a/bridge/fedi-ffi/src/api.rs b/bridge/fedi-ffi/src/api.rs index 27669fd..1d96ffc 100644 --- a/bridge/fedi-ffi/src/api.rs +++ b/bridge/fedi-ffi/src/api.rs @@ -221,7 +221,7 @@ impl IFediApi for LiveFediApi { .post(api_url) .json(&GenerateInvoiceRequestV1 { amount_msat: amount.msats, - module, + module: module.to_string(), tx_direction: match tx_direction { RpcTransactionDirection::Send => TransactionDirection::Send, RpcTransactionDirection::Receive => TransactionDirection::Receive, diff --git a/bridge/fedi-ffi/src/bridge.rs b/bridge/fedi-ffi/src/bridge.rs index 033d9ca..dd1965c 100644 --- a/bridge/fedi-ffi/src/bridge.rs +++ b/bridge/fedi-ffi/src/bridge.rs @@ -6,15 +6,17 @@ use std::time::Duration; use anyhow::{anyhow, bail, Context, Result}; use bitcoin::bech32::{self, ToBase32}; +use bitcoin::key::XOnlyPublicKey; use bitcoin::secp256k1::{Message, Secp256k1}; use fedi_social_client::{ self, FediSocialCommonGen, RecoveryFile, SocialRecoveryClient, SocialRecoveryState, }; -use fedimint_core::api::{DynGlobalApi, InviteCode}; +use fedimint_api_client::api::DynGlobalApi; use fedimint_core::config::ClientConfig; use fedimint_core::core::ModuleKind; use fedimint_core::db::{Database, IDatabaseTransactionOpsCore}; use fedimint_core::encoding::{Decodable, Encodable}; +use fedimint_core::invite_code::InviteCode; use fedimint_core::module::registry::ModuleDecoderRegistry; use fedimint_core::module::CommonModuleInit; use fedimint_core::task::TaskGroup; @@ -85,7 +87,7 @@ impl Bridge { let fedi_fee_helper = Arc::new(FediFeeHelper::new( fedi_api.clone(), app_state.clone(), - task_group.make_subgroup().await, + task_group.make_subgroup(), )); let _device_identifier = app_state @@ -139,7 +141,7 @@ impl Bridge { FederationV2::from_db( db, event_sink.clone(), - task_group.make_subgroup().await, + task_group.make_subgroup(), &root_mnemonic, // Always present when join federations exist device_index.context( @@ -179,7 +181,7 @@ impl Bridge { let communities = Communities::init( app_state.clone(), event_sink.clone(), - task_group.make_subgroup().await, + task_group.make_subgroup(), ) .await .into(); @@ -316,7 +318,7 @@ impl Bridge { let federation_v2 = FederationV2::from_db( db, this.event_sink.clone(), - this.task_group.make_subgroup().await, + this.task_group.make_subgroup(), &root_mnemonic, device_index, this.fedi_fee_helper.clone(), @@ -325,6 +327,9 @@ impl Bridge { .await .with_context(|| format!("loading federation {}", federation_id.clone()))?; let fed_network = federation_v2.get_network(); + if federation_v2.recovering() { + error!(%federation_id, "federation must be recovered after restart on recovery completed once"); + } federation_lock.insert(federation_id.clone(), Arc::new(federation_v2)); info!(%federation_id, "reinserted to federation list"); drop(federation_lock); @@ -348,11 +353,18 @@ impl Bridge { /// /// Federation ID saved to global database, new rocksdb database created for /// it, and it is saved to local hashmap by ID - pub async fn join_federation(&self, invite_code_string: String) -> Result { + pub async fn join_federation( + &self, + invite_code_string: String, + recover_from_scratch: bool, + ) -> Result { let invite_code = invite_code_string.to_lowercase(); // FIXME: this is kinda unreliable let mut error_code = None; - match self.join_federation_inner(invite_code.clone()).await { + match self + .join_federation_inner(invite_code.clone(), recover_from_scratch) + .await + { Ok(federation) => { info!("Joined v2 federation"); return Ok(federation_v2_to_rpc_federation(&federation).await); @@ -368,7 +380,11 @@ impl Bridge { bail!("failed to join") } - async fn join_federation_inner(&self, invite_code_string: String) -> Result> { + async fn join_federation_inner( + &self, + invite_code_string: String, + recover_from_scratch: bool, + ) -> Result> { // Check if we've already joined this federation let invite_code = InviteCode::from_str(&invite_code_string)?; if self @@ -393,10 +409,11 @@ impl Bridge { let federation = FederationV2::join( invite_code_string, self.event_sink.clone(), - self.task_group.make_subgroup().await, + self.task_group.make_subgroup(), db, &root_mnemonic, device_index, + recover_from_scratch, self.fedi_fee_helper.clone(), self.feature_catalog.clone(), ) @@ -443,33 +460,30 @@ impl Bridge { let invite_code = invite_code.to_lowercase(); let root_mnemonic = self.app_state.root_mnemonic().await; let device_index = self.app_state.ensure_device_index().await?; - let (v2,) = futures::join!(FederationV2::download_client_config( + let (config, backup) = FederationV2::download_client_config( &invite_code, &root_mnemonic, device_index, self.feature_catalog.override_localhost.is_some(), - )); - match (v2,) { - (Ok((config, backup_snapshots_result)),) => Ok(RpcFederationPreview { - id: RpcFederationId(config.global.calculate_federation_id().to_string()), - name: config - .global - .federation_name() - .map(|x| x.to_owned()) - .unwrap_or( - config.global.calculate_federation_id().to_string()[0..8].to_string(), - ), - meta: config.global.meta, - invite_code: invite_code.to_string(), - version: 2, - returning_member_status: match backup_snapshots_result.as_deref() { - Ok([]) => RpcReturningMemberStatus::NewMember, - Ok([_, ..]) => RpcReturningMemberStatus::ReturningMember, - Err(_) => RpcReturningMemberStatus::Unknown, - }, - }), - (Err(e),) => Err(e.context("Failed to connect")), - } + ) + .await + .context("failed to connect")?; + Ok(RpcFederationPreview { + id: RpcFederationId(config.global.calculate_federation_id().to_string()), + name: config + .global + .federation_name() + .map(|x| x.to_owned()) + .unwrap_or(config.global.calculate_federation_id().to_string()[0..8].to_string()), + meta: config.global.meta, + invite_code: invite_code.to_string(), + version: 2, + returning_member_status: match backup { + Ok(Some(_)) => RpcReturningMemberStatus::ReturningMember, + Ok(None) => RpcReturningMemberStatus::NewMember, + Err(_) => RpcReturningMemberStatus::Unknown, + }, + }) } /// Look up federation by id from in-memory hashmap @@ -670,6 +684,7 @@ impl Bridge { )?, ) .to_string(), + false, ) .await .map(Some) @@ -749,7 +764,15 @@ impl Bridge { ) .expect("needs social recovery module client config"); - let social_api = DynGlobalApi::from_config(&config).with_module(social_module_id); + let social_api = DynGlobalApi::from_endpoints( + config + .global + .api_endpoints + .iter() + .map(|(peer_id, peer_url)| (*peer_id, peer_url.url.clone())), + &None, // FIXME: api secret + ) + .with_module(social_module_id); let client = SocialRecoveryClient::new_start( social_module_id, social_cfg.clone(), @@ -838,7 +861,15 @@ impl Bridge { "fedi-social", ) .expect("needs social recovery module client config"); - let social_api = DynGlobalApi::from_config(&config).with_module(social_module_id); + let social_api = DynGlobalApi::from_endpoints( + config + .global + .api_endpoints + .iter() + .map(|(peer_id, peer_url)| (*peer_id, peer_url.url.clone())), + &None, // FIXME: api secret + ) + .with_module(social_module_id); let recovery_client = SocialRecoveryClient::new_continue( social_module_id, social_cfg.clone(), @@ -895,9 +926,12 @@ impl Bridge { &self, federation_id: RpcFederationId, recovery_id: RpcRecoveryId, + peer_id: RpcPeerId, ) -> Result> { let federation = self.get_federation(&federation_id.0).await?; - let verification_doc = federation.download_verification_doc(&recovery_id.0).await?; + let verification_doc = federation + .download_verification_doc(&recovery_id.0, peer_id.0) + .await?; if let Some(verification_doc) = verification_doc { self.storage .write_file(VERIFICATION_FILENAME.as_ref(), verification_doc) @@ -956,7 +990,7 @@ impl Bridge { Ok(bech32::encode("npub", data, bech32::Variant::Bech32)?) } - async fn nostr_pubkey(&self) -> bitcoin::XOnlyPublicKey { + async fn nostr_pubkey(&self) -> XOnlyPublicKey { let global_root_secret = self.app_state.root_secret().await; let secp = Secp256k1::new(); let nostr_secret = global_root_secret.child_key(ChildId(NOSTR_CHILD_ID)); diff --git a/bridge/fedi-ffi/src/community/mod.rs b/bridge/fedi-ffi/src/community/mod.rs index 25d908c..36a63c4 100644 --- a/bridge/fedi-ffi/src/community/mod.rs +++ b/bridge/fedi-ffi/src/community/mod.rs @@ -7,8 +7,8 @@ use std::time::Duration; use anyhow::{bail, Context}; use bitcoin::bech32::{self, FromBase32}; use fedimint_core::task::TaskGroup; +use fedimint_core::util::backon::FibonacciBuilder as FibonacciBackoff; use fedimint_core::util::update_merge::UpdateMerge; -use fedimint_core::util::FibonacciBackoff; use serde::{Deserialize, Serialize}; use tokio::sync::{Mutex, RwLock}; use tracing::info; diff --git a/bridge/fedi-ffi/src/device_registration.rs b/bridge/fedi-ffi/src/device_registration.rs index 6d7de9d..584f7e3 100644 --- a/bridge/fedi-ffi/src/device_registration.rs +++ b/bridge/fedi-ffi/src/device_registration.rs @@ -3,7 +3,8 @@ use std::time::{Duration, SystemTime}; use anyhow::{anyhow, bail}; use fedimint_core::task::TaskGroup; -use fedimint_core::util::{retry, FibonacciBackoff}; +use fedimint_core::util::backon::FibonacciBuilder as FibonacciBackoff; +use fedimint_core::util::retry; use tracing::{error, info}; use crate::api::{IFediApi, RegisterDeviceError, RegisteredDevice}; @@ -96,7 +97,7 @@ impl DeviceRegistrationService { task_group: &TaskGroup, event_sink: EventSink, ) { - let subgroup = task_group.make_subgroup().await; + let subgroup = task_group.make_subgroup(); subgroup.spawn_cancellable( "device_registration_service", renew_registration_periodically( diff --git a/bridge/fedi-ffi/src/error.rs b/bridge/fedi-ffi/src/error.rs index b233811..a71ae0d 100644 --- a/bridge/fedi-ffi/src/error.rs +++ b/bridge/fedi-ffi/src/error.rs @@ -37,6 +37,12 @@ pub enum ErrorCode { Recovery, #[error("Deserializing JSON failed: {0}")] InvalidJson(String), + #[error("pay_invoice is already paid")] + PayLnInvoiceAlreadyPaid, + #[error("pay_invoice is already in progress")] + PayLnInvoiceAlreadyInProgress, + #[error("No Lightning gateway is available")] + NoLnGatewayAvailable, } pub fn get_error_code(err: &anyhow::Error) -> Option { diff --git a/bridge/fedi-ffi/src/federation_v2/backup_service.rs b/bridge/fedi-ffi/src/federation_v2/backup_service.rs index 0f93a23..1b24752 100644 --- a/bridge/fedi-ffi/src/federation_v2/backup_service.rs +++ b/bridge/fedi-ffi/src/federation_v2/backup_service.rs @@ -4,8 +4,9 @@ use anyhow::Result; use fedimint_client::backup::Metadata; use fedimint_client::Client; use fedimint_core::db::{DatabaseTransaction, IDatabaseTransactionOpsCoreTyped}; +use fedimint_core::util::backon::{BackoffBuilder, FibonacciBuilder as FibonacciBackoff}; +use fedimint_core::util::retry; use fedimint_core::util::update_merge::UpdateMerge; -use fedimint_core::util::{retry, BackoffBuilder, FibonacciBackoff}; use futures::lock::Mutex; use serde::Serialize; use tracing::{error, info, instrument}; diff --git a/bridge/fedi-ffi/src/federation_v2/dev.rs b/bridge/fedi-ffi/src/federation_v2/dev.rs index 56c7b11..a8adf52 100644 --- a/bridge/fedi-ffi/src/federation_v2/dev.rs +++ b/bridge/fedi-ffi/src/federation_v2/dev.rs @@ -3,8 +3,8 @@ /// emulator use std::str::FromStr; -use fedimint_core::api::InviteCode; use fedimint_core::config::ClientConfig; +use fedimint_core::invite_code::InviteCode; use fedimint_core::util::SafeUrl; use tracing::info; @@ -34,6 +34,7 @@ pub fn override_localhost_invite_code(invite_code: &mut InviteCode) { override_localhost(&invite_code.url()), invite_code.peer(), invite_code.federation_id(), + invite_code.api_secret(), ); } diff --git a/bridge/fedi-ffi/src/federation_v2/meta.rs b/bridge/fedi-ffi/src/federation_v2/meta.rs new file mode 100644 index 0000000..52996f3 --- /dev/null +++ b/bridge/fedi-ffi/src/federation_v2/meta.rs @@ -0,0 +1,93 @@ +use std::collections::BTreeMap; +use std::time::Duration; + +use fedimint_client::db::{MetaFieldKey, MetaFieldPrefix, MetaFieldValue, MetaServiceInfoKey}; +use fedimint_client::meta::{fetch_meta_overrides, FetchKind, MetaService, MetaSource, MetaValues}; +use fedimint_client::Client; +use fedimint_core::db::{Database, IDatabaseTransactionOpsCoreTyped}; +use fedimint_core::util::{backon, retry}; +use fedimint_core::{apply, async_trait_maybe_send}; +use futures::StreamExt; + +pub type MetaEntries = BTreeMap; + +#[apply(async_trait_maybe_send)] +pub trait MetaServiceExt { + async fn entries_from_db(&self, db: &Database) -> Option; +} + +#[apply(async_trait_maybe_send)] +impl MetaServiceExt for MetaService { + /// Retrieve all meta entries from the database + async fn entries_from_db(&self, db: &Database) -> Option { + let dbtx = &mut db.begin_transaction_nc().await; + let info = dbtx.get_value(&MetaServiceInfoKey).await; + #[allow(clippy::question_mark)] // more readable + if info.is_none() { + return None; + } + let entries: MetaEntries = dbtx + .find_by_prefix(&MetaFieldPrefix) + .await + .map(|(k, v)| (k.0, v.0)) + .collect() + .await; + Some(entries) + } +} + +/// Legacy non-meta module config source uses client config meta and +/// meta_override_url meta field. +#[derive(Clone, Debug, Default)] +#[non_exhaustive] +pub struct LegacyMetaSourceWithExternalUrl { + reqwest: reqwest::Client, +} + +pub const META_EXTERNAL_URL_FIELD: &str = "meta_external_url"; +pub const META_OVERRIDE_URL_FIELD: &str = "meta_override_url"; +#[apply(async_trait_maybe_send!)] +impl MetaSource for LegacyMetaSourceWithExternalUrl { + async fn wait_for_update(&self) { + fedimint_core::runtime::sleep(Duration::from_secs(10 * 60)).await; + } + + async fn fetch( + &self, + client: &Client, + fetch_kind: FetchKind, + last_revision: Option, + ) -> anyhow::Result { + let config_iter = client + .config() + .await + .global + .meta + .into_iter() + .map(|(key, value)| (MetaFieldKey(key.clone()), MetaFieldValue(value.clone()))); + let backoff = match fetch_kind { + // need to be fast the first time. + FetchKind::Initial => backon::FibonacciBuilder::default() + .with_min_delay(Duration::from_millis(300)) + .with_max_delay(Duration::from_secs(3)) + .with_max_times(10), + FetchKind::Background => backon::FibonacciBuilder::default() + .with_min_delay(Duration::from_secs(10)) + .with_max_delay(Duration::from_secs(10 * 60)) + .with_max_times(usize::MAX), + }; + let overrides = retry("fetch_meta_overrides", backoff, || async { + let static_meta = &client.config().await.global.meta; + if static_meta.contains_key(META_OVERRIDE_URL_FIELD) { + fetch_meta_overrides(&self.reqwest, client, META_OVERRIDE_URL_FIELD).await + } else { + fetch_meta_overrides(&self.reqwest, client, META_EXTERNAL_URL_FIELD).await + } + }) + .await?; + Ok(MetaValues { + values: config_iter.chain(overrides).collect(), + revision: last_revision.map_or(0, |r| r + 1), + }) + } +} diff --git a/bridge/fedi-ffi/src/federation_v2/mod.rs b/bridge/fedi-ffi/src/federation_v2/mod.rs index d50aab0..859e565 100644 --- a/bridge/fedi-ffi/src/federation_v2/mod.rs +++ b/bridge/fedi-ffi/src/federation_v2/mod.rs @@ -1,16 +1,19 @@ pub mod db; mod dev; +mod meta; use std::any::Any; use std::collections::HashMap; +use std::fmt::Debug; use std::pin::pin; use std::str::FromStr; use std::sync::Arc; -use std::time::{Duration, SystemTime}; +use std::time::Duration; use ::serde::{Deserialize, Serialize}; use anyhow::{anyhow, bail, Context, Result}; -use bitcoin::secp256k1::{self, PublicKey, Secp256k1}; +use bitcoin::address::NetworkUnchecked; +use bitcoin::secp256k1::PublicKey; use bitcoin::{Address, Network}; use db::{FediRawClientConfigKey, InviteCodeKey, TransactionNotesKey, XmppUsernameKey}; use fedi_social_client::common::VerificationDocument; @@ -18,53 +21,57 @@ use fedi_social_client::{ FediSocialClientInit, RecoveryFile, RecoveryId, SocialBackup, SocialRecoveryClient, SocialRecoveryState, SocialVerification, UserSeedPhrase, SOCIAL_RECOVERY_SECRET_CHILD_ID, }; +use fedimint_api_client::api::{ + DynGlobalApi, DynModuleApi, FederationApiExt as _, StatusResponse, WsFederationApi, +}; +use fedimint_api_client::download_from_invite_code; use fedimint_bip39::Bip39RootSecretStrategy; -use fedimint_client::backup::Metadata; +use fedimint_client::backup::{ClientBackup, Metadata}; use fedimint_client::db::ChronologicalOperationLogKey; +use fedimint_client::meta::MetaService; use fedimint_client::module::recovery::RecoveryProgress; use fedimint_client::module::ClientModule; -use fedimint_client::oplog::OperationLogEntry; -use fedimint_client::secret::{DeriveableSecretClientExt, RootSecretStrategy}; +use fedimint_client::oplog::{OperationLogEntry, UpdateStreamOrOutcome}; +use fedimint_client::secret::RootSecretStrategy; use fedimint_client::{Client, ClientBuilder, ClientHandle, ClientHandleArc}; -use fedimint_core::api::{ - DynGlobalApi, DynModuleApi, FederationApiExt, FederationResult, InviteCode, StatusResponse, - WsFederationApi, -}; -use fedimint_core::backup::ClientBackupSnapshot; use fedimint_core::config::{ClientConfig, FederationId}; use fedimint_core::core::{ModuleKind, OperationId}; use fedimint_core::db::{ Committable, Database, DatabaseTransaction, IDatabaseTransactionOpsCoreTyped, }; +use fedimint_core::invite_code::InviteCode; +use fedimint_core::module::registry::ModuleDecoderRegistry; use fedimint_core::module::ApiRequestErased; use fedimint_core::task::{timeout, MaybeSend, MaybeSync, TaskGroup}; use fedimint_core::timing::TimeReporter; -use fedimint_core::util::FibonacciBackoff; +use fedimint_core::util::backon::FibonacciBuilder as FibonacciBackoff; use fedimint_core::{maybe_add_send_sync, Amount, PeerId}; use fedimint_derive_secret::{ChildId, DerivableSecret}; use fedimint_ln_client::{ InternalPayState, LightningClientInit, LightningClientModule, LightningOperationMeta, LightningOperationMetaPay, LightningOperationMetaVariant, LnPayState, LnReceiveState, - OutgoingLightningPayment, PayType, + OutgoingLightningPayment, PayBolt11InvoiceError, PayType, }; +use fedimint_ln_common::config::FeeToAmount; use fedimint_ln_common::LightningGateway; use fedimint_mint_client::{ spendable_notes_to_operation_id, MintClientInit, MintClientModule, MintOperationMeta, - MintOperationMetaVariant, OOBNotes, ReissueExternalNotesState, + MintOperationMetaVariant, OOBNotes, ReissueExternalNotesState, SelectNotesWithExactAmount, }; use fedimint_wallet_client::{ - DepositState, PegOutFees, WalletClientInit, WalletClientModule, WalletOperationMeta, + DepositStateV2, PegOutFees, WalletClientInit, WalletClientModule, WalletOperationMeta, WalletOperationMetaVariant, WithdrawState, }; use futures::{FutureExt, StreamExt}; use lightning_invoice::{Bolt11Invoice, RoutingFees}; +use meta::{LegacyMetaSourceWithExternalUrl, MetaEntries, MetaServiceExt}; use serde::de::DeserializeOwned; use stability_pool_client::{ ClientAccountInfo, StabilityPoolClientInit, StabilityPoolClientModule, StabilityPoolDepositOperationState, StabilityPoolMeta, StabilityPoolWithdrawalOperationState, }; use tokio::sync::{Mutex, OnceCell}; -use tracing::{error, info, warn}; +use tracing::{error, info, warn, Level}; use self::backup_service::BackupService; pub use self::backup_service::BackupServiceStatus; @@ -94,10 +101,11 @@ use crate::features::FeatureCatalog; use crate::fedi_fee::{FediFeeHelper, FediFeeRemittanceService}; use crate::storage::FediFeeSchedule; use crate::types::{ - EcashReceiveMetadata, GuardianStatus, LightningSendMetadata, OperationFediFeeStatus, - RpcBitcoinDetails, RpcEcashInfo, RpcFederationId, RpcFeeDetails, RpcGenerateEcashResponse, - RpcLightningDetails, RpcLnState, RpcOOBState, RpcOnchainState, RpcPayAddressResponse, - RpcStabilityPoolTransactionState, RpcTransaction, RpcTransactionDirection, WithdrawalDetails, + EcashReceiveMetadata, EcashSendMetadata, GuardianStatus, LightningSendMetadata, + OperationFediFeeStatus, RpcBitcoinDetails, RpcEcashInfo, RpcFederationId, RpcFeeDetails, + RpcGenerateEcashResponse, RpcLightningDetails, RpcLnState, RpcOOBState, RpcOnchainState, + RpcOperationFediFeeStatus, RpcPayAddressResponse, RpcStabilityPoolTransactionState, + RpcTransaction, RpcTransactionDirection, WithdrawalDetails, }; use crate::utils::{display_currency, to_unix_time, unix_now}; @@ -131,6 +139,7 @@ pub fn invite_code_from_client_confing(config: &ClientConfig) -> InviteCode { endpoint.url.clone(), *peer, config.global.calculate_federation_id(), + None, // FIXME: api secret ) } @@ -163,9 +172,11 @@ pub struct FederationV2 { impl FederationV2 { /// Instantiate Federation from FediConfig async fn build_client_builder(db: Database) -> anyhow::Result { - let mut client_builder = fedimint_client::Client::builder(db); + let mut client_builder = fedimint_client::Client::builder(db).await?; + client_builder + .with_meta_service(MetaService::new(LegacyMetaSourceWithExternalUrl::default())); client_builder.with_module(MintClientInit); - client_builder.with_module(LightningClientInit); + client_builder.with_module(LightningClientInit::default()); client_builder.with_module(WalletClientInit(None)); client_builder.with_module(FediSocialClientInit); client_builder.with_module(StabilityPoolClientInit); @@ -181,7 +192,7 @@ impl FederationV2 { fedi_fee_helper: Arc, feature_catalog: Arc, ) -> Self { - let recovering = ng.has_pending_recoveries().await; + let recovering = ng.has_pending_recoveries(); let client = Arc::new(ng); let mut federation = Self { event_sink, @@ -217,19 +228,37 @@ impl FederationV2 { self.subscribe_to_all_operations().await; if self - .fedi_fee_remittance_service - .set(FediFeeRemittanceService::default()) + .gateway_service + .set(LnGatewayService::new(self.client.clone(), &self.task_group)) .is_err() { - error!("fedi fee remittance service already initialized"); + error!("ln gateway service already initialized"); } + + // This needs to be initialized after LnGatewayService since remitting fees + // happens through lightning and we need a gateway for that. if self - .gateway_service - .set(LnGatewayService::new(self.client.clone(), &self.task_group)) + .fedi_fee_remittance_service + .set(FediFeeRemittanceService::init(self)) .is_err() { - error!("ln gateway service already initialized"); + error!("fedi fee remittance service already initialized"); } + + let federation = self.clone(); + self.task_group + .spawn_cancellable("send_meta_updates", async move { + let mut subscribe_to_updates = + std::pin::pin!(federation.client.meta_service().subscribe_to_updates()); + while subscribe_to_updates.next().await.is_some() { + federation.send_federation_event().await; + } + }); + + // We disable the StabilityPoolSweeperService in tests to ensure that staged + // seeks don't accidentally disappear if a test takes longer than expected and a + // stability pool cycle elapses during the course of the test. + #[cfg(not(test))] if self .client .get_first_instance(&stability_pool_client::common::KIND) @@ -282,7 +311,8 @@ impl FederationV2 { let federation_id = config.calculate_federation_id(); let client = { - let _g = TimeReporter::new("federation loading"); + info!("started federation loading"); + let _g = TimeReporter::new("federation loading").level(Level::INFO); client_builder .open(Self::client_root_secret_from_root_mnemonic( root_mnemonic, @@ -296,7 +326,7 @@ impl FederationV2 { Ok(Self::new( client, event_sink, - task_group.make_subgroup().await, + task_group.make_subgroup(), auxiliary_secret, fedi_fee_helper, feature_catalog, @@ -309,31 +339,25 @@ impl FederationV2 { root_mnemonic: &bip39::Mnemonic, device_index: u8, should_override_localhost: bool, - ) -> anyhow::Result<(ClientConfig, FederationResult>)> { + ) -> anyhow::Result<(ClientConfig, anyhow::Result>)> { let mut invite_code: InviteCode = InviteCode::from_str(invite_code_string)?; if should_override_localhost { override_localhost_invite_code(&mut invite_code); } - let api = DynGlobalApi::from_invite_code(&[invite_code.clone()]); - let backup_id_pub_key = { + let api = DynGlobalApi::from_invite_code(&invite_code); + let client_root_sercet = { let federation_id = invite_code.federation_id(); // We do an additional derivation using `DerivableSecret::federation_key` since // that is what fedimint-client does internally - let client_root_secret = Self::client_root_secret_from_root_mnemonic( - root_mnemonic, - &federation_id, - device_index, - ) - .federation_key(&federation_id); - client_root_secret - .derive_backup_secret() - .to_secp_key(&Secp256k1::::gen_new()) - .public_key() + Self::client_root_secret_from_root_mnemonic(root_mnemonic, &federation_id, device_index) + .federation_key(&federation_id) }; + // we only use this to check if backup exists + let decoders = ModuleDecoderRegistry::default().with_fallback(); let (client_config, backup) = tokio::join!( - ClientConfig::download_from_invite_code(&invite_code), - api.download_backup(&backup_id_pub_key) + download_from_invite_code(&invite_code), + Client::download_backup_from_federation_static(&api, &client_root_sercet, &decoders,) ); Ok((client_config?, backup)) @@ -349,6 +373,7 @@ impl FederationV2 { db: Database, root_mnemonic: &bip39::Mnemonic, device_index: u8, + recover_from_scratch: bool, fedi_fee_helper: Arc, feature_catalog: Arc, ) -> Result { @@ -357,8 +382,7 @@ impl FederationV2 { if feature_catalog.override_localhost.is_some() { override_localhost_invite_code(&mut invite_code); } - let mut client_config: ClientConfig = - ClientConfig::download_from_invite_code(&invite_code).await?; + let mut client_config: ClientConfig = download_from_invite_code(&invite_code).await?; if feature_catalog.override_localhost.is_some() { override_localhost_client_config(&mut client_config); } @@ -386,41 +410,38 @@ impl FederationV2 { let auxiliary_secret = Self::auxiliary_secret_from_root_mnemonic(root_mnemonic, &federation_id, device_index); // restore from scratch is not used because it takes too much time. - if let Some(backup) = client_builder - .download_backup_from_federation(&client_secret, &client_config) - .await? - { - // TODO: ensure that if user exists app and re-opens during the restoration, - // they will still see a spinner - info!("backup found {:?}", backup); - let client = client_builder - .recover(client_secret, client_config, Some(backup)) - .await?; - let metadata = client.get_metadata().await; - let this = Self::new( - client, - event_sink, - task_group.make_subgroup().await, - auxiliary_secret, - fedi_fee_helper, - feature_catalog, - ) - .await; - this.save_restored_metadata(metadata).await?; - Ok(this) + // FIXME: api secret + let client_backup = client_builder + .download_backup_from_federation(&client_secret, &client_config, None) + .await?; + let client = if recover_from_scratch { + info!("recovering from scratch"); + client_builder + .recover(client_secret, client_config, None, None) + .await? + } else if let Some(client_backup) = client_backup { + info!("backup found {:?}", client_backup); + client_builder + .recover(client_secret, client_config, None, Some(client_backup)) + .await? } else { info!("backup not found"); - let client = client_builder.join(client_secret, client_config).await?; - Ok(Self::new( - client, - event_sink, - task_group.make_subgroup().await, - auxiliary_secret, - fedi_fee_helper, - feature_catalog, - ) - .await) - } + client_builder + .join(client_secret, client_config, None) + .await? + }; + let metadata = client.get_metadata().await; + let this = Self::new( + client, + event_sink, + task_group.make_subgroup(), + auxiliary_secret, + fedi_fee_helper, + feature_catalog, + ) + .await; + this.save_restored_metadata(metadata).await?; + Ok(this) } /// Get federation ID @@ -463,6 +484,18 @@ impl FederationV2 { .unwrap_or(self.federation_id().to_string()[0..8].to_string()) } + pub async fn get_cached_meta(&self) -> MetaEntries { + match self + .client + .meta_service() + .entries_from_db(self.client.db()) + .await + { + Some(entries) => entries, + None => self.client.config().await.global.meta, + } + } + /// Create database transaction pub async fn dbtx(&self) -> DatabaseTransaction<'_, Committable> { self.client.db().begin_transaction().await @@ -495,16 +528,16 @@ impl FederationV2 { } pub async fn guardian_status(&self) -> anyhow::Result> { + let api_secret = self.client.api_secret(); let peer_clients: Vec<_> = self .client - .get_config() - .global - .api_endpoints + .get_peer_urls() + .await .iter() // use iter() instead of into_iter() .map(|(&peer_id, endpoint)| { ( peer_id, - WsFederationApi::new(vec![(peer_id, endpoint.url.clone())]), + WsFederationApi::new(vec![(peer_id, endpoint.clone())], api_secret), ) }) .collect(); @@ -603,24 +636,24 @@ impl FederationV2 { /// Generate bitcoin address pub async fn generate_address(&self) -> Result { - let fedi_fee_ppm = self - .fedi_fee_helper - .get_fedi_fee_ppm( - self.federation_id().to_string(), - fedimint_wallet_client::KIND, - RpcTransactionDirection::Receive, - ) - .await?; - let expires_at = fedimint_core::time::now() + Duration::from_secs(86400 * 365); - let (operation_id, address) = self + // FIXME: add fedi fees once fedimint await primary module outputs + // let fedi_fee_ppm = self + // .fedi_fee_helper + // .get_fedi_fee_ppm( + // self.federation_id().to_string(), + // fedimint_wallet_client::KIND, + // RpcTransactionDirection::Receive, + // ) + // .await?; + let (operation_id, address, _) = self .client .get_first_module::() - .get_deposit_address(expires_at, ()) - .await?; - self.write_pending_receive_fedi_fee_ppm(operation_id, fedi_fee_ppm) + .allocate_deposit_address_expert_only(()) .await?; + // self.write_pending_receive_fedi_fee_ppm(operation_id, fedi_fee_ppm) + // .await?; - self.subscribe_deposit(operation_id, address.to_string(), expires_at) + self.subscribe_deposit(operation_id, address.to_string()) .await?; Ok(address.to_string()) @@ -674,51 +707,47 @@ impl FederationV2 { }) } - async fn subscribe_deposit( - &self, - operation_id: OperationId, - address: String, - expires_at: SystemTime, - ) -> Result<()> { + async fn subscribe_deposit(&self, operation_id: OperationId, address: String) -> Result<()> { let fed = self.clone(); fed.task_group .clone() - .spawn("subscribe deposit", move |_| async move { - let mut updates = fed - .client - .get_first_module::() - .subscribe_deposit_updates(operation_id) + .spawn_cancellable("subscribe deposit", async move { + let wallet = fed.client.get_first_module::(); + let Ok(mut updates) = wallet + .subscribe_deposit(operation_id) .await - .unwrap() // FIXME - .into_stream(); + .map(|x| x.into_stream()) + .inspect_err(|e| { + warn!("subscribing to 0.3 deposits is not implemented: {e}"); + }) + else { + return; + }; while let Some(update) = updates.next().await { info!("Update: {:?}", update); fed.update_operation_state(operation_id, update.clone()) .await; let deposit_outcome = update.clone(); match update { - DepositState::WaitingForConfirmation(data) - | DepositState::Claimed(data) - | DepositState::Confirmed(data) => { - let amount = Amount::from_sats( - data.btc_transaction.output[data.out_idx as usize].value, - ); - let fedi_fee_status = fed - .write_success_receive_fedi_fee(operation_id, amount) - .await - .map(|(_, status)| status) - .ok() - .map(Into::into); + DepositStateV2::WaitingForConfirmation { btc_deposited, .. } + | DepositStateV2::Claimed { btc_deposited, .. } => { + let fees = wallet.get_fee_consensus().peg_in_abs; + let amount = Amount::from_sats(btc_deposited.to_sat()) - fees; + // FIXME: add fedi fees once fedimint await primary module outputs + // let fedi_fee_status = fed + // .write_success_receive_fedi_fee(operation_id, amount) + // .await + // .map(|(_, status)| status) + // .ok() + // .map(Into::into); let onchain_details = Some(RpcBitcoinDetails { address: address.clone(), - expires_at: to_unix_time(expires_at) - .expect("unix time should exist"), }); let transaction = RpcTransaction { - id: operation_id.to_string(), + id: operation_id.fmt_full().to_string(), created_at: unix_now().expect("unix time should exist"), amount: RpcAmount(amount), - fedi_fee_status, + fedi_fee_status: None, direction: RpcTransactionDirection::Receive, notes: "".into(), onchain_state: RpcOnchainState::from_deposit_state(Some( @@ -734,7 +763,7 @@ impl FederationV2 { info!("send_transaction_event: {:?}", transaction); fed.send_transaction_event(transaction); } - DepositState::Failed(reason) => { + DepositStateV2::Failed(reason) => { let _ = fed.write_failed_receive_fedi_fee(operation_id).await; // FIXME: handle this error!("Failed to claim on-chain deposit: {reason}"); @@ -777,7 +806,7 @@ impl FederationV2 { .ok() .map(Into::into); let transaction = RpcTransaction { - id: operation_id.to_string(), + id: operation_id.fmt_full().to_string(), created_at: unix_now().expect("unix time should exist"), amount: RpcAmount(amount), fedi_fee_status, @@ -812,10 +841,10 @@ impl FederationV2 { /// whilst attaching federation-specific fee details to the response pub async fn decode_invoice(&self, invoice: String) -> Result { let invoice: Bolt11Invoice = invoice.trim().parse().context(ErrorCode::InvalidInvoice)?; - let invoice: RpcInvoice = invoice.try_into()?; - let amount = invoice.amount.0; + let rpc_invoice: RpcInvoice = invoice.clone().try_into()?; + let amount = rpc_invoice.amount.0; - // Calculate the different fee components + // Fedi app fee applies regardless of internal/external payment let fedi_fee_ppm = self .fedi_fee_helper .get_fedi_fee_ppm( @@ -826,20 +855,44 @@ impl FederationV2 { .await?; let fedi_fee = (amount.msats * fedi_fee_ppm).div_ceil(MILLION); - let gateway = self - .select_gateway() - .await? - .context("No gateway available")?; - let gateway_fees = gateway.fees; - let network_fee = gateway_fees.base_msat as u64 - + (amount.msats * gateway_fees.proportional_millionths as u64).div_ceil(MILLION); + // Logic inside the if statement below is currently copied from + // fedimint-ln-client to determine when the destination of a lightning invoice + // is within the current federation so that we know to show a 0 gateway fee. + let mut is_internal_payment = false; + if let Ok(markers) = self.client.get_internal_payment_markers() { + is_internal_payment = invoice_has_internal_payment_markers(&invoice, markers); + if !is_internal_payment { + let gateways = self + .client + .get_first_module::() + .list_gateways() + .await + .into_iter() + .map(|g| g.info) + .collect::>(); + is_internal_payment = invoice_routes_back_to_federation(&invoice, gateways); + } + } + + let network_fee = if is_internal_payment { + RpcAmount(Amount::ZERO) + } else { + // External payments have a non-0 gateway fee in addition to Fedi app fee + let gateway = self + .select_gateway() + .await? + .context("No gateway available")?; + let gateway_fees = gateway.fees; + RpcAmount(gateway_fees.to_amount(&amount)) + }; + let fee = Some(RpcFeeDetails { fedi_fee: RpcAmount(Amount::from_msats(fedi_fee)), - network_fee: RpcAmount(Amount::from_msats(network_fee)), + network_fee, federation_fee: RpcAmount(Amount::ZERO), }); - Ok(RpcInvoice { fee, ..invoice }) + Ok(RpcInvoice { fee, ..rpc_invoice }) } /// Pay lightning invoice @@ -893,9 +946,34 @@ impl FederationV2 { is_fedi_fee_remittance: false, }; let ln = self.client.get_first_module::(); - let OutgoingLightningPayment { payment_type, .. } = ln + let OutgoingLightningPayment { payment_type, .. } = match ln .pay_bolt11_invoice(gateway, invoice.to_owned(), extra_meta.clone()) - .await?; + .await + { + Ok(v) => v, + Err(e) => match e.downcast::()? { + PayBolt11InvoiceError::PreviousPaymentAttemptStillInProgress { .. } + // FundedContractAlreadyExists is also same but with less information. + // see https://discord.com/channels/990354215060795454/990354215878688860/1273318556108324904 + | PayBolt11InvoiceError::FundedContractAlreadyExists { .. } => { + bail!(ErrorCode::PayLnInvoiceAlreadyInProgress) + } + PayBolt11InvoiceError::NoLnGatewayAvailable => { + bail!(ErrorCode::NoLnGatewayAvailable) + } + }, + }; + // already paid + if self + .client + .operation_log() + .get_operation(payment_type.operation_id()) + .await + .map_or(false, |o| o.outcome::().is_some()) + { + bail!(ErrorCode::PayLnInvoiceAlreadyPaid); + } + self.write_pending_send_fedi_fee(payment_type.operation_id(), Amount::from_msats(fedi_fee)) .await?; drop(spend_guard); @@ -914,7 +992,7 @@ impl FederationV2 { // case the amount exceeds the max spendable amount. pub async fn preview_pay_address( &self, - address: Address, + address: Address, amount: bitcoin::Amount, ) -> Result { let fedi_fee_ppm = self @@ -952,7 +1030,7 @@ impl FederationV2 { // Pay an onchain address pub async fn pay_address( &self, - address: Address, + address: Address, amount: bitcoin::Amount, ) -> Result { let fedi_fee_ppm = self @@ -1095,13 +1173,25 @@ impl FederationV2 { .unwrap_or(LightningSendMetadata { is_fedi_fee_remittance: false, }); + // HACK: our code accidentally subscribed using wrong function in past. + if pay_meta.is_internal_payment + && operation + .outcome::() + .map_or(false, internal_pay_is_bad_state) + { + anyhow::bail!("not subscribe to failed transaction"); + } self.task_group .clone() .spawn("subscribe_to_ln_pay", move |_| async move { // FIXME: what happens if it fails? if let Err(e) = fed .subscribe_to_ln_pay( - PayType::Lightning(operation_id), + if pay_meta.is_internal_payment { + PayType::Internal(operation_id) + } else { + PayType::Lightning(operation_id) + }, extra_meta, pay_meta.invoice, ) @@ -1159,14 +1249,10 @@ impl FederationV2 { let meta = operation.meta::(); match meta { WalletOperationMeta { - variant: - WalletOperationMetaVariant::Deposit { - address, - expires_at, - }, + variant: WalletOperationMetaVariant::Deposit { address, .. }, .. } => { - self.subscribe_deposit(operation_id, address.to_string(), expires_at) + self.subscribe_deposit(operation_id, address.assume_checked().to_string()) .await?; } _ => { @@ -1348,9 +1434,8 @@ impl FederationV2 { pub async fn wait_for_recovery(&self) -> Result<()> { info!("waiting for recovering"); let mut recovery_complete = pin!(self.client.wait_for_all_recoveries().fuse()); - let mint_instance_id = self - .client - .get_config() + let client_config = self.client.config().await; + let mint_instance_id = client_config .modules .iter() .find(|(_, config)| config.is_kind(&MintClientModule::kind())) @@ -1538,7 +1623,7 @@ impl FederationV2 { .await .map(Into::into); self.send_transaction_event(RpcTransaction { - id: operation_id.to_string(), + id: operation_id.fmt_full().to_string(), created_at: unix_now().expect("unix time should exist"), direction: RpcTransactionDirection::Receive, notes: "".into(), @@ -1580,49 +1665,80 @@ impl FederationV2 { ))); } + // If generating EXACT amount works, use those notes. Otherwise, generate using + // AT LEAST strategy, marking it as internal TX (so we can filter it out). + // Immediately cancel, which will reissue the notes attempting to fill in lower + // denominations. And then generate using AT LEAST strategy again, which + // will now have a high chance to producing the exact amount. let cancel_time = fedimint_core::time::now() + ONE_WEEK; - let (operation_id, notes) = self + let (spend_guard, operation_id, notes) = match self .client .get_first_module::() - .spend_notes(amount, ONE_WEEK, false, ()) - .await?; - self.write_pending_send_fedi_fee(operation_id, fedi_fee) - .await?; - drop(spend_guard); - self.subscribe_to_operation(operation_id).await?; - let notes = if amount != notes.total_amount() { - // try to make change (exempt this from fedi app fee) - timeout(REISSUE_ECASH_TIMEOUT, async { - let notes_amount = notes.total_amount(); - let operation_id = self + .spend_notes_with_selector( + &SelectNotesWithExactAmount, + amount, + ONE_WEEK, + false, + EcashSendMetadata { internal: false }, + ) + .await + { + Ok((operation_id, notes)) => (spend_guard, operation_id, notes), + Err(_) => { + let (_, notes) = self .client .get_first_module::() - .reissue_external_notes(notes, EcashReceiveMetadata { internal: true }) + .spend_notes( + amount, + ONE_WEEK, + false, + EcashSendMetadata { internal: true }, + ) .await?; - self.subscribe_to_ecash_reissue(operation_id, notes_amount) - .await - }) - .await - .context("Failed to select notes with correct amount")??; - let spend_guard = self.spend_guard.lock().await; - let virtual_balance = self.get_balance().await; - if amount > virtual_balance { - self.write_failed_send_fedi_fee(operation_id).await?; - bail!(ErrorCode::InsufficientBalance(RpcAmount( - get_max_spendable_amount(virtual_balance, fedi_fee_ppm, None, None) - ))); + drop(spend_guard); + + // try to make change + timeout(REISSUE_ECASH_TIMEOUT, async { + let notes_amount = notes.total_amount(); + let operation_id = self + .client + .get_first_module::() + .reissue_external_notes(notes, EcashReceiveMetadata { internal: true }) + .await?; + self.subscribe_to_ecash_reissue(operation_id, notes_amount) + .await + }) + .await + .context("Failed to select notes with correct amount")??; + + let spend_guard = self.spend_guard.lock().await; + let virtual_balance = self.get_balance().await; + if amount + fedi_fee > virtual_balance { + bail!(ErrorCode::InsufficientBalance(RpcAmount( + get_max_spendable_amount(virtual_balance, fedi_fee_ppm, None, None) + ))); + } + let (operation_id, notes) = self + .client + .get_first_module::() + .spend_notes( + amount, + ONE_WEEK, + false, + EcashSendMetadata { internal: false }, + ) + .await?; + (spend_guard, operation_id, notes) } - let (operation_id, new_notes) = self - .client - .get_first_module::() - .spend_notes(amount, ONE_WEEK, false, ()) - .await?; - drop(spend_guard); - self.subscribe_to_operation(operation_id).await?; - new_notes - } else { - notes }; + + self.write_pending_send_fedi_fee(operation_id, fedi_fee) + .await?; + // spend_guard must be dropped after writing fee since virtual balance only + // updates once fee is written + drop(spend_guard); + self.subscribe_to_operation(operation_id).await?; + Ok(RpcGenerateEcashResponse { ecash: notes.to_string(), cancel_at: to_unix_time(cancel_time)?, @@ -1750,7 +1866,7 @@ impl FederationV2 { } pub async fn decoded_config(&self) -> Result { - let client_config = self.client.get_config().clone(); + let client_config = self.client.config().await.clone(); Ok(client_config.redecode_raw(self.client.decoders())?) } @@ -1851,10 +1967,11 @@ impl FederationV2 { pub async fn download_verification_doc( &self, recovery_id: &RecoveryId, + peer_id: PeerId, ) -> Result>> { tracing::info!("downloading verification doc {}", recovery_id); // FIXME: maybe shouldn't download from only one peer? - let verification_client = self.social_verification(PeerId::from(0)).await?; + let verification_client = self.social_verification(peer_id).await?; let verification_doc = verification_client .download_verification_doc(*recovery_id) .await?; @@ -1924,41 +2041,26 @@ impl FederationV2 { None } - pub async fn get_deposit_outcome( - &self, - operation_id: OperationId, - log_entry: OperationLogEntry, - ) -> Option { - let outcome = log_entry.outcome::(); - - // Return client's cached outcome if we find it - if let Some(outcome) = outcome { - return Some(outcome); - } + pub async fn get_deposit_outcome(&self, operation_id: OperationId) -> Option { // Return our cached outcome if we find it - if let Some(outcome) = self.get_operation_state(&operation_id).await { + if let Some(outcome) = self + .get_operation_state::(&operation_id) + .await + { return Some(outcome); } - // If no cached outcomes, consume the stream to get the outcome and populate - // client's cache in future This is only useful for outgoing lightning - // payments which fail due to timeout and nothing is subscribed to them - let mut updates = match self + match self .client .get_first_module::() - .subscribe_deposit_updates(operation_id) + .subscribe_deposit(operation_id) .await { - Err(_) => return None, - Ok(stream) => stream.into_stream(), - }; - - let mut last_state = None; - while let Some(update) = updates.next().await { - tracing::info!("update {:?}", update); - last_state = Some(update); + Err(_) => None, + Ok(UpdateStreamOrOutcome::Outcome(outcome)) => Some(outcome), + // don't block + Ok(UpdateStreamOrOutcome::UpdateStream(_)) => None, } - last_state } pub async fn get_client_operation_outcome( @@ -2008,6 +2110,10 @@ impl FederationV2 { .get_value(&OperationFediFeeStatusKey(op.0.operation_id)) .await .map(Into::into); + let fedi_fee_msats = match fedi_fee_status { + Some(RpcOperationFediFeeStatus::PendingSend { fedi_fee } | RpcOperationFediFeeStatus::Success { fedi_fee }) => fedi_fee.0.msats, + _ => 0, + }; match op.1.operation_module_kind() { LIGHTNING_OPERATION_TYPE => { @@ -2023,11 +2129,11 @@ impl FederationV2 { None } else { Some(RpcTransaction { - id: op.0.operation_id.to_string(), + id: op.0.operation_id.fmt_full().to_string(), created_at: to_unix_time(op.0.creation_time) .expect("unix time should exist"), amount: RpcAmount(Amount { - msats: invoice.amount_milli_satoshis().unwrap(), + msats: invoice.amount_milli_satoshis().unwrap() + fedi_fee_msats + fee.msats, }), fedi_fee_status, direction: RpcTransactionDirection::Send, @@ -2052,7 +2158,7 @@ impl FederationV2 { op.1.outcome::(), ); Some(RpcTransaction { - id: op.0.operation_id.to_string(), + id: op.0.operation_id.fmt_full().to_string(), created_at: to_unix_time(op.0.creation_time) .expect("unix time should exist"), amount: RpcAmount(Amount { @@ -2087,10 +2193,10 @@ impl FederationV2 { Err(_) => None, }; Some(RpcTransaction { - id: op.0.operation_id.to_string(), + id: op.0.operation_id.fmt_full().to_string(), created_at: to_unix_time(op.0.creation_time) .expect("unix time should exist"), - amount: RpcAmount(amount), + amount: RpcAmount(amount + Amount::from_msats(fedi_fee_msats)), fedi_fee_status, direction: RpcTransactionDirection::Send, notes, @@ -2107,7 +2213,7 @@ impl FederationV2 { .get_client_operation_outcome(op.0.operation_id, op.1) .await; Some(RpcTransaction { - id: op.0.operation_id.to_string(), + id: op.0.operation_id.fmt_full().to_string(), created_at: to_unix_time(op.0.creation_time) .expect("unix time should exist"), amount: match outcome { @@ -2147,7 +2253,7 @@ impl FederationV2 { .map_or(false, |x| x.internal); if !internal { Some(RpcTransaction { - id: op.0.operation_id.to_string(), + id: op.0.operation_id.fmt_full().to_string(), created_at: to_unix_time(op.0.creation_time) .expect("unix time should exist"), direction: RpcTransactionDirection::Receive, @@ -2171,25 +2277,36 @@ impl FederationV2 { } MintOperationMetaVariant::SpendOOB { requested_amount, .. - } => Some(RpcTransaction { - id: op.0.operation_id.to_string(), - created_at: to_unix_time(op.0.creation_time) - .expect("unix time should exist"), - direction: RpcTransactionDirection::Send, - notes, - onchain_state: None, - bitcoin: None, - ln_state: None, - amount: RpcAmount(requested_amount), - fedi_fee_status, - lightning: None, - oob_state: self - .get_client_operation_outcome(op.0.operation_id, op.1) - .await - .map(RpcOOBState::from_spend_v2), - onchain_withdrawal_details: None, - stability_pool_state: None, - }), + } => { + let internal = serde_json::from_value::( + mint_meta.extra_meta, + ) + .map_or(false, |x| x.internal); + + if !internal { + Some(RpcTransaction { + id: op.0.operation_id.fmt_full().to_string(), + created_at: to_unix_time(op.0.creation_time) + .expect("unix time should exist"), + direction: RpcTransactionDirection::Send, + notes, + onchain_state: None, + bitcoin: None, + ln_state: None, + amount: RpcAmount(requested_amount + Amount::from_msats(fedi_fee_msats)), + fedi_fee_status, + lightning: None, + oob_state: self + .get_client_operation_outcome(op.0.operation_id, op.1) + .await + .map(RpcOOBState::from_spend_v2), + onchain_withdrawal_details: None, + stability_pool_state: None, + }) + } else { + None + } + }, } } WALLET_OPERATION_TYPE => { @@ -2197,35 +2314,31 @@ impl FederationV2 { match wallet_meta.variant { WalletOperationMetaVariant::Deposit { address, - expires_at, + .. } => { - let outcome = - self.get_deposit_outcome(op.0.operation_id, op.1).await; + let outcome = self.get_deposit_outcome(op.0.operation_id).await; let onchain_state = RpcOnchainState::from_deposit_state(outcome.clone()); Some(RpcTransaction { - id: op.0.operation_id.to_string(), + id: op.0.operation_id.fmt_full().to_string(), created_at: to_unix_time(op.0.creation_time) .expect("unix time should exist"), direction: RpcTransactionDirection::Receive, notes, onchain_state: onchain_state.clone(), bitcoin: Some(RpcBitcoinDetails { - address: address.to_string(), - expires_at: to_unix_time(expires_at) - .expect("unix time should exist"), + address: address.assume_checked().to_string(), }), ln_state: None, amount: match outcome { Some( - DepositState::WaitingForConfirmation(data) - | DepositState::Confirmed(data) - | DepositState::Claimed(data), - ) => RpcAmount(Amount::from_sats( - data.btc_transaction.output[data.out_idx as usize] - .value, - )), + DepositStateV2::WaitingForConfirmation { btc_deposited, ..} + | DepositStateV2::Claimed { btc_deposited, ..}, + ) => { + let fees = self.client.get_first_module::().get_fee_consensus().peg_in_abs; + RpcAmount(Amount::from_sats(btc_deposited.to_sat()) - fees) + }, _ => RpcAmount(Amount::ZERO), }, fedi_fee_status, @@ -2261,7 +2374,7 @@ impl FederationV2 { }; Some(RpcTransaction { - id: op.0.operation_id.to_string(), + id: op.0.operation_id.fmt_full().to_string(), created_at: to_unix_time(op.0.creation_time) .expect("unix time should exist"), amount: rpc_amount, @@ -2274,7 +2387,7 @@ impl FederationV2 { lightning: None, oob_state: None, onchain_withdrawal_details: Some(WithdrawalDetails { - address: address.to_string(), + address: address.assume_checked().to_string(), txid: txid_str, fee: RpcAmount(Amount::from_sats(fee.amount().to_sat())), fee_rate: fee.fee_rate.sats_per_kvb, @@ -2625,11 +2738,14 @@ impl FederationV2 { match res { Ok(_) => info!( "Successfully wrote pending send fedi fee for op ID {} with amount {}", - operation_id, fedi_fee + operation_id.fmt_short(), + fedi_fee ), Err(ref e) => warn!( "Error writing pending send fedi fee for op ID {} with amount {}: {}", - operation_id, fedi_fee, e + operation_id.fmt_short(), + fedi_fee, + e ), } @@ -2721,7 +2837,7 @@ impl FederationV2 { Ok((true, _)) => { info!( "Successfully wrote success send fedi fee for op ID {}", - operation_id + operation_id.fmt_short() ); if let Some(service) = self.fedi_fee_remittance_service.get() { service @@ -2735,11 +2851,12 @@ impl FederationV2 { } Ok((false, _)) => info!( "Already recorded success send fedi fee for op ID {}, nothing overwritten", - operation_id + operation_id.fmt_short() ), Err(ref e) => warn!( "Error writing success send fedi fee for op ID {}: {}", - operation_id, e + operation_id.fmt_short(), + e ), } @@ -2817,15 +2934,16 @@ impl FederationV2 { match res { Ok((true, _)) => info!( "Successfully wrote failed send fedi fee for op ID {}", - operation_id + operation_id.fmt_short() ), Ok((false, _)) => info!( "Already recorded failed send fedi fee for op ID {}, nothing overwritten", - operation_id + operation_id.fmt_short() ), Err(ref e) => warn!( "Error writing failed send fedi fee for op ID {}: {}", - operation_id, e + operation_id.fmt_short(), + e ), } @@ -2867,11 +2985,14 @@ impl FederationV2 { match res { Ok(_) => info!( "Successfully wrote pending receive fedi fee for op ID {} with ppm {}", - operation_id, fedi_fee_ppm + operation_id.fmt_short(), + fedi_fee_ppm ), Err(ref e) => warn!( "Error writing pending receive fedi fee for op ID {} with ppm {}: {}", - operation_id, fedi_fee_ppm, e + operation_id.fmt_short(), + fedi_fee_ppm, + e ), } @@ -2952,7 +3073,7 @@ impl FederationV2 { Ok((true, _)) => { info!( "Successfully wrote success receive fedi fee for op ID {}", - operation_id + operation_id.fmt_short() ); if let Some(service) = self.fedi_fee_remittance_service.get() { service @@ -2966,11 +3087,12 @@ impl FederationV2 { } Ok((false, _)) => info!( "Already recorded success receive fedi fee for op ID {}, nothing overwritten", - operation_id + operation_id.fmt_short() ), Err(ref e) => warn!( "Error writing success receive fedi fee for op ID {}: {}", - operation_id, e + operation_id.fmt_short(), + e ), } @@ -3021,15 +3143,16 @@ impl FederationV2 { match res { Ok((true, _)) => info!( "Successfully wrote failed receive fedi fee for op ID {}", - operation_id + operation_id.fmt_short() ), Ok((false, _)) => info!( "Already recorded failed receive fedi fee for op ID {}, nothing overwritten", - operation_id + operation_id.fmt_short() ), Err(ref e) => warn!( "Error writing failed receive fedi fee for op ID {}: {}", - operation_id, e + operation_id.fmt_short(), + e ), } @@ -3119,3 +3242,54 @@ fn get_max_spendable_amount( let denominator_msats = MILLION + fedi_fee_ppm + gateway_ppm; Amount::from_msats(numerator_msats / denominator_msats) } + +// Function below is currently copied from +// fedimint-ln-client to determine when the destination of a lightning invoice +// is within the current federation so that we know to show a 0 gateway fee. +fn invoice_has_internal_payment_markers( + invoice: &Bolt11Invoice, + markers: (PublicKey, u64), +) -> bool { + // Asserts that the invoice src_node_id and short_channel_id match known + // values used as internal payment markers + invoice + .route_hints() + .first() + .and_then(|rh| rh.0.last()) + .map(|hop| (hop.src_node_id, hop.short_channel_id)) + == Some(markers) +} + +// Function below is currently copied from +// fedimint-ln-client to determine when the destination of a lightning invoice +// is within the current federation so that we know to show a 0 gateway fee. +fn invoice_routes_back_to_federation( + invoice: &Bolt11Invoice, + gateways: Vec, +) -> bool { + gateways.into_iter().any(|gateway| { + invoice + .route_hints() + .first() + .and_then(|rh| rh.0.last()) + .map(|hop| (hop.src_node_id, hop.short_channel_id)) + == Some((gateway.node_pub_key, gateway.mint_channel_id)) + }) +} + +fn internal_pay_is_bad_state(outcome: serde_json::Value) -> bool { + serde_json::from_value::(outcome).is_err() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_pay_state_is_getting_parsed() { + let state = LnPayState::Canceled; + let json = serde_json::to_string(&state).unwrap(); + let value = serde_json::from_str::(&json).unwrap(); + assert!(internal_pay_is_bad_state(value)); + } +} diff --git a/bridge/fedi-ffi/src/fedi_fee.rs b/bridge/fedi-ffi/src/fedi_fee.rs index 9da28d8..bd1d5fe 100644 --- a/bridge/fedi-ffi/src/fedi_fee.rs +++ b/bridge/fedi-ffi/src/fedi_fee.rs @@ -9,13 +9,16 @@ use fedimint_core::db::IDatabaseTransactionOpsCoreTyped; use fedimint_core::task::TaskGroup; use fedimint_core::Amount; use fedimint_ln_client::{LightningClientModule, OutgoingLightningPayment}; +use futures::StreamExt; use lightning_invoice::Bolt11Invoice; use tokio::sync::{Mutex, OwnedMutexGuard}; use tracing::{error, info, instrument, warn}; use crate::api::IFediApi; use crate::constants::MILLION; -use crate::federation_v2::db::OutstandingFediFeesPerTXTypeKey; +use crate::federation_v2::db::{ + OutstandingFediFeesPerTXTypeKey, OutstandingFediFeesPerTXTypeKeyPrefix, +}; use crate::federation_v2::{zero_gateway_fees, FederationV2}; use crate::storage::{AppState, FediFeeSchedule, ModuleFediFeeSchedule}; use crate::types::{LightningSendMetadata, RpcTransactionDirection}; @@ -200,13 +203,42 @@ impl FediFeeHelper { type ModuleTXDirectionLockMap = BTreeMap<(ModuleKind, RpcTransactionDirection), Arc>>; -#[derive(Clone, Default)] +#[derive(Clone)] pub struct FediFeeRemittanceService { // held while remit the fees locks_map: Arc>, } impl FediFeeRemittanceService { + /// On initialization, spawn a background task that attempts all remittances + /// one by one. + pub fn init(fed: &FederationV2) -> Self { + let service = Self { + locks_map: Default::default(), + }; + + let fed2 = fed.clone(); + let service2 = service.clone(); + fed.task_group + .spawn_cancellable("init_fee_remittance_service", async move { + let tx_types = fed2 + .dbtx() + .await + .find_by_prefix(&OutstandingFediFeesPerTXTypeKeyPrefix) + .await + .map(|(key, _)| (key.0, key.1)) + .collect::>() + .await; + + for (module, tx_direction) in tx_types { + service2 + .remit_fedi_fee_if_threshold_met(&fed2, module, tx_direction) + .await; + } + }); + + service + } /// Checks whether the accrued outstanding fedi fees has surpassed the /// remittance threshold. If yes, queries the fee helper to obtain a /// lightning invoice to remit the fees. If the fees HAS surpassed diff --git a/bridge/fedi-ffi/src/logging.rs b/bridge/fedi-ffi/src/logging.rs index ea70729..2458f8c 100644 --- a/bridge/fedi-ffi/src/logging.rs +++ b/bridge/fedi-ffi/src/logging.rs @@ -8,6 +8,7 @@ use std::sync::{Arc, Mutex}; use std::time::SystemTime; use anyhow::Context; +use fedimint_logging::{LOG_CLIENT, LOG_CLIENT_MODULE_WALLET, LOG_CLIENT_REACTOR}; use rolling_file::{BasicRollingFileAppender, RollingConditionBasic}; use tracing::metadata::LevelFilter; use tracing_appender::non_blocking::NonBlocking; @@ -70,7 +71,7 @@ pub fn init_logging( ); let reg = reg.with(log_file_layer.with_filter(EnvFilter::new( - "info,fedimint_client=debug,fediffi=trace,client::reactor=trace", + format!("info,{LOG_CLIENT}=debug,fediffi=trace,{LOG_CLIENT_REACTOR}=trace,{LOG_CLIENT_MODULE_WALLET}=trace"), ))); let res = if cfg!(target_os = "android") && option_env!("FEDI_DEV_LOGS").is_some() { diff --git a/bridge/fedi-ffi/src/matrix.rs b/bridge/fedi-ffi/src/matrix.rs index 5281002..c573a22 100644 --- a/bridge/fedi-ffi/src/matrix.rs +++ b/bridge/fedi-ffi/src/matrix.rs @@ -334,7 +334,7 @@ impl Matrix { static OBSERVABLE_ID: AtomicU64 = AtomicU64::new(0); let id = OBSERVABLE_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed); let observable = Observable::new(id, initial); - let tg = self.task_group.make_subgroup().await; + let tg = self.task_group.make_subgroup(); { let mut observables = self.observables.lock().await; observables.insert(id, tg.clone()); diff --git a/bridge/fedi-ffi/src/rpc.rs b/bridge/fedi-ffi/src/rpc.rs index 3147604..93a398b 100644 --- a/bridge/fedi-ffi/src/rpc.rs +++ b/bridge/fedi-ffi/src/rpc.rs @@ -7,7 +7,7 @@ use std::time::{Duration, UNIX_EPOCH}; use anyhow::Context; use bitcoin::secp256k1::Message; -use bitcoin::{Address, Amount}; +use bitcoin::Amount; use fedimint_client::db::ChronologicalOperationLogKey; use fedimint_core::core::OperationId; use fedimint_core::timing::TimeReporter; @@ -155,6 +155,7 @@ macro_rules! federation_rpc_method { pub type Return = $ret; pub async fn handle(bridge: Arc, $name::Args { federation_id, $( $arg_name ),* }: $name::Args) -> anyhow::Result<$ret> { let $federation = bridge.get_federation(&federation_id.0).await?; + tracing::Span::current().record("federation_id", &federation_id.0); super::$name($federation, $($arg_name),*).await } } @@ -187,6 +188,7 @@ macro_rules! federation_recovering_rpc_method { pub type Return = $ret; pub async fn handle(bridge: Arc, $name::Args { federation_id, $( $arg_name ),* }: $name::Args) -> anyhow::Result<$ret> { let $federation = bridge.get_federation_maybe_recovering(&federation_id.0).await?; + tracing::Span::current().record("federation_id", &federation_id.0); super::$name($federation, $($arg_name),*).await } } @@ -199,9 +201,15 @@ async fn guardianStatus(federation: Arc) -> anyhow::Result, invite_code: String) -> anyhow::Result { +async fn joinFederation( + bridge: Arc, + invite_code: String, + recover_from_scratch: bool, +) -> anyhow::Result { info!("joining federation {:?}", invite_code); - bridge.join_federation(invite_code).await + bridge + .join_federation(invite_code, recover_from_scratch) + .await } #[macro_rules_derive(rpc_method!)] @@ -293,7 +301,7 @@ async fn previewPayAddress( // TODO: parse this as bitcoin::Amount sats: u64, ) -> anyhow::Result { - let address: Address = address.trim().parse().context("Invalid Bitcoin Address")?; + let address = address.trim().parse().context("Invalid Bitcoin Address")?; let amount: Amount = Amount::from_sat(sats); federation.preview_pay_address(address, amount).await } @@ -305,7 +313,7 @@ async fn payAddress( // TODO: parse this as bitcoin::Amount sats: u64, ) -> anyhow::Result { - let address: Address = address.trim().parse().context("Invalid Bitcoin Address")?; + let address = address.trim().parse().context("Invalid Bitcoin Address")?; let amount: Amount = Amount::from_sat(sats); federation.pay_address(address, amount).await } @@ -438,9 +446,10 @@ async fn socialRecoveryDownloadVerificationDoc( bridge: Arc, federation_id: RpcFederationId, recovery_id: RpcRecoveryId, + peer_id: RpcPeerId, ) -> anyhow::Result> { bridge - .download_verification_doc(federation_id, recovery_id) + .download_verification_doc(federation_id, recovery_id, peer_id) .await } @@ -531,9 +540,11 @@ async fn stabilityPoolCycleStartPrice(federation: Arc) -> anyhow:: #[macro_rules_derive(federation_rpc_method!)] async fn stabilityPoolAverageFeeRate( federation: Arc, - num_cycles: u64, + num_cycles: u32, ) -> anyhow::Result { - federation.stability_pool_average_fee_rate(num_cycles).await + federation + .stability_pool_average_fee_rate(num_cycles.into()) + .await } #[macro_rules_derive(federation_rpc_method!)] @@ -1417,7 +1428,8 @@ rpc_methods!(RpcMethods { request_id = %{ static REQUEST_ID: AtomicU64 = AtomicU64::new(0); REQUEST_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst) - } + }, + federation_id, ) )] pub async fn fedimint_rpc_async(bridge: Arc, method: String, payload: String) -> String { @@ -1458,8 +1470,10 @@ mod tests { use fedi_core::envs::FEDI_SOCIAL_RECOVERY_MODULE_ENABLE_ENV; use fedi_social_client::common::VerificationDocument; use fedimint_core::core::ModuleKind; + use fedimint_core::task::sleep_in_test; use fedimint_core::{apply, async_trait_maybe_send, Amount}; use fedimint_logging::TracingSetup; + use fedimint_wallet_client::WalletClientModule; use tokio::sync::Mutex; use tracing::{error, info}; @@ -1708,7 +1722,7 @@ mod tests { pub struct BitcoinCli; impl BitcoinCli { - pub async fn cmd(self) -> devimint::util::Command { + pub fn cmd(self) -> devimint::util::Command { get_command_for_alias("FM_BTC_CLIENT", "bitcoin-cli") } } @@ -1798,7 +1812,7 @@ mod tests { async fn join_test_fed(bridge: &Arc) -> Result, anyhow::Error> { let invite_code = std::env::var("FM_INVITE_CODE").unwrap(); - let fedimint_federation = joinFederation(bridge.clone(), invite_code).await?; + let fedimint_federation = joinFederation(bridge.clone(), invite_code, false).await?; let federation = bridge .get_federation_maybe_recovering(&fedimint_federation.id.0) .await?; @@ -1808,9 +1822,11 @@ mod tests { async fn join_test_fed_recovery( bridge: &Arc, + recover_from_scratch: bool, ) -> Result, anyhow::Error> { let invite_code = std::env::var("FM_INVITE_CODE").unwrap(); - let fedimint_federation = joinFederation(bridge.clone(), invite_code).await?; + let fedimint_federation = + joinFederation(bridge.clone(), invite_code, recover_from_scratch).await?; let federation = bridge .get_federation_maybe_recovering(&fedimint_federation.id.0) .await?; @@ -1886,9 +1902,11 @@ mod tests { let env_invite_code = std::env::var("FM_INVITE_CODE").unwrap(); // Can't re-join a federation we're already a member of - assert!(joinFederation(bridge.clone(), env_invite_code.clone()) - .await - .is_err()); + assert!( + joinFederation(bridge.clone(), env_invite_code.clone(), false) + .await + .is_err() + ); // listTransactions works let federations = listFederations(bridge.clone()).await?; @@ -1900,7 +1918,7 @@ mod tests { assert_eq!(listFederations(bridge.clone()).await?.len(), 0); // rejoin without any rocksdb locking problems - joinFederation(bridge.clone(), env_invite_code).await?; + joinFederation(bridge.clone(), env_invite_code, false).await?; assert_eq!(listFederations(bridge).await?.len(), 1); Ok(()) @@ -2128,6 +2146,7 @@ mod tests { } #[tokio::test(flavor = "multi_thread")] + // on chain is marked experimental for 0.4 async fn test_on_chain() -> anyhow::Result<()> { // Vec of tuple of (send_ppm, receive_ppm) let fee_ppm_values = vec![(0, 0), (10, 5), (100, 50)]; @@ -2154,6 +2173,12 @@ mod tests { let address = generateAddress(federation.clone()).await?; bitcoin_cli_send_to_address(&address, "0.1").await?; + assert!(matches!( + listTransactions(federation.clone(), None, None).await?[0].onchain_state, + Some(crate::types::RpcOnchainState::DepositState( + RpcOnchainDepositState::WaitingForTransaction + )) + ),); // check for event of type transaction that has onchain_state of // DepositState::Claimed 'check: loop { @@ -2184,13 +2209,38 @@ mod tests { ) .await; } + assert!(matches!( + listTransactions(federation.clone(), None, None).await?[0].onchain_state, + Some(crate::types::RpcOnchainState::DepositState( + RpcOnchainDepositState::Claimed(_) + )) + ),); let btc_amount = Amount::from_sats(10_000_000); - let receive_fedi_fee = - Amount::from_msats((btc_amount.msats * fedi_fees_receive_ppm).div_ceil(MILLION)); + let pegin_fees = federation + .client + .get_first_module::() + .get_fee_consensus() + .peg_in_abs; + let receive_fedi_fee = Amount::ZERO; + // FIXME: implement fedi fees + // let receive_fedi_fee = Amount::from_msats( + // ((btc_amount.msats - pegin_fees.msats) * + // fedi_fees_receive_ppm).div_ceil(MILLION), ); + // wait for balance to trickle in atmost 10s + for _ in 0..100 { + if btc_amount == federation.get_balance().await + receive_fedi_fee + pegin_fees { + break; + } + sleep_in_test( + "waiting for balance to trickle in", + Duration::from_millis(100), + ) + .await; + } assert_eq!( - btc_amount - receive_fedi_fee, - federation.get_balance().await, + btc_amount, + federation.get_balance().await + receive_fedi_fee + pegin_fees, ); Ok(()) @@ -2225,6 +2275,15 @@ mod tests { #[tokio::test(flavor = "multi_thread")] async fn test_backup_and_recovery() -> anyhow::Result<()> { + test_backup_and_recovery_inner(false).await + } + + #[tokio::test(flavor = "multi_thread")] + async fn test_backup_and_recovery_from_scratch() -> anyhow::Result<()> { + test_backup_and_recovery_inner(true).await + } + + async fn test_backup_and_recovery_inner(from_scratch: bool) -> anyhow::Result<()> { let (backup_bridge, federation) = setup().await?; // receive ecash @@ -2269,7 +2328,7 @@ mod tests { transferExistingDeviceRegistration(recovery_bridge.clone(), 0).await?; // Rejoin federation and assert that balances are correct - let recovery_federation = join_test_fed_recovery(&recovery_bridge).await?; + let recovery_federation = join_test_fed_recovery(&recovery_bridge, from_scratch).await?; assert!(recovery_federation.recovering()); let id = recovery_federation.rpc_federation_id(); drop(recovery_federation); @@ -2287,14 +2346,17 @@ mod tests { } let recovery_federation = recovery_bridge.get_federation(&id.0).await?; // Currently, accrued fedi fee is merged back into balance upon recovery + // wait atmost 10s + for _ in 0..100 { + if ecash_balance_before + expected_fedi_fee == recovery_federation.get_balance().await { + break; + } + fedimint_core::task::sleep(Duration::from_millis(100)).await; + } assert_eq!( ecash_balance_before + expected_fedi_fee, recovery_federation.get_balance().await ); - assert_eq!( - Some(username), - recovery_federation.get_xmpp_username().await - ); let account_info = stabilityPoolAccountInfo(recovery_federation.clone(), true).await?; assert_eq!(account_info.idle_balance.0, Amount::ZERO); @@ -2380,6 +2442,7 @@ mod tests { guardian_bridge.clone(), federation_id.clone(), recovery_id, + RpcPeerId(fedimint_core::PeerId::from(1)), ) .await? .unwrap(); @@ -2622,7 +2685,8 @@ mod tests { )); // join - let fedimint_federation = joinFederation(bridge.clone(), invite_code.clone()).await?; + let fedimint_federation = + joinFederation(bridge.clone(), invite_code.clone(), false).await?; let federation = bridge.get_federation(&fedimint_federation.id.0).await?; use_lnd_gateway(&federation).await?; @@ -2701,7 +2765,9 @@ mod tests { )); // Rejoining federation should fail since device index wasn't assigned - assert!(join_test_fed_recovery(&recovery_bridge).await.is_err()); + assert!(join_test_fed_recovery(&recovery_bridge, false) + .await + .is_err()); Ok(()) } @@ -2837,7 +2903,7 @@ mod tests { transferExistingDeviceRegistration(recovery_bridge.clone(), 0).await?; // Rejoin federation and assert that balances are correct - let recovery_federation = join_test_fed_recovery(&recovery_bridge).await?; + let recovery_federation = join_test_fed_recovery(&recovery_bridge, false).await?; assert!(recovery_federation.recovering()); let id = recovery_federation.rpc_federation_id(); drop(recovery_federation); @@ -2944,7 +3010,7 @@ mod tests { // Rejoin federation and assert that balances don't carry over (and there is no // backup) - let recovery_federation = join_test_fed_recovery(&recovery_bridge).await?; + let recovery_federation = join_test_fed_recovery(&recovery_bridge, false).await?; assert!(!recovery_federation.recovering()); assert_eq!(Amount::ZERO, recovery_federation.get_balance().await); assert_eq!(None, recovery_federation.get_xmpp_username().await); diff --git a/bridge/fedi-ffi/src/types.rs b/bridge/fedi-ffi/src/types.rs index a192635..d97e09c 100644 --- a/bridge/fedi-ffi/src/types.rs +++ b/bridge/fedi-ffi/src/types.rs @@ -9,7 +9,7 @@ use fedimint_core::encoding::{Decodable, Encodable}; use fedimint_core::Amount; use fedimint_ln_client::pay::GatewayPayError; use fedimint_ln_client::{LnPayState, LnReceiveState}; -use fedimint_wallet_client::{BitcoinTransactionData, DepositState, WithdrawState}; +use fedimint_wallet_client::{DepositStateV2, WithdrawState}; use serde::{Deserialize, Serialize}; use stability_pool_client::ClientAccountInfo; use ts_rs::TS; @@ -165,8 +165,8 @@ pub async fn federation_v2_to_rpc_federation(federation: &FederationV2) -> RpcFe let id = RpcFederationId(federation.federation_id().to_string()); let name = federation.federation_name(); let network = federation.get_network(); - let client_config = federation.client.get_config(); - let meta = federation.client.get_config().global.meta.clone(); + let client_config = federation.client.config().await; + let meta = federation.get_cached_meta().await; let nodes = client_config .global .api_endpoints @@ -174,7 +174,7 @@ pub async fn federation_v2_to_rpc_federation(federation: &FederationV2) -> RpcFe .iter() .map(|(peer_id, peer_url)| (RpcPeerId(*peer_id), peer_url.clone())) .collect(); - let client_config_json = federation.client.get_config_json(); + let client_config_json = federation.client.get_config_json().await; let (invite_code, fedi_fee_schedule, balance) = futures::join!( federation.get_invite_code(), federation.fedi_fee_schedule(), @@ -409,21 +409,18 @@ pub enum RpcOnchainState { } impl RpcOnchainState { - pub fn from_deposit_state(opt: Option) -> Option { + pub fn from_deposit_state(opt: Option) -> Option { let state = match opt? { - DepositState::WaitingForTransaction => RpcOnchainDepositState::WaitingForTransaction, - DepositState::WaitingForConfirmation(data) => { + DepositStateV2::WaitingForTransaction => RpcOnchainDepositState::WaitingForTransaction, + DepositStateV2::WaitingForConfirmation { btc_out_point, .. } => { RpcOnchainDepositState::WaitingForConfirmation( - RpcOnchainDepositTransactionData::new(&data), + RpcOnchainDepositTransactionData::new(&btc_out_point), ) } - DepositState::Confirmed(data) => { - RpcOnchainDepositState::Confirmed(RpcOnchainDepositTransactionData::new(&data)) - } - DepositState::Claimed(data) => { - RpcOnchainDepositState::Claimed(RpcOnchainDepositTransactionData::new(&data)) - } - DepositState::Failed(_) => RpcOnchainDepositState::Failed, + DepositStateV2::Claimed { btc_out_point, .. } => RpcOnchainDepositState::Claimed( + RpcOnchainDepositTransactionData::new(&btc_out_point), + ), + DepositStateV2::Failed(_) => RpcOnchainDepositState::Failed, }; Some(Self::DepositState(state)) } @@ -450,7 +447,6 @@ impl RpcOnchainState { pub enum RpcOnchainDepositState { WaitingForTransaction, WaitingForConfirmation(RpcOnchainDepositTransactionData), - Confirmed(RpcOnchainDepositTransactionData), Claimed(RpcOnchainDepositTransactionData), Failed, } @@ -463,9 +459,9 @@ pub struct RpcOnchainDepositTransactionData { } impl RpcOnchainDepositTransactionData { - pub fn new(data: &BitcoinTransactionData) -> Self { + pub fn new(outpoint: &bitcoin::OutPoint) -> Self { Self { - txid: data.btc_transaction.txid().to_string(), + txid: outpoint.txid.to_string(), } } } @@ -485,8 +481,6 @@ pub enum RpcOnchainWithdrawState { #[ts(export, export_to = "target/bindings/")] pub struct RpcBitcoinDetails { pub address: String, - #[ts(type = "number")] - pub expires_at: u64, } #[derive(Debug, Serialize, Deserialize, TS)] @@ -521,14 +515,12 @@ impl RpcLnState { opt.map(|state| match state { LnPayState::Created => RpcLnState::PayState(RpcLnPayState::Created), LnPayState::Canceled => RpcLnState::PayState(RpcLnPayState::Canceled), - LnPayState::Funded => RpcLnState::PayState(RpcLnPayState::Funded), - LnPayState::WaitingForRefund { - block_height, - gateway_error, - } => RpcLnState::PayState(RpcLnPayState::WaitingForRefund { - block_height, - gateway_error, - }), + LnPayState::Funded { block_height } => { + RpcLnState::PayState(RpcLnPayState::Funded { block_height }) + } + LnPayState::WaitingForRefund { error_reason } => { + RpcLnState::PayState(RpcLnPayState::WaitingForRefund { error_reason }) + } LnPayState::AwaitingChange => RpcLnState::PayState(RpcLnPayState::AwaitingChange), LnPayState::Success { preimage } => { RpcLnState::PayState(RpcLnPayState::Success { preimage }) @@ -548,11 +540,11 @@ impl RpcLnState { pub enum RpcLnPayState { Created, Canceled, - Funded, - WaitingForRefund { + Funded { block_height: u32, - #[ts(type = "string")] - gateway_error: GatewayPayError, + }, + WaitingForRefund { + error_reason: String, }, AwaitingChange, Success { @@ -657,7 +649,7 @@ pub struct RpcLightningDetails { } // FIXME: should probaby type these as bytes -#[derive(Debug, Deserialize, Serialize, TS)] +#[derive(Deserialize, Serialize, TS)] #[serde(rename_all = "camelCase")] #[ts(export, export_to = "target/bindings/")] pub struct RpcXmppCredentials { @@ -666,11 +658,25 @@ pub struct RpcXmppCredentials { pub username: Option, } +// Implement Debug manually to ignore sensitive fields +impl std::fmt::Debug for RpcXmppCredentials { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("RpcXmppCredentials") + .field("username", &self.username) + .finish() + } +} + #[derive(Debug, Deserialize, Serialize)] pub struct EcashReceiveMetadata { pub internal: bool, } +#[derive(Debug, Deserialize, Serialize)] +pub struct EcashSendMetadata { + pub internal: bool, +} + #[derive(Debug, Clone, Deserialize, Serialize)] pub struct LightningSendMetadata { pub is_fedi_fee_remittance: bool, diff --git a/bridge/fedi-wasm/src/db.rs b/bridge/fedi-wasm/src/db.rs index 67fec8c..77b0771 100644 --- a/bridge/fedi-wasm/src/db.rs +++ b/bridge/fedi-wasm/src/db.rs @@ -118,6 +118,10 @@ impl IRawDatabase for MemAndIndexedDb { .expect("MemTransaction never fails"); memtx } + + fn checkpoint(&self, _: &std::path::Path) -> Result<(), anyhow::Error> { + unimplemented!() + } } #[apply(async_trait_maybe_send!)] diff --git a/devi/Cargo.toml b/devi/Cargo.toml index 092a5e8..68f29b6 100644 --- a/devi/Cargo.toml +++ b/devi/Cargo.toml @@ -7,7 +7,4 @@ edition = "2021" anyhow = { workspace = true } clap = { workspace = true } devimint = { workspace = true } -fedi-core = { workspace = true } -futures = { workspace = true } tokio = { workspace = true, features = ["full"] } -tracing = { workspace = true } diff --git a/devi/src/main.rs b/devi/src/main.rs index 635e794..fed67dd 100644 --- a/devi/src/main.rs +++ b/devi/src/main.rs @@ -1,13 +1,5 @@ -use std::ops::ControlFlow; -use std::path::PathBuf; -use std::time::{Duration, Instant}; - -use anyhow::Context; use clap::{Parser, Subcommand}; -use devimint::cli::{setup, CommonArgs}; -use devimint::tests::{latency_tests, LatencyTest}; -use devimint::util::poll_with_timeout; -use devimint::{cmd, dev_fed, DevFed}; +use devimint::cli::CommonArgs; #[derive(Parser)] struct Args { @@ -19,63 +11,10 @@ struct Args { #[derive(Subcommand)] enum Cmd { - TestUpgrade { - old_fedimintd: PathBuf, - new_fedimintd: PathBuf, - }, - TestUpgradeShutdownTogether { - old_fedimintd: PathBuf, - new_fedimintd: PathBuf, - }, #[clap(flatten)] Devimint(devimint::cli::Cmd), } -use fedi_core::envs::{ - FEDI_SOCIAL_RECOVERY_MODULE_ENABLE_ENV, FEDI_STABILITY_POOL_MODULE_ENABLE_ENV, - FEDI_STABILITY_POOL_MODULE_TEST_PARAMS_ENV, -}; -use tracing::info; -async fn wait_session(client: &devimint::federation::Client) -> anyhow::Result<()> { - info!("Waiting for a new session"); - let session_count = cmd!(client, "dev", "api", "session_count") - .out_json() - .await?["value"] - .as_u64() - .context("session count must be integer")? - .to_owned(); - let start = Instant::now(); - poll_with_timeout( - "Waiting for a new session", - Duration::from_secs(180), - || async { - info!("Awaiting session outcome {session_count}"); - match cmd!(client, "dev", "api", "await_session_outcome", session_count) - .run() - .await - { - Err(e) => Err(ControlFlow::Continue(e)), - Ok(_) => Ok(()), - } - }, - ) - .await?; - let session_found_in = start.elapsed(); - info!("session found in {session_found_in:?}"); - Ok(()) -} - -async fn stress_test_fed(dev_fed: &DevFed) -> anyhow::Result<()> { - tokio::try_join!( - latency_tests(dev_fed.clone(), LatencyTest::Reissue), - latency_tests(dev_fed.clone(), LatencyTest::LnSend), - latency_tests(dev_fed.clone(), LatencyTest::LnReceive), - latency_tests(dev_fed.clone(), LatencyTest::FmPay), - latency_tests(dev_fed.clone(), LatencyTest::Restore), - )?; - Ok(()) -} - #[tokio::main] async fn main() -> anyhow::Result<()> { let args: Args = Args::parse(); @@ -85,72 +24,6 @@ async fn main() -> anyhow::Result<()> { std::env::set_var("FM_USE_UNKNOWN_MODULE", "0"); devimint::cli::handle_command(cmd, args.common).await?; } - Cmd::TestUpgrade { - old_fedimintd, - new_fedimintd, - } => { - let (process_mgr, _) = setup(args.common).await?; - std::env::set_var("FM_FEDIMINTD_BASE_EXECUTABLE", old_fedimintd); - - std::env::set_var("INCLUDE_STABILITY_POOL", "1"); - std::env::set_var(FEDI_STABILITY_POOL_MODULE_ENABLE_ENV, "1"); - std::env::set_var("USE_STABILITY_POOL_TEST_PARAMS", "1"); - std::env::set_var(FEDI_STABILITY_POOL_MODULE_TEST_PARAMS_ENV, "1"); - - std::env::set_var(FEDI_SOCIAL_RECOVERY_MODULE_ENABLE_ENV, "1"); - let mut dev_fed = dev_fed(&process_mgr).await?; - let client = dev_fed.fed.new_joined_client("test-client").await?; - - tokio::try_join!(stress_test_fed(&dev_fed), wait_session(&client))?; - - dev_fed.fed.terminate_server(3).await?; - // wait for SP cycle - tokio::time::sleep(Duration::from_secs(30)).await; - dev_fed.fed.terminate_server(0).await?; - dev_fed.fed.terminate_server(1).await?; - dev_fed.fed.terminate_server(2).await?; - // upgrade fedimint - std::env::set_var("FM_FEDIMINTD_BASE_EXECUTABLE", new_fedimintd); - dev_fed.fed.start_server(&process_mgr, 2).await?; - dev_fed.fed.start_server(&process_mgr, 1).await?; - dev_fed.fed.start_server(&process_mgr, 0).await?; - tokio::time::sleep(Duration::from_secs(30)).await; - dev_fed.fed.start_server(&process_mgr, 3).await?; - - stress_test_fed(&dev_fed).await?; - } - Cmd::TestUpgradeShutdownTogether { - old_fedimintd, - new_fedimintd, - } => { - let (process_mgr, _) = setup(args.common).await?; - std::env::set_var("FM_FEDIMINTD_BASE_EXECUTABLE", old_fedimintd); - std::env::set_var("INCLUDE_STABILITY_POOL", "1"); - std::env::set_var(FEDI_STABILITY_POOL_MODULE_ENABLE_ENV, "1"); - std::env::set_var("USE_STABILITY_POOL_TEST_PARAMS", "1"); - std::env::set_var(FEDI_STABILITY_POOL_MODULE_TEST_PARAMS_ENV, "1"); - - std::env::set_var(FEDI_SOCIAL_RECOVERY_MODULE_ENABLE_ENV, "1"); - let mut dev_fed = dev_fed(&process_mgr).await?; - let client = dev_fed.fed.new_joined_client("test-client").await?; - - stress_test_fed(&dev_fed).await?; - wait_session(&client).await?; - let futures = std::mem::take(&mut dev_fed.fed.members) - .into_values() - .map(|x| x.terminate()); - futures::future::try_join_all(futures).await?; - // upgrade fedimint - std::env::set_var("FM_FEDIMINTD_BASE_EXECUTABLE", new_fedimintd); - dev_fed.fed.start_server(&process_mgr, 2).await?; - dev_fed.fed.start_server(&process_mgr, 1).await?; - dev_fed.fed.start_server(&process_mgr, 0).await?; - dev_fed.fed.start_server(&process_mgr, 3).await?; - stress_test_fed(&dev_fed).await?; - wait_session(&client).await?; - wait_session(&client).await?; - stress_test_fed(&dev_fed).await?; - } } Ok(()) } diff --git a/fedi-api-types/Cargo.toml b/fedi-api-types/Cargo.toml index a81f334..ac02156 100644 --- a/fedi-api-types/Cargo.toml +++ b/fedi-api-types/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "fedi-api-types" edition = "2021" -version = "0.3.0" +version = "0.4.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde = { workspace = true } -anyhow = { workspace = true } +serde.workspace = true +anyhow.workspace = true hex = { version = "0.4.3", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] } diff --git a/fedi-api-types/src/invoice_generator.rs b/fedi-api-types/src/invoice_generator.rs index 1456b49..438e0e3 100644 --- a/fedi-api-types/src/invoice_generator.rs +++ b/fedi-api-types/src/invoice_generator.rs @@ -1,4 +1,3 @@ -use fedimint_core::core::ModuleKind; use serde::{Deserialize, Serialize}; // v0 - deprecated @@ -21,7 +20,7 @@ pub struct GenerateInvoiceResponseV0 { #[serde(tag = "type", rename = "v1")] pub struct GenerateInvoiceRequestV1 { pub amount_msat: u64, - pub module: ModuleKind, + pub module: String, pub tx_direction: TransactionDirection, } @@ -36,3 +35,10 @@ pub enum TransactionDirection { pub struct GenerateInvoiceResponseV1 { pub invoice: String, } + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(tag = "type", rename = "v1")] +pub struct InvoiceRequestMemoV1 { + pub module: String, + pub tx_direction: TransactionDirection, +} diff --git a/fedimintd/src/main.rs b/fedimintd/src/main.rs index 24010b7..c3fa1a1 100644 --- a/fedimintd/src/main.rs +++ b/fedimintd/src/main.rs @@ -23,7 +23,8 @@ async fn main() -> anyhow::Result<()> { || std::env::var("INCLUDE_STABILITY_POOL").is_ok(); let include_social_recovery = is_env_var_set(FEDI_SOCIAL_RECOVERY_MODULE_ENABLE_ENV); - let mut fedimintd = Fedimintd::new(env!("FEDIMINT_BUILD_CODE_VERSION"))?.with_default_modules(); + let mut fedimintd = + Fedimintd::new(env!("FEDIMINT_BUILD_CODE_VERSION"), Some("fedi"))?.with_default_modules(); if include_stability_pool { let use_test_params = is_env_var_set(FEDI_STABILITY_POOL_MODULE_TEST_PARAMS_ENV) || diff --git a/flake.lock b/flake.lock index 94930ee..a053232 100644 --- a/flake.lock +++ b/flake.lock @@ -48,17 +48,17 @@ ] }, "locked": { - "lastModified": 1695500413, - "narHash": "sha256-yinrAWIc4XZbWQoXOYkUO0lCNQ5z/vMyl+QCYuIwdPc=", - "owner": "dpc", + "lastModified": 1719001124, + "narHash": "sha256-JXrMwYlQarZPyjN5UkD4fS9mrHSE1PUa7P//1Z5Sqr0=", + "owner": "tadfisher", "repo": "android-nixpkgs", - "rev": "2e42268a196375ce9b010a10ec5250d2f91a09b4", + "rev": "7fa1348249564e43185d3053f579f9fa923d46cc", "type": "github" }, "original": { - "owner": "dpc", + "owner": "tadfisher", "repo": "android-nixpkgs", - "rev": "2e42268a196375ce9b010a10ec5250d2f91a09b4", + "rev": "7fa1348249564e43185d3053f579f9fa923d46cc", "type": "github" } }, @@ -72,17 +72,17 @@ ] }, "locked": { - "lastModified": 1695500413, - "narHash": "sha256-yinrAWIc4XZbWQoXOYkUO0lCNQ5z/vMyl+QCYuIwdPc=", - "owner": "dpc", + "lastModified": 1719001124, + "narHash": "sha256-JXrMwYlQarZPyjN5UkD4fS9mrHSE1PUa7P//1Z5Sqr0=", + "owner": "tadfisher", "repo": "android-nixpkgs", - "rev": "2e42268a196375ce9b010a10ec5250d2f91a09b4", + "rev": "7fa1348249564e43185d3053f579f9fa923d46cc", "type": "github" }, "original": { - "owner": "dpc", + "owner": "tadfisher", "repo": "android-nixpkgs", - "rev": "2e42268a196375ce9b010a10ec5250d2f91a09b4", + "rev": "7fa1348249564e43185d3053f579f9fa923d46cc", "type": "github" } }, @@ -116,17 +116,17 @@ ] }, "locked": { - "lastModified": 1699217310, - "narHash": "sha256-xpW3VFUG7yE6UE6Wl0dhqencuENSkV7qpnpe9I8VbPw=", + "lastModified": 1717383740, + "narHash": "sha256-559HbY4uhNeoYvK3H6AMZAtVfmR3y8plXZ1x6ON/cWU=", "owner": "ipetkov", "repo": "crane", - "rev": "d535642bbe6f377077f7c23f0febb78b1463f449", + "rev": "b65673fce97d277934488a451724be94cc62499a", "type": "github" }, "original": { "owner": "ipetkov", "repo": "crane", - "rev": "d535642bbe6f377077f7c23f0febb78b1463f449", + "rev": "b65673fce97d277934488a451724be94cc62499a", "type": "github" } }, @@ -138,17 +138,17 @@ ] }, "locked": { - "lastModified": 1716156051, - "narHash": "sha256-TjUX7WWRcrhuUxDHsR8pDR2N7jitqZehgCVSy3kBeS8=", + "lastModified": 1717383740, + "narHash": "sha256-559HbY4uhNeoYvK3H6AMZAtVfmR3y8plXZ1x6ON/cWU=", "owner": "ipetkov", "repo": "crane", - "rev": "7443df1c478947bf96a2e699209f53b2db26209d", + "rev": "b65673fce97d277934488a451724be94cc62499a", "type": "github" }, "original": { "owner": "ipetkov", "repo": "crane", - "rev": "7443df1c478947bf96a2e699209f53b2db26209d", + "rev": "b65673fce97d277934488a451724be94cc62499a", "type": "github" } }, @@ -255,17 +255,17 @@ "nixpkgs": "nixpkgs_5" }, "locked": { - "lastModified": 1720113148, - "narHash": "sha256-0hSJjjQuZW4FymLV38jH3QiF7n2qYiHEmNjgi+gtL9M=", + "lastModified": 1724250977, + "narHash": "sha256-FMDH6mESzY78NH69D7HdZV3meHloUCbamQmcxN2cxHc=", "owner": "fedibtc", "repo": "fedimint", - "rev": "2ea651c2da20a0380062109428b43d4702a47bae", + "rev": "b41b1ef19d3addcf2a94cc1eb1aa82b10275e907", "type": "github" }, "original": { "owner": "fedibtc", + "ref": "v0.4.2-rc.0-fed", "repo": "fedimint", - "rev": "2ea651c2da20a0380062109428b43d4702a47bae", "type": "github" } }, @@ -550,17 +550,17 @@ "systems": "systems_6" }, "locked": { - "lastModified": 1709623646, - "narHash": "sha256-kqN+O/D+s2SKYfDdJUrmh1/tpc476gn+JU7JjjnkSik=", + "lastModified": 1719004469, + "narHash": "sha256-TZSHiEJ3qYgA46vikQKT2bwGCEF2LrJVw7cettqa+/g=", "owner": "dpc", "repo": "flakebox", - "rev": "27ecbf8f2b252dd843d0f58d45658eb56bb5e223", + "rev": "12d5ee4f6c47bc01f07ec6f5848a83db265902d3", "type": "github" }, "original": { "owner": "dpc", "repo": "flakebox", - "rev": "27ecbf8f2b252dd843d0f58d45658eb56bb5e223", + "rev": "12d5ee4f6c47bc01f07ec6f5848a83db265902d3", "type": "github" } }, @@ -578,17 +578,17 @@ "systems": "systems_10" }, "locked": { - "lastModified": 1716395311, - "narHash": "sha256-vEoZ4CFyBKYv3G4zZiTFob+YwUIXgjScBg3J40qs7wo=", - "owner": "dpc", + "lastModified": 1719004469, + "narHash": "sha256-TZSHiEJ3qYgA46vikQKT2bwGCEF2LrJVw7cettqa+/g=", + "owner": "fedibtc", "repo": "flakebox", - "rev": "19f4cc696fdd1422cb522fdadbe82df2473cb479", + "rev": "12d5ee4f6c47bc01f07ec6f5848a83db265902d3", "type": "github" }, "original": { - "owner": "dpc", + "owner": "fedibtc", "repo": "flakebox", - "rev": "19f4cc696fdd1422cb522fdadbe82df2473cb479", + "rev": "12d5ee4f6c47bc01f07ec6f5848a83db265902d3", "type": "github" } }, @@ -602,13 +602,13 @@ "locked": { "lastModified": 1693034888, "narHash": "sha256-xYzhy2LZ6DvdKNUxHmZRBZW3qhLFizIXSmm6tPQp3h4=", - "owner": "dpc", + "owner": "fedibtc", "repo": "fs-dir-cache", "rev": "a6371f48f84512ea06a8ac671f9cdc141a732673", "type": "github" }, "original": { - "owner": "dpc", + "owner": "fedibtc", "repo": "fs-dir-cache", "rev": "a6371f48f84512ea06a8ac671f9cdc141a732673", "type": "github" @@ -729,16 +729,16 @@ }, "nixpkgs_5": { "locked": { - "lastModified": 1709309926, - "narHash": "sha256-VZFBtXGVD9LWTecGi6eXrE0hJ/mVB3zGUlHImUs2Qak=", + "lastModified": 1721686456, + "narHash": "sha256-nw/BnNzATDPfzpJVTnY8mcSKKsz6BJMEFRkJ332QSN0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "79baff8812a0d68e24a836df0a364c678089e2c7", + "rev": "575f3027caa1e291d24f1e9fb0e3a19c2f26d96b", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-23.11", + "ref": "nixos-24.05", "repo": "nixpkgs", "type": "github" } @@ -761,16 +761,16 @@ }, "nixpkgs_7": { "locked": { - "lastModified": 1711668574, - "narHash": "sha256-u1dfs0ASQIEr1icTVrsKwg2xToIpn7ZXxW3RHfHxshg=", + "lastModified": 1721686456, + "narHash": "sha256-nw/BnNzATDPfzpJVTnY8mcSKKsz6BJMEFRkJ332QSN0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "219951b495fc2eac67b1456824cc1ec1fd2ee659", + "rev": "575f3027caa1e291d24f1e9fb0e3a19c2f26d96b", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.11", + "ref": "nixos-24.05", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index d55c355..aca8ab6 100644 --- a/flake.nix +++ b/flake.nix @@ -1,12 +1,12 @@ { inputs = { nixpkgs = { - url = "github:NixOS/nixpkgs/nixos-23.11"; + url = "github:NixOS/nixpkgs/nixos-24.05"; }; nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; fedimint-pkgs = { - url = "github:fedibtc/fedimint/2ea651c2da20a0380062109428b43d4702a47bae"; #ref=v0.3.2-rc.0-fed1 + url = "github:fedibtc/fedimint?ref=v0.4.2-rc.0-fed"; }; fenix = { @@ -14,13 +14,13 @@ inputs.nixpkgs.follows = "nixpkgs"; }; flakebox = { - url = "github:dpc/flakebox?rev=19f4cc696fdd1422cb522fdadbe82df2473cb479"; + url = "github:fedibtc/flakebox?rev=12d5ee4f6c47bc01f07ec6f5848a83db265902d3"; inputs.nixpkgs.follows = "nixpkgs"; inputs.fenix.follows = "fenix"; }; fs-dir-cache = { - url = "github:dpc/fs-dir-cache?rev=a6371f48f84512ea06a8ac671f9cdc141a732673"; + url = "github:fedibtc/fs-dir-cache?rev=a6371f48f84512ea06a8ac671f9cdc141a732673"; }; android-nixpkgs = { @@ -119,9 +119,11 @@ build-tools-30-0-3 build-tools-32-0-0 build-tools-33-0-0 + build-tools-34-0-0 platform-tools platforms-android-31 platforms-android-33 + platforms-android-34 emulator ndk-bundle ndk-23-1-7779620 @@ -285,7 +287,7 @@ pkgs.binaryen pkgs.gnused pkgs.yarn - pkgs.nodejs_21 + pkgs.nodejs_22 pkgs.nodePackages.prettier # for ts-bindgen pkgs.jdk17 pkgs.nodePackages.typescript-language-server @@ -321,6 +323,10 @@ export PATH="''${REPO_ROOT}/nix/cargo-wrapper/:$PATH" export RUSTC_WRAPPER=${pkgs.sccache}/bin/sccache export CARGO_BUILD_TARGET_DIR="''${CARGO_BUILD_TARGET_DIR:-''${REPO_ROOT}/target-nix}" + + # this is where we publish the android bridge package so the react native app + # can find it as a local maven dependency + export ANDROID_BRIDGE_ARTIFACTS="''${REPO_ROOT}/bridge/fedi-android/artifacts" ''; }); in @@ -336,6 +342,7 @@ fedi-fedimintd = craneMultiBuild.fedi-fedimintd; fedi-fedimint-cli = craneMultiBuild.fedi-fedimint-cli; + fedi-api-types = craneMultiBuild.fedi-api-types; fedi-wasm = craneMultiBuild.wasm32-unknown.release.fedi-wasm; }; diff --git a/justfile.fedi b/justfile.fedi index 6988e17..3f9a453 100644 --- a/justfile.fedi +++ b/justfile.fedi @@ -127,12 +127,6 @@ fedimint-cli-v0_2_2-rc7 *ARGS: fedimint-cli-v0_2_2-rc8 *ARGS: @just fedimint-cli "refs/tags/v0.2.2-rc8" d3e154ef0ea2fde064d6f3c3d40b9800c9a9a3ce {{ARGS}} -fedi-fedimint-cli-v0_2_2-rc8 *ARGS: - @just fedi-fedimint-cli "deployments/v0.2.2-rc8" 719a96d26e67f39d00ca37c1c160b0556ae20622 {{ARGS}} - -fedi-fedimint-cli-master *ARGS: - @just fedi-fedimint-cli "master" 38447bb77b28c95874fcb03d6e66dc2f357c1953 {{ARGS}} - tidy-up: @./scripts/tidy-up.sh diff --git a/misc/fedimintd-container-entrypoint.sh b/misc/fedimintd-container-entrypoint.sh old mode 100755 new mode 100644 diff --git a/modules/fedi-social/client/Cargo.toml b/modules/fedi-social/client/Cargo.toml index 527bb03..ff64331 100644 --- a/modules/fedi-social/client/Cargo.toml +++ b/modules/fedi-social/client/Cargo.toml @@ -22,6 +22,7 @@ hex = { workspace = true, features = ["serde"] } itertools = { workspace = true } fedimint-aead = { workspace = true } fedimint-client = { workspace = true } +fedimint-api-client = { workspace = true } fedimint-core = { workspace = true } fedimint-derive-secret = { workspace = true } fedimint_threshold_crypto = { workspace = true } diff --git a/modules/fedi-social/client/src/api.rs b/modules/fedi-social/client/src/api.rs index 9b20a0a..c962386 100644 --- a/modules/fedi-social/client/src/api.rs +++ b/modules/fedi-social/client/src/api.rs @@ -1,10 +1,14 @@ +use std::time::Duration; + use async_trait::async_trait; use fedi_social_common::common::SignedRecoveryRequest; use fedi_social_common::SignedBackupRequest; -use fedimint_core::api::{FederationApiExt, FederationResult, IRawFederationApi}; +use fedimint_api_client::api::{FederationApiExt, FederationResult, IRawFederationApi}; use fedimint_core::core::ModuleInstanceId; use fedimint_core::module::ApiRequestErased; use fedimint_core::task::{MaybeSend, MaybeSync}; +use futures::future::join_all; +use tracing::info; #[cfg_attr(target_family = "wasm", async_trait(? Send))] #[cfg_attr(not(target_family = "wasm"), async_trait)] @@ -16,7 +20,7 @@ pub trait FediSocialFederationApi { request: &SignedBackupRequest, ) -> FederationResult<()>; - async fn social_recovery( + async fn start_social_recovery( &self, module_id: ModuleInstanceId, request: &SignedRecoveryRequest, @@ -35,16 +39,40 @@ where _module_id: ModuleInstanceId, request: &SignedBackupRequest, ) -> FederationResult<()> { - self.request_current_consensus("backup".into(), ApiRequestErased::new(request)) - .await + for res in join_all(self.all_peers().iter().map(|peer_id| { + info!(%peer_id, id=%request.backup_id(), "Uploading social backup to guardian"); + self.request_single_peer_federation( + Some(Duration::from_secs(60)), + "backup".into(), + ApiRequestErased::new(request), + *peer_id, + ) + })) + .await + { + let _ = res?; + } + Ok(()) } - async fn social_recovery( + async fn start_social_recovery( &self, _module_id: ModuleInstanceId, request: &SignedRecoveryRequest, ) -> FederationResult<()> { - self.request_current_consensus("recover".into(), ApiRequestErased::new(request)) - .await + for res in join_all(self.all_peers().iter().map(|peer_id| { + info!(%peer_id, id=%request.recovery_id(), "Uploading social backup to guardian"); + self.request_single_peer_federation( + Some(Duration::from_secs(60)), + "recover".into(), + ApiRequestErased::new(request), + *peer_id, + ) + })) + .await + { + let _ = res?; + } + Ok(()) } } diff --git a/modules/fedi-social/client/src/client.rs b/modules/fedi-social/client/src/client.rs index 0dcdf3b..9a06db9 100644 --- a/modules/fedi-social/client/src/client.rs +++ b/modules/fedi-social/client/src/client.rs @@ -3,7 +3,7 @@ use std::fmt; use anyhow::format_err; use bitcoin::secp256k1; -use fedimint_core::api::DynModuleApi; +use fedimint_api_client::api::{DynModuleApi, FederationApiExt}; use fedimint_core::config::ClientConfig; use fedimint_core::core::ModuleInstanceId; use fedimint_core::encoding::{Decodable, Encodable}; @@ -191,7 +191,7 @@ impl SocialBackup { } /// The state of recovery, that can be serialized and stored -#[derive(Encodable, Decodable, Clone, Debug, Serialize, Deserialize)] +#[derive(Encodable, Decodable, Clone, Serialize, Deserialize)] pub struct SocialRecoveryState { signing_sk: SerdeEncodable, encryption_key: [u8; 32], @@ -203,6 +203,17 @@ pub struct SocialRecoveryState { pub client_config: String, } +// Implement Debug manually to ignore sensitive fields +impl fmt::Debug for SocialRecoveryState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SocialRecoveryState") + .field("double_encrypted_seed", &self.double_encrypted_seed) + .field("shares", &self.shares) + .field("client_config", &self.client_config) + .finish() + } +} + impl SocialRecoveryState { fn new(recovery_file: RecoveryFile) -> Self { Self { @@ -296,7 +307,7 @@ impl SocialRecoveryClient { &self, req: &SignedRecoveryRequest, ) -> anyhow::Result<()> { - self.api.social_recovery(self.module_id, req).await?; + self.api.start_social_recovery(self.module_id, req).await?; Ok(()) } @@ -405,17 +416,16 @@ impl SocialVerification { id: RecoveryId, admin_password: &str, ) -> anyhow::Result<()> { - let encrypted_share = self + let _: Option<()> = self .api - .request_raw( + .request_single_peer_typed( + None, + "approve_recovery".to_owned(), + ApiRequestErased::new((id, admin_password)), self.peer_id, - "approve_recovery", - &[ApiRequestErased::new((id, admin_password)).to_json()], ) .await?; - let _: Option<()> = serde_json::from_value(encrypted_share)?; - Ok(()) } } diff --git a/modules/fedi-social/client/src/lib.rs b/modules/fedi-social/client/src/lib.rs index 290e47c..e7bca03 100644 --- a/modules/fedi-social/client/src/lib.rs +++ b/modules/fedi-social/client/src/lib.rs @@ -18,7 +18,6 @@ use fedimint_core::{apply, async_trait_maybe_send}; #[derive(Debug, Clone)] pub struct FediSocialClientInit; -#[apply(async_trait_maybe_send!)] impl ModuleInit for FediSocialClientInit { type Common = FediSocialCommonGen; @@ -60,17 +59,17 @@ impl ClientModule for FediSocialClientModule { fn context(&self) -> Self::ModuleStateMachineContext {} - fn input_amount( + fn input_fee( &self, _input: &::Input, - ) -> Option { + ) -> Option { unreachable!("FediSocial does not have any inputs") } - fn output_amount( + fn output_fee( &self, _output: &::Output, - ) -> Option { + ) -> Option { unreachable!("FediSocial does not have any outputs") } } diff --git a/modules/fedi-social/common/src/common.rs b/modules/fedi-social/common/src/common.rs index c406730..d97f463 100644 --- a/modules/fedi-social/common/src/common.rs +++ b/modules/fedi-social/common/src/common.rs @@ -108,7 +108,8 @@ impl VerificationDocument { Self( // add checksum of the original data - hash.iter() + hash.as_byte_array() + .iter() .copied() .chain( // XOR the data with a simple pattern, just @@ -127,7 +128,7 @@ impl VerificationDocument { .collect(); let hash = sha256::Hash::hash(&raw_data); - if hash.as_ref() != &self.0[..Self::HASH_LENGHT] { + if hash.as_byte_array() != &self.0[..Self::HASH_LENGHT] { anyhow::bail!("The verification document raw data does not match the checksum"); } @@ -241,6 +242,10 @@ impl BackupRequest { signature, }) } + + pub fn id(&self) -> BackupId { + self.id + } } /// Signed [`BackupRequest`] @@ -252,13 +257,17 @@ pub struct SignedBackupRequest { } impl SignedBackupRequest { + pub fn backup_id(&self) -> BackupId { + self.request.id() + } + pub fn verify_valid(&self, ctx: &Secp256k1) -> Result<&BackupRequest, secp256k1::Error> where C: Signing + Verification, { ctx.verify_schnorr( &self.signature, - &Message::from_slice(&self.request.hash()).expect("Can't fail"), + &Message::from_slice(self.request.hash().as_ref()).expect("Can't fail"), &self.request.id.0.x_only_public_key().0, )?; @@ -315,7 +324,7 @@ impl SignedRecoveryRequest { { ctx.verify_schnorr( &self.signature, - &Message::from_slice(&self.request.hash()).expect("Can't fail"), + &Message::from_slice(self.request.hash().as_byte_array()).expect("Can't fail"), &self.request.id.0.x_only_public_key().0, )?; diff --git a/modules/fedi-social/server/src/lib.rs b/modules/fedi-social/server/src/lib.rs index 3fc8d01..d0c9994 100644 --- a/modules/fedi-social/server/src/lib.rs +++ b/modules/fedi-social/server/src/lib.rs @@ -46,7 +46,6 @@ use crate::common::{ #[derive(Clone, Debug)] pub struct FediSocialInit; -#[async_trait] impl ModuleInit for FediSocialInit { type Common = FediSocialCommonGen; const DATABASE_VERSION: DatabaseVersion = DatabaseVersion(0); @@ -133,7 +132,10 @@ impl ServerModuleInit for FediSocialInit { peers: &[PeerId], _params: &ConfigGenModuleParams, ) -> BTreeMap { - let sks = fedimint_threshold_crypto::SecretKeySet::random(peers.degree(), &mut OsRng); + let sks = fedimint_threshold_crypto::SecretKeySet::random( + peers.to_num_peers().degree(), + &mut OsRng, + ); let pks = sks.public_keys(); let server_cfg = peers.iter().map(|&peer| { @@ -146,7 +148,8 @@ impl ServerModuleInit for FediSocialInit { sk_share: fedimint_threshold_crypto::serde_impl::SerdeSecret(sk), }, consensus: FediSocialConsensusConfig { - threshold: u32::try_from(peers.threshold()).expect("must not fail"), + threshold: u32::try_from(peers.to_num_peers().threshold()) + .expect("must not fail"), pk_set: pks.clone(), }, local: FediSocialConfigLocal {}, @@ -176,7 +179,8 @@ impl ServerModuleInit for FediSocialInit { }, consensus: FediSocialConsensusConfig { pk_set: public_key_set, - threshold: u32::try_from(peers.peer_ids().threshold()).expect("must not fail"), + threshold: u32::try_from(peers.peer_ids().to_num_peers().threshold()) + .expect("must not fail"), }, local: FediSocialConfigLocal {}, }; diff --git a/modules/stability-pool/client/Cargo.toml b/modules/stability-pool/client/Cargo.toml index efe5b25..03f9079 100644 --- a/modules/stability-pool/client/Cargo.toml +++ b/modules/stability-pool/client/Cargo.toml @@ -10,10 +10,9 @@ anyhow = { workspace = true } async-trait = { workspace = true } fedimint-core = { workspace = true } fedimint-client = { workspace = true } +fedimint-api-client = { workspace = true } futures = { workspace = true } serde = { workspace = true, features = ["derive"] } -strum = { workspace = true } -strum_macros = { workspace = true } bitcoin = { workspace = true, features = ["rand", "serde"] } tracing = { workspace = true } secp256k1-zkp = { workspace = true, features = ["serde", "bitcoin_hashes"] } diff --git a/modules/stability-pool/client/src/lib.rs b/modules/stability-pool/client/src/lib.rs index 1373028..8936f1c 100644 --- a/modules/stability-pool/client/src/lib.rs +++ b/modules/stability-pool/client/src/lib.rs @@ -4,9 +4,8 @@ use std::pin::Pin; use std::sync::Arc; use std::time::{Duration, SystemTime}; -use anyhow::{anyhow, bail}; +use anyhow::bail; use async_stream::stream; -use bitcoin::KeyPair; use common::config::StabilityPoolClientConfig; use common::{ amount_to_cents, AccountInfo, CancelRenewal, IntendedAction, LiquidityStats, Provide, Seek, @@ -14,6 +13,7 @@ use common::{ BPS_UNIT, }; use db::AccountInfoKey; +use fedimint_api_client::api::{DynModuleApi, FederationApiExt as _, FederationError}; use fedimint_client::module::init::{ClientModuleInit, ClientModuleInitArgs}; use fedimint_client::module::recovery::NoModuleBackup; use fedimint_client::module::{ClientContext, ClientModule}; @@ -24,7 +24,6 @@ use fedimint_client::sm::{ }; use fedimint_client::transaction::{ClientInput, ClientOutput, TransactionBuilder}; use fedimint_client::{sm_enum_variant_translation, DynGlobalClientContext}; -use fedimint_core::api::{DynModuleApi, FederationApiExt, FederationError}; use fedimint_core::core::{IntoDynInstance, ModuleInstanceId, OperationId}; use fedimint_core::db::{ Database, DatabaseTransaction, DatabaseVersion, IDatabaseTransactionOpsCoreTyped, @@ -32,12 +31,11 @@ use fedimint_core::db::{ use fedimint_core::encoding::{Decodable, Encodable}; use fedimint_core::module::{ ApiRequestErased, ApiVersion, CommonModuleInit, ModuleInit, MultiApiVersion, - TransactionItemAmount, }; use fedimint_core::task::timeout; use fedimint_core::{apply, async_trait_maybe_send, Amount, OutPoint, TransactionId}; use futures::{Stream, StreamExt}; -use secp256k1_zkp::Secp256k1; +use secp256k1_zkp::{KeyPair, Secp256k1}; use serde::{Deserialize, Serialize}; pub use stability_pool_common as common; use tokio::sync::Mutex; @@ -48,7 +46,6 @@ mod db; #[derive(Debug, Clone)] pub struct StabilityPoolClientInit; -#[apply(async_trait_maybe_send!)] impl ModuleInit for StabilityPoolClientInit { type Common = StabilityPoolCommonGen; const DATABASE_VERSION: DatabaseVersion = DatabaseVersion(0); @@ -121,29 +118,14 @@ impl ClientModule for StabilityPoolClientModule { } } - fn input_amount(&self, input: &StabilityPoolInput) -> Option { - let input = input.maybe_v0_ref()?; - + fn input_fee(&self, _input: &StabilityPoolInput) -> Option { // TODO shaurya figure out fees - Some(TransactionItemAmount { - amount: input.amount, - fee: Amount::ZERO, - }) + Some(Amount::ZERO) } - fn output_amount(&self, output: &StabilityPoolOutput) -> Option { - let output = output.maybe_v0_ref()?; - + fn output_fee(&self, _output: &StabilityPoolOutput) -> Option { // TODO shaurya figure out fees - Some(TransactionItemAmount { - amount: match output.intended_action { - IntendedAction::Seek(Seek(amount)) => amount, - IntendedAction::Provide(Provide { amount, .. }) => amount, - IntendedAction::CancelRenewal(_) => Amount::ZERO, - IntendedAction::UndoCancelRenewal => Amount::ZERO, - }, - fee: Amount::ZERO, - }) + Some(Amount::ZERO) } async fn handle_cli_command( @@ -525,10 +507,7 @@ pub struct ClientAccountInfo { } impl StabilityPoolClientModule { - pub async fn account_info( - &self, - force_update: bool, - ) -> anyhow::Result { + pub async fn account_info(&self, force_update: bool) -> anyhow::Result { let _lock = self.account_info_lock.lock().await; let mut dbtx = self.db.begin_transaction_nc().await; let db_account_info = dbtx.get_value(&AccountInfoKey).await; @@ -564,22 +543,21 @@ impl StabilityPoolClientModule { }); } - Err(FederationError::general(anyhow!("No local data present"))) + anyhow::bail!("No local data present") } async fn fetch_account_info_from_server( &self, timeout_duration: Duration, - ) -> anyhow::Result { - timeout( + ) -> anyhow::Result { + Ok(timeout( timeout_duration, self.module_api.request_current_consensus( "account_info".to_string(), ApiRequestErased::new(self.client_key_pair.public_key()), ), ) - .await - .map_err(FederationError::general)? + .await??) } pub async fn current_cycle_index(&self) -> anyhow::Result { @@ -716,6 +694,7 @@ impl StabilityPoolClientModule { if unlocked_amount != Amount::ZERO { let input = ClientInput { + amount: unlocked_amount, input: StabilityPoolInput::new_v0( self.client_key_pair.public_key(), unlocked_amount, @@ -974,6 +953,7 @@ async fn submit_tx_with_intended_action( let (transaction_id, _) = match intended_action { IntendedAction::Seek(Seek(amount)) | IntendedAction::Provide(Provide { amount, .. }) => { let output = ClientOutput { + amount, output: stability_pool_output, state_machines: Arc::new(move |_, _| Vec::::new()), }; @@ -994,6 +974,7 @@ async fn submit_tx_with_intended_action( } IntendedAction::CancelRenewal(CancelRenewal { bps }) => { let output = ClientOutput { + amount: Amount::ZERO, output: stability_pool_output, state_machines: Arc::new(move |transaction_id, _| { vec![StabilityPoolStateMachines::CancelLocked( @@ -1091,6 +1072,7 @@ async fn claim_idle_balance_input( idle_balance: Amount, ) -> StabilityPoolCancelLockedStateMachine { let input = ClientInput { + amount: idle_balance, input: StabilityPoolInput::new_v0( context.module.client_key_pair.public_key(), idle_balance, @@ -1124,6 +1106,7 @@ async fn maybe_fund_cancellation_output( state: match old_state.maybe_cancel_locked_bps { Some(bps) => { let output = ClientOutput { + amount: Amount::ZERO, output: StabilityPoolOutput::new_v0( context.module.client_key_pair.public_key(), IntendedAction::CancelRenewal(CancelRenewal { bps }), diff --git a/modules/stability-pool/server/Cargo.toml b/modules/stability-pool/server/Cargo.toml index 22b82a5..8b7ee57 100644 --- a/modules/stability-pool/server/Cargo.toml +++ b/modules/stability-pool/server/Cargo.toml @@ -9,8 +9,6 @@ async-trait = { workspace = true } fedimint-core = { workspace = true } futures = { workspace = true } serde = { workspace = true } -strum = { workspace = true } -strum_macros = { workspace = true } bitcoin = { workspace = true } tracing = { workspace = true } secp256k1-zkp = { workspace = true } diff --git a/modules/stability-pool/server/src/lib.rs b/modules/stability-pool/server/src/lib.rs index 1a7b998..15bf857 100644 --- a/modules/stability-pool/server/src/lib.rs +++ b/modules/stability-pool/server/src/lib.rs @@ -53,7 +53,6 @@ const B: u128 = 1_000_000_000; #[derive(Debug, Clone)] pub struct StabilityPoolInit; -#[async_trait] impl ModuleInit for StabilityPoolInit { type Common = StabilityPoolCommonGen; const DATABASE_VERSION: DatabaseVersion = DatabaseVersion(2); @@ -100,7 +99,7 @@ impl ServerModuleInit for StabilityPoolInit { local: StabilityPoolConfigLocal, private: StabilityPoolConfigPrivate, consensus: StabilityPoolConfigConsensus { - consensus_threshold: peers.threshold() as _, + consensus_threshold: peers.to_num_peers().threshold() as _, oracle_config: params.consensus.oracle_config.clone(), cycle_duration: params.consensus.cycle_duration, collateral_ratio: params.consensus.collateral_ratio.clone(), @@ -135,7 +134,7 @@ impl ServerModuleInit for StabilityPoolInit { local: StabilityPoolConfigLocal, private: StabilityPoolConfigPrivate, consensus: StabilityPoolConfigConsensus { - consensus_threshold: peers.peers.threshold() as _, + consensus_threshold: peers.peers.to_num_peers().threshold() as _, oracle_config: params.consensus.oracle_config, cycle_duration: params.consensus.cycle_duration, collateral_ratio: params.consensus.collateral_ratio, @@ -173,9 +172,9 @@ impl ServerModuleInit for StabilityPoolInit { fn get_database_migrations( &self, - ) -> BTreeMap { + ) -> BTreeMap { let mut migrations = - BTreeMap::::default(); + BTreeMap::::default(); migrations.insert(DatabaseVersion(1), |dbtx| migrate_to_v2(dbtx).boxed()); migrations } diff --git a/modules/stability-pool/tests/tests/tests.rs b/modules/stability-pool/tests/tests/tests.rs index 545b34c..189246c 100644 --- a/modules/stability-pool/tests/tests/tests.rs +++ b/modules/stability-pool/tests/tests/tests.rs @@ -6,6 +6,7 @@ use std::time::Duration; use anyhow::anyhow; use devimint::external::Bitcoind; +use devimint::federation::Federation; use devimint::util::{Command, ProcessManager}; use devimint::{cmd, dev_fed, vars, DevFed}; use fedimint_core::task::TaskGroup; @@ -47,8 +48,8 @@ async fn starter_test() -> anyhow::Result<()> { // Peg in for seeker and provider and verify balances fed.await_block_sync().await?; let (seeker_peg_in_op_id, provider_peg_in_op_id) = tokio::try_join!( - seeker.initiate_peg_in(&bitcoind, seeker_peg_in_sats), - provider.initiate_peg_in(&bitcoind, provider_peg_in_sats) + seeker.initiate_peg_in(&fed, &bitcoind, seeker_peg_in_sats), + provider.initiate_peg_in(&fed, &bitcoind, provider_peg_in_sats) )?; bitcoind.mine_blocks(30).await?; tokio::try_join!( @@ -615,7 +616,7 @@ impl ForkedClient { }) } - pub async fn cmd(&self) -> Command { + pub fn cmd(&self) -> Command { cmd!( "fedimint-cli", format!("--data-dir={}", self.data_dir_path.display()) @@ -632,13 +633,24 @@ impl ForkedClient { .unwrap()) } - async fn initiate_peg_in(&self, bitcoind: &Bitcoind, amount: u64) -> anyhow::Result { + async fn initiate_peg_in( + &self, + fed: &Federation, + bitcoind: &Bitcoind, + amount: u64, + ) -> anyhow::Result { + let deposit_fees = fed.deposit_fees()?; info!(self.name, amount, "Peg-in"); let deposit = cmd!(self, "deposit-address").out_json().await?; let deposit_address = deposit["address"].as_str().unwrap(); let deposit_operation_id = deposit["operation_id"].as_str().unwrap(); - bitcoind.send_to(deposit_address.to_owned(), amount).await?; + bitcoind + .send_to( + deposit_address.to_owned(), + amount + deposit_fees.msats / 1000, + ) + .await?; Ok(deposit_operation_id.to_string()) } diff --git a/nix/cargo-wrapper/cargo b/nix/cargo-wrapper/cargo index 94a6a40..0d6e612 100755 --- a/nix/cargo-wrapper/cargo +++ b/nix/cargo-wrapper/cargo @@ -89,7 +89,11 @@ done if [ -n "$target" ]; then rocksdb_lib_dir="ROCKSDB_${target}_LIB_DIR" snappy_lib_dir="SNAPPY_${target}_LIB_DIR" + sqlite3_lib_dir="SQLITE3_${target}_LIB_DIR" + sqlcipher_lib_dir="SQLCIPHER_${target}_LIB_DIR" rocksdb_static="ROCKSDB_${target}_STATIC" + sqlite3_static="SQLITE3_${target}_STATIC" + sqlcipher_static="SQLCIPHER_${target}_STATIC" snappy_static="SNAPPY_${target}_STATIC" if [ -n "${!rocksdb_lib_dir}" ]; then @@ -102,6 +106,16 @@ if [ -n "$target" ]; then else unset SNAPPY_LIB_DIR fi + if [ -n "${!sqlite3_lib_dir}" ]; then + export SQLITE3_LIB_DIR="${!sqlite3_lib_dir}" + else + unset SQLITE3_LIB_DIR + fi + if [ -n "${!sqlcipher_lib_dir}" ]; then + export SQLCIPHER_LIB_DIR="${!sqlcipher_lib_dir}" + else + unset SQLCIPHER_LIB_DIR + fi if [ -n "${!rocksdb_static}" ]; then export ROCKSDB_STATIC="${!rocksdb_static}" else @@ -112,6 +126,16 @@ if [ -n "$target" ]; then else unset SNAPPY_STATIC fi + if [ -n "${!sqlite3_static}" ]; then + export SQLITE3_STATIC="${!sqlite3_static}" + else + unset SQLITE3_STATIC + fi + if [ -n "${!sqlcipher_static}" ]; then + export SQLCIPHER_STATIC="${!sqlcipher_static}" + else + unset SQLCIPHER_STATIC + fi fi cmd_accepts_target_dir="" diff --git a/nix/flakebox.nix b/nix/flakebox.nix index 732f76f..a4fcc0f 100644 --- a/nix/flakebox.nix +++ b/nix/flakebox.nix @@ -11,6 +11,7 @@ let "bridge" "fedimintd" "fedimint-cli" + "fedi-api-types" "fedi-db-dump" "fedi-debug" "fedi-core" @@ -22,7 +23,6 @@ let "modules/stability-pool/common" "modules/stability-pool/server" "modules/stability-pool/tests" - "fedi-api-types" ]; root = builtins.path { @@ -67,9 +67,17 @@ let ROCKSDB_STATIC = "true"; ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib/"; SNAPPY_LIB_DIR = "${pkgs.pkgsStatic.snappy}/lib/"; + SQLITE3_STATIC = "true"; + SQLITE3_LIB_DIR = "${pkgs.pkgsStatic.sqlite.out}/lib/"; + SQLCIPHER_STATIC = "true"; + SQLCIPHER_LIB_DIR = "${pkgs.pkgsStatic.sqlcipher}/lib/"; "ROCKSDB_${target_underscores}_STATIC" = "true"; "ROCKSDB_${target_underscores}_LIB_DIR" = "${pkgs.rocksdb}/lib/"; + "SQLITE3_${target_underscores}_STATIC" = "true"; + "SQLITE3_${target_underscores}_LIB_DIR" = "${pkgs.pkgsStatic.sqlite}/lib/"; + "SQLCIPHER_${target_underscores}_STATIC" = "true"; + "SQLCIPHER_${target_underscores}_LIB_DIR" = "${pkgs.pkgsStatic.sqlcipher}/lib/"; "SNAPPY_${target_underscores}_LIB_DIR" = "${pkgs.pkgsStatic.snappy}/lib/"; } // pkgs.lib.optionalAttrs (!pkgs.stdenv.isDarwin) { # macos can't static libraries @@ -291,6 +299,13 @@ rec { fedi-fedimintd = flakeboxLib.pickBinary { bin = "fedimintd"; pkg = fedi-fedimint-pkgs; }; fedi-fedimint-cli = flakeboxLib.pickBinary { bin = "fedimint-cli"; pkg = fedi-fedimint-pkgs; }; + fedi-api-types = fediBuildPackageGroup { + pname = "fedi-api-types"; + packages = [ + "fedi-api-types" + ]; + }; + fedi-wasm = fediBuildPackageGroup { pname = "fedi-wasm"; packages = [ diff --git a/scripts/bridge/build-bridge-android.sh b/scripts/bridge/build-bridge-android.sh index 940b498..0c9031c 100755 --- a/scripts/bridge/build-bridge-android.sh +++ b/scripts/bridge/build-bridge-android.sh @@ -46,6 +46,7 @@ cd $BRIDGE_ROOT/fedi-ffi # note: using '--target-dir' or otherwise this build will completely invalidate previous ones already in the ./target cargo run --target-dir "${CARGO_BUILD_TARGET_DIR}/pkg/fedi-ffi/ffi-bindgen-run" --package ffi-bindgen -- generate --language kotlin --out-dir $BRIDGE_ROOT/fedi-android/lib/src/main/kotlin "$BRIDGE_ROOT/fedi-ffi/src/fedi.udl" -# publish android live to local maven +# publish android package to a local maven repository so the app can locate it cd $BRIDGE_ROOT/fedi-android -./gradlew publishToMavenLocal +mkdir -p "$ANDROID_BRIDGE_ARTIFACTS" +./gradlew publishMavenPublicationToFediAndroidRepository \ No newline at end of file diff --git a/scripts/ci/run-in-fs-dir-cache.sh b/scripts/ci/run-in-fs-dir-cache.sh index 741b2c2..0209b6c 100755 --- a/scripts/ci/run-in-fs-dir-cache.sh +++ b/scripts/ci/run-in-fs-dir-cache.sh @@ -13,7 +13,7 @@ fi export FS_DIR_CACHE_ROOT="$HOME/.cache/fs-dir-cache" # directory to hold all cache (sub)directories export FS_DIR_CACHE_LOCK_ID="pid-$$-rnd-$RANDOM" # acquire lock based on the current pid and something random (just in case pid gets reused) export FS_DIR_CACHE_KEY_NAME="$job_name" # the base name of our key -export FS_DIR_CACHE_LOCK_TIMEOUT_SECS="$((60 * 30))" # unlock after timeout in case our job fails misereably +export FS_DIR_CACHE_LOCK_TIMEOUT_SECS="$((60 * 60))" # unlock after timeout in case our job fails misereably log_file="$FS_DIR_CACHE_ROOT/log" diff --git a/scripts/ci/verify-bridge-hash.sh b/scripts/ci/verify-bridge-hash.sh new file mode 100644 index 0000000..765f146 --- /dev/null +++ b/scripts/ci/verify-bridge-hash.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +set -euo pipefail + +apk_path="$1" +git_hash="$2" + +if [ ! -e "$apk_path" ]; then + >&2 echo "Apk path $apk_path doesn't exist" + exit 1 +fi + +apk_extract_tmp="$(mktemp -d)" + +on_exit() { + rm -Rf "$apk_extract_tmp" +} +trap on_exit EXIT + +nix run nixpkgs#apktool -- d -o "${apk_extract_tmp}" -f "${apk_path}" > /dev/null +hash_from_apk=$(nix shell nixpkgs#bintools --command strings "${apk_extract_tmp}/lib/arm64-v8a/libfediffi.so" | grep -oP 'bridge version hash=\K[[:xdigit:]]{40}') + +if [ "${hash_from_apk}" != "${git_hash}" ]; then + >&2 echo "Bridge hash in the apk does not match the source code" + >&2 echo "${hash_from_apk} != ${git_hash}" + exit 1 +fi + +rm -Rf apk_extract_tmp diff --git a/scripts/common.sh b/scripts/common.sh old mode 100755 new mode 100644 diff --git a/scripts/test-bridge-current.sh b/scripts/test-bridge-current.sh index bdb4ec8..88ac307 100755 --- a/scripts/test-bridge-current.sh +++ b/scripts/test-bridge-current.sh @@ -6,4 +6,4 @@ source scripts/common.sh export PATH="${CARGO_BIN_DIR}:$PATH" own_dir="$(dirname "${BASH_SOURCE[0]}")" -source "${own_dir}/test-bridge-current.inner.sh" +source "${own_dir}/test-bridge-current.inner.sh" "$@" diff --git a/scripts/ui/bump-version-native.sh b/scripts/ui/bump-version-native.sh index c72aad3..9f4cda0 100755 --- a/scripts/ui/bump-version-native.sh +++ b/scripts/ui/bump-version-native.sh @@ -27,6 +27,8 @@ if [[ $GITHUB_REF == refs/heads/release/* ]]; then # major vs minor vs patch version bump RELEASE_BRANCH_VERSION="${GITHUB_REF##*/}" echo "Release branch: $RELEASE_BRANCH_VERSION" + + # get current version from package.json CURRENT_VERSION="$(npm pkg get version --ws false | sed 's/"//g')" echo "Current version: $CURRENT_VERSION" CURRENT_MINOR_VERSION="$(cut -d '.' -f 1,2 <<< "$CURRENT_VERSION")" @@ -46,6 +48,9 @@ if [[ $GITHUB_REF == refs/heads/release/* ]]; then # Android: just use react-native-version npx react-native-version --never-amend --never-increment-build --target android + # npm should have new version in package.json + NEW_VERSION="$(npm pkg get version --ws false | sed 's/"//g')" + # iOS: Navigate to xcode project and update version using agvtool # using only the major.minor version to avoid excessive review times # on Testflight. @@ -53,14 +58,13 @@ if [[ $GITHUB_REF == refs/heads/release/* ]]; then if command -v agvtool >/dev/null 2>&1; then echo "Bumping iOS marketing version to match npm" pushd $REPO_ROOT/ui/native/ios - agvtool new-marketing-version $RELEASE_BRANCH_VERSION + nix develop .#xcode -c agvtool new-marketing-version $NEW_VERSION popd else echo "Error: agvtool is not installed. Could not bump iOS version" fi echo "Pushing version commit to git branch" - NEW_VERSION="$(npm pkg get version --ws false | sed 's/"//g')" echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_OUTPUT echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_OUTPUT git add package.json android/app/build.gradle ios/ && git commit -m "chore: bump version for ${NEW_VERSION}" && git push diff --git a/scripts/ui/deploy-to-testflight.sh b/scripts/ui/deploy-to-testflight.sh index 5501524..639b35f 100755 --- a/scripts/ui/deploy-to-testflight.sh +++ b/scripts/ui/deploy-to-testflight.sh @@ -6,6 +6,9 @@ REPO_ROOT=$(git rev-parse --show-toplevel) $REPO_ROOT/scripts/enforce-nix.sh # Make sure Apple certificates are installed in the keychain +# and keychain is unlocked since there are some codesigning steps +# involved in the build process +security unlock-keychain -p $MATCH_PASSWORD $MATCH_KEYCHAIN_NAME $REPO_ROOT/scripts/ci/install-apple-certs.sh BUILD_BRIDGE=${BUILD_BRIDGE:-1} diff --git a/scripts/ui/start-ios.sh b/scripts/ui/start-ios.sh index 0e12d2a..c6bc296 100755 --- a/scripts/ui/start-ios.sh +++ b/scripts/ui/start-ios.sh @@ -16,6 +16,9 @@ $REPO_ROOT/scripts/enforce-nix.sh # the "xcrun xctrace list devices" command. The list includes both physical devices # connected to the machine and simulators. Once the user selects a device, the script # extracts the device ID, which can then be used to run commands specifically for that device. +# File to store the previously selected device ID +DEVICE_ID_FILE="/tmp/selected_device_id" + devices=() xcrunDevicesList=$(nix develop .#xcode --command xcrun xctrace list devices) while IFS= read -r line; do @@ -28,11 +31,43 @@ if [ ${#devices[@]} -eq 0 ]; then exit 1 fi -# Set the default choice to the last device -defaultChoice=${#devices[@]} +# Function to extract device ID from a device string +extract_device_id() { + echo "$1" | sed -n -E 's/.*\(([^)]+)\).*/\1/p' +} -# allow the user to select from the list -if [[ "$SELECT_IOS_DEVICE" == "1" ]]; then +# Check if the device ID file exists and if the stored ID matches any current device +if [[ -f "$DEVICE_ID_FILE" ]]; then + last_selected_device_id=$(cat "$DEVICE_ID_FILE") + matching_device="" + + for device in "${devices[@]}"; do + current_device_id=$(extract_device_id "$device") + if [[ "$current_device_id" == "$last_selected_device_id" ]]; then + matching_device="$device" + break + fi + done + + if [[ -n "$matching_device" ]]; then + echo "Last selected device: $matching_device" + echo "Would you like to use this device again? (press ENTER/Y/y for yes, any other key for no -- will proceed after 10 seconds...): " + + # Read user input with timeout + if read -t 10 user_choice; then + user_choice=${user_choice:-Y} + else + user_choice="Y" + fi + + if [[ "$user_choice" =~ ^[Yy]$ ]]; then + selectedDevice="$matching_device" + fi + fi +fi + +# If no device is selected yet, allow the user to choose one +if [[ -z "$selectedDevice" ]]; then echo "Select a device:" for i in "${!devices[@]}"; do echo "$((i+1))) ${devices[$i]}" @@ -40,18 +75,18 @@ if [[ "$SELECT_IOS_DEVICE" == "1" ]]; then # Prompt for user input and use the default choice if none is given read -p "Enter choice: " choice - choice=${choice:-$defaultChoice} + choice=${choice:-${#devices[@]}} selectedDevice=${devices[$((choice-1))]} # adjust for 0-indexing - - echo "You selected device: $selectedDevice" -else - # If SELECT_IOS_DEVICE is 0, select the default device without prompting the user - selectedDevice=${devices[$((defaultChoice-1))]} fi # Extract the device ID -FEDI_DEVICE_ID=$(echo "$selectedDevice" | sed -n -E 's/.*\(([^)]+)\).*/\1/p') +FEDI_DEVICE_ID=$(extract_device_id "$selectedDevice") + +# Store the selected device ID for future use +echo "$FEDI_DEVICE_ID" > "$DEVICE_ID_FILE" + +echo "You selected device: $selectedDevice" cd $REPO_ROOT/ui/native echo "Building & installing ios app bundle" diff --git a/ui/.eslintrc.js b/ui/.eslintrc.js index 7db6fb9..9622f69 100644 --- a/ui/.eslintrc.js +++ b/ui/.eslintrc.js @@ -24,6 +24,8 @@ module.exports = { ], }, ], + 'no-duplicate-imports': 'off', + '@typescript-eslint/no-duplicate-imports': ['error'], }, extends: [ 'eslint:recommended', diff --git a/ui/.prettierrc.js b/ui/.prettierrc.js index 30364f6..c59d28c 100644 --- a/ui/.prettierrc.js +++ b/ui/.prettierrc.js @@ -9,4 +9,5 @@ module.exports = { trailingComma: 'all', importOrder: ['', '^@fedi/(.*)$', '^[./]'], importOrderSeparation: true, + plugins: [require('prettier-plugin-organize-imports')], } diff --git a/ui/common/.prettierignore b/ui/common/.prettierignore index e504b64..445140c 100644 --- a/ui/common/.prettierignore +++ b/ui/common/.prettierignore @@ -1,3 +1,4 @@ dist wasm/*.js wasm/*.d.ts +types/bindings.ts.inc diff --git a/ui/common/hooks/amount.ts b/ui/common/hooks/amount.ts index 1cd36a3..7317fcd 100644 --- a/ui/common/hooks/amount.ts +++ b/ui/common/hooks/amount.ts @@ -1,26 +1,28 @@ import { TFunction } from 'i18next' -import { useState, useCallback, useMemo } from 'react' +import { useCallback, useMemo, useState } from 'react' import { RequestInvoiceArgs } from 'webln' import { + selectAmountInputType, selectBtcExchangeRate, + selectBtcUsdExchangeRate, selectCurrency, - selectMaxInvoiceAmount, - selectFederationMetadata, + selectCurrencyLocale, selectFederationBalance, - selectAmountInputType, - setAmountInputType, - selectBtcUsdExchangeRate, + selectFederationMetadata, + selectMaxInvoiceAmount, + selectMaxStableBalanceSats, selectMinimumDepositAmount, - selectWithdrawableStableBalanceMsats, selectMinimumWithdrawAmountMsats, + selectPaymentFederationBalance, selectShowFiatTxnAmounts, - selectMaxStableBalanceSats, selectStableBalanceSats, - selectPayFromFederationBalance, + selectWithdrawableStableBalanceMsats, + setAmountInputType, } from '../redux' import { Btc, + EcashRequest, Invoice, MSats, ParsedBip21, @@ -31,7 +33,6 @@ import { SupportedCurrency, UsdCents, } from '../types' -import { EcashRequest } from '../types' import amountUtils from '../utils/AmountUtils' import { getFederationDefaultCurrency } from '../utils/FederationUtils' import stringUtils from '../utils/StringUtils' @@ -49,6 +50,7 @@ interface SendAmountArgs { bip21Payment?: ParsedBip21['data'] | null invoice?: Invoice | null lnurlPayment?: ParsedLnurlPay['data'] | null + selectedPaymentFederation?: boolean } export type FormattedAmounts = { @@ -72,6 +74,7 @@ export type NumpadButtonValue = (typeof numpadButtons)[number] export const useBtcFiatPrice = () => { const selectedFiatCurrency = useCommonSelector(selectCurrency) + const currencyLocale = useCommonSelector(selectCurrencyLocale) const exchangeRate: number = useCommonSelector(selectBtcExchangeRate) const btcUsdExchangeRate: number = useCommonSelector( selectBtcUsdExchangeRate, @@ -87,9 +90,15 @@ export const useBtcFiatPrice = () => { ) return amountUtils.formatFiat(amount, selectedFiatCurrency, { symbolPosition, + locale: currencyLocale, }) }, - [btcUsdExchangeRate, exchangeRate, selectedFiatCurrency], + [ + btcUsdExchangeRate, + currencyLocale, + exchangeRate, + selectedFiatCurrency, + ], ), convertSatsToFiat: useCallback( (sats: Sats) => { @@ -102,18 +111,20 @@ export const useBtcFiatPrice = () => { const amount = amountUtils.satToFiat(sats, exchangeRate) return amountUtils.formatFiat(amount, selectedFiatCurrency, { symbolPosition, + locale: currencyLocale, }) }, - [exchangeRate, selectedFiatCurrency], + [exchangeRate, selectedFiatCurrency, currencyLocale], ), convertSatsToFormattedUsd: useCallback( (sats: Sats, symbolPosition: AmountSymbolPosition = 'end') => { const amount = amountUtils.satToFiat(sats, btcUsdExchangeRate) return amountUtils.formatFiat(amount, SupportedCurrency.USD, { symbolPosition, + locale: currencyLocale, }) }, - [btcUsdExchangeRate], + [btcUsdExchangeRate, currencyLocale], ), } } @@ -210,6 +221,7 @@ export function useAmountInput( const btcToFiatRate = useCommonSelector(selectBtcExchangeRate) const btcToFiatRateRef = useUpdatingRef(btcToFiatRate) const currency = useCommonSelector(selectCurrency) + const currencyLocale = useCommonSelector(selectCurrencyLocale) const federationMetadata = useCommonSelector(selectFederationMetadata) const defaultAmountInputType = useCommonSelector(selectAmountInputType) @@ -228,7 +240,7 @@ export function useAmountInput( amountUtils.formatFiat( amountUtils.satToFiat(amount, btcToFiatRate), currency, - { symbolPosition: 'none' }, + { symbolPosition: 'none', locale: currencyLocale }, ), ) @@ -248,7 +260,9 @@ export function useAmountInput( const handleChangeSats = useCallback( (value: string) => { // can be 1,000 or 1.000 or 1 000 - const thousandsSeparator = amountUtils.getThousandsSeparator() + const thousandsSeparator = amountUtils.getThousandsSeparator({ + locale: currencyLocale, + }) // replacing periods requires a special regex let escapeSeparator = thousandsSeparator if (thousandsSeparator === '.') { @@ -262,22 +276,29 @@ export function useAmountInput( setFiatValue( amountUtils.formatFiat(fiat, currency, { symbolPosition: 'none', + locale: currencyLocale, }), ) }, - [clampSats, onChangeAmount, currency, btcToFiatRateRef], + [currencyLocale, clampSats, btcToFiatRateRef, onChangeAmount, currency], ) const handleChangeFiat = useCallback( (value: string) => { - let fiat = amountUtils.parseFiatString(value) + let fiat = amountUtils.parseFiatString(value, { + locale: currencyLocale, + }) if (Number.isNaN(fiat) || fiat < 0) { fiat = 0 } // If they've added or removed a sigdig, offset all numbers by a tens place - const decimals = amountUtils.getCurrencyDecimals(currency) - const decimalSeparator = amountUtils.getDecimalSeparator() + const decimals = amountUtils.getCurrencyDecimals(currency, { + locale: currencyLocale, + }) + const decimalSeparator = amountUtils.getDecimalSeparator({ + locale: currencyLocale, + }) const valueDecimals = value.split(decimalSeparator)[1]?.length || 0 if (valueDecimals > decimals) { fiat = fiat * 10 @@ -322,11 +343,13 @@ export function useAmountInput( setFiatValue( amountUtils.formatFiat(fiat, currency, { symbolPosition: 'none', + locale: currencyLocale, }), ) setSatsValue(amountUtils.formatSats(sats)) }, [ + currencyLocale, currency, clampSats, btcToFiatRateRef, @@ -389,6 +412,7 @@ export function useAmountInput( handleChangeSats, currency, currencySymbol, + currencyLocale, numpadButtons, handleNumpadPress, validation, @@ -460,15 +484,16 @@ export function useMinMaxRequestAmount({ * Get the minimum and maximum amount you can send. Optionally take in an * LNURL pay request as part of the calculation. */ -export function useMinMaxSendAmount( - { invoice, lnurlPayment }: SendAmountArgs = {}, +export function useMinMaxSendAmount({ + invoice, + lnurlPayment, // TODO: Remove this option in favor of always using payFromFederation once // https://github.com/fedibtc/fedi/issues/4070 is finished - usePayFromFederationBalance = false, -) { + selectedPaymentFederation, +}: SendAmountArgs = {}) { const balance = useCommonSelector(s => - usePayFromFederationBalance - ? selectPayFromFederationBalance(s) + selectedPaymentFederation + ? selectPaymentFederationBalance(s) : selectFederationBalance(s), ) @@ -531,9 +556,9 @@ export function useMinMaxDepositAmount() { maxStableBalanceSats === 0 ? balanceSats : (Math.min( - balanceSats, - Math.max(0, maxStableBalanceSats - stableBalanceSats), - ) as Sats) + balanceSats, + Math.max(0, maxStableBalanceSats - stableBalanceSats), + ) as Sats) return { minimumAmount, maximumAmount } } @@ -563,7 +588,7 @@ export function useRequestForm(args: RequestAmountArgs = {}) { args.lnurlWithdrawal && args.lnurlWithdrawal.minWithdrawable && args.lnurlWithdrawal.minWithdrawable === - args.lnurlWithdrawal.maxWithdrawable + args.lnurlWithdrawal.maxWithdrawable ) { exactAmount = amountUtils.msatToSat( args.lnurlWithdrawal.minWithdrawable, @@ -637,11 +662,13 @@ export function useSendForm({ bip21Payment, invoice, lnurlPayment, + selectedPaymentFederation, }: SendAmountArgs = {}) { const [inputAmount, setInputAmount] = useState(0 as Sats) const { minimumAmount, maximumAmount } = useMinMaxSendAmount({ invoice, lnurlPayment, + selectedPaymentFederation, }) const minimumAmountRef = useUpdatingRef(minimumAmount) diff --git a/ui/common/hooks/chat.ts b/ui/common/hooks/chat.ts index a3df5e3..e035e5c 100644 --- a/ui/common/hooks/chat.ts +++ b/ui/common/hooks/chat.ts @@ -1,42 +1,36 @@ import { TFunction } from 'i18next' -import { useState, useMemo, useEffect, useCallback } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import { useSelector } from 'react-redux' -import type { ChatMember, ChatMessage, Sats } from '@fedi/common/types' +import type { ChatMember, Sats } from '@fedi/common/types' import { INVALID_NAME_PLACEHOLDER } from '../constants/matrix' import { configureMatrixPushNotifications, + previewDefaultGroupChats, selectActiveFederation, selectActiveFederationId, selectAuthenticatedMember, selectChatClientLastOnlineAt, selectChatClientStatus, - selectChatLastReadMessageTimestamps, selectChatLastSeenMessageTimestamp, selectChatMember, selectHasSetMatrixDisplayName, + selectIsMatrixReady, selectLatestChatMessageTimestamp, selectMatrixAuth, - selectPayFromFederation, + selectMatrixPushNotificationToken, + selectPaymentFederation, sendMatrixPaymentPush, sendMatrixPaymentRequest, - setLastReadMessageTimestamp, setLastSeenMessageTimestamp, setMatrixDisplayName, - selectMatrixPushNotificationToken, - selectIsMatrixReady, startMatrixClient, - previewDefaultGroupChats, } from '../redux' -import { - getDisplayNameValidator, - getLatestMessage, - parseData, -} from '../utils/chat' +import { getDisplayNameValidator, parseData } from '../utils/chat' import { FedimintBridge } from '../utils/fedimint' import { makeLog } from '../utils/log' -import { useMinMaxSendAmount, useMinMaxRequestAmount } from './amount' +import { useMinMaxRequestAmount, useMinMaxSendAmount } from './amount' import { useCommonDispatch, useCommonSelector } from './redux' import { useToast } from './toast' @@ -132,57 +126,6 @@ export function useUpdateLastMessageSeen(pauseUpdates?: boolean) { ]) } -/** - * Automatically dispatch an update to the last message read in a chat while a - * component using this hook is mounted. - * - * the pauseUpdates param is used by the native app since components remain - * mounted even when the screen is not in focus. the navigation library - * returns isFocused = false for any screen using this hook and we can pause it - * @deprecated XMPP legacy code - */ -export function useUpdateLastMessageRead( - chatId: string, - messages: ChatMessage[], - pauseUpdates?: boolean, -) { - const dispatch = useCommonDispatch() - const federationId = useCommonSelector(selectActiveFederation)?.id - const lastReadMessageTimestamps = useCommonSelector( - selectChatLastReadMessageTimestamps, - ) - const lastReadTimestampInChat = lastReadMessageTimestamps[chatId] - const latestMessageTimestamp = getLatestMessage(messages)?.sentAt - - useEffect(() => { - if (!federationId || !chatId || !latestMessageTimestamp || pauseUpdates) - return - - // don't dispatch if we already have the latest timestamp - if ( - lastReadTimestampInChat && - lastReadTimestampInChat >= latestMessageTimestamp - ) - return - - dispatch( - setLastReadMessageTimestamp({ - federationId, - chatId, - timestamp: latestMessageTimestamp, - }), - ) - }, [ - dispatch, - chatId, - federationId, - lastReadMessageTimestamps, - latestMessageTimestamp, - lastReadTimestampInChat, - pauseUpdates, - ]) -} - // This hook sets a given device token to be published to the Matrix Sygnal Push server // so it can process push notifications for timeline events export function usePublishNotificationToken( @@ -279,7 +222,7 @@ export const useChatPaymentPush = ( ) => { const toast = useToast() const dispatch = useCommonDispatch() - const payFromFederation = useCommonSelector(selectPayFromFederation) + const payFromFederation = useCommonSelector(selectPaymentFederation) const federationId = payFromFederation?.id || '' const [isProcessing, setIsProcessing] = useState(false) @@ -322,7 +265,7 @@ export const useChatPaymentUtils = ( const dispatch = useCommonDispatch() const activeFederationId = useCommonSelector(selectActiveFederationId) const [federationId] = useState(activeFederationId) - const sendMinMax = useMinMaxSendAmount({}, true) + const sendMinMax = useMinMaxSendAmount({ selectedPaymentFederation: true }) const requestMinMax = useMinMaxRequestAmount({ ecashRequest: {} }) const [amount, setAmount] = useState(0 as Sats) const [submitAction, setSubmitAction] = useState( @@ -335,8 +278,8 @@ export const useChatPaymentUtils = ( submitType === 'send' ? sendMinMax : submitType === 'request' - ? requestMinMax - : {} + ? requestMinMax + : {} const canRequestAmount = amount >= requestMinMax.minimumAmount && diff --git a/ui/common/hooks/federation.ts b/ui/common/hooks/federation.ts index f681a8d..fe76a2f 100644 --- a/ui/common/hooks/federation.ts +++ b/ui/common/hooks/federation.ts @@ -17,17 +17,17 @@ import { import { ClientConfigMetadata, Federation, JoinPreview } from '../types' import dateUtils from '../utils/DateUtils' import { - shouldShowOfflineWallet, - shouldShowSocialRecovery, - shouldShowInviteCode, - shouldEnableOnchainDeposits, - shouldEnableNostr, + fetchPublicFederations, getFederationChatServerDomain, getFederationPopupInfo, - shouldEnableStabilityPool, - shouldEnableFediInternalInjection, - fetchPublicFederations, previewInvite, + shouldEnableFediInternalInjection, + shouldEnableNostr, + shouldEnableOnchainDeposits, + shouldEnableStabilityPool, + shouldShowInviteCode, + shouldShowOfflineWallet, + shouldShowSocialRecovery, } from '../utils/FederationUtils' import { FedimintBridge } from '../utils/fedimint' import { useCommonDispatch, useCommonSelector } from './redux' @@ -274,7 +274,7 @@ export function useFederationPreview( ) const handleJoin = useCallback( - async (onSuccess?: () => void) => { + async (onSuccess?: () => void, recoverFromScratch = false) => { setIsJoining(true) try { if (!federationPreview) throw new Error() @@ -282,6 +282,7 @@ export function useFederationPreview( joinFederation({ fedimint, code: federationPreview.inviteCode, + recoverFromScratch, }), ).unwrap() onSuccess && onSuccess() diff --git a/ui/common/hooks/matrix.ts b/ui/common/hooks/matrix.ts index 9ceb497..e36b253 100644 --- a/ui/common/hooks/matrix.ts +++ b/ui/common/hooks/matrix.ts @@ -4,11 +4,14 @@ import { useCallback, useEffect, useRef, useState } from 'react' import { acceptMatrixPaymentRequest, cancelMatrixPayment, + joinMatrixRoom, observeMatrixRoom, rejectMatrixPaymentRequest, searchMatrixUsers, - selectIsMatrixReady, selectCanClaimPayment, + selectCanPayFromOtherFeds, + selectCanSendPayment, + selectIsMatrixReady, selectLatestMatrixRoomEventId, selectMatrixAuth, selectMatrixRoom, @@ -16,9 +19,6 @@ import { selectMatrixUser, sendMatrixReadReceipt, unobserveMatrixRoom, - selectCanSendPayment, - selectCanPayFromOtherFeds, - joinMatrixRoom, } from '../redux' import { MatrixPaymentEvent, diff --git a/ui/common/hooks/pay.ts b/ui/common/hooks/pay.ts index dfee4b3..febb269 100644 --- a/ui/common/hooks/pay.ts +++ b/ui/common/hooks/pay.ts @@ -66,6 +66,7 @@ interface OmniPaymentState { export function useOmniPaymentState( fedimint: FedimintBridge, federationId: string | undefined, + selectedPaymentFederation = false, ): OmniPaymentState { const [feeDetails, setFeeDetails] = useState() const [invoice, setInvoice] = useState() @@ -80,7 +81,9 @@ export function useOmniPaymentState( maximumAmount, description, sendTo, - } = useSendForm({ btcAddress, bip21Payment, invoice, lnurlPayment }) + } = useSendForm( + { btcAddress, bip21Payment, invoice, lnurlPayment, selectedPaymentFederation }, + ) useEffect(() => { const getOnchainFeeDetails = async () => { diff --git a/ui/common/hooks/recovery.ts b/ui/common/hooks/recovery.ts index 5d6f62b..ed08c89 100644 --- a/ui/common/hooks/recovery.ts +++ b/ui/common/hooks/recovery.ts @@ -3,19 +3,19 @@ import orderBy from 'lodash/orderBy' import { useCallback, useEffect, useMemo, useState } from 'react' import { - fetchSocialRecovery as reduxFetchSocialRecovery, - completeSocialRecovery as reduxCompleteSocialRecovery, + createNewWallet, + recoverFromMnemonic, cancelSocialRecovery as reduxCancelSocialRecovery, + completeSocialRecovery as reduxCompleteSocialRecovery, + fetchSocialRecovery as reduxFetchSocialRecovery, refreshSocialRecoveryState, selectHasCheckedForSocialRecovery, + selectHasSetMatrixDisplayName, + selectRegisteredDevices, selectSocialRecoveryQr, selectSocialRecoveryState, - recoverFromMnemonic, - selectRegisteredDevices, - transferExistingWallet, - createNewWallet, startMatrixClient, - selectHasSetMatrixDisplayName, + transferExistingWallet, } from '../redux' import { SeedWords } from '../types' import { RpcRegisteredDevice } from '../types/bindings' diff --git a/ui/common/hooks/redux.ts b/ui/common/hooks/redux.ts index 589aee0..7d70962 100644 --- a/ui/common/hooks/redux.ts +++ b/ui/common/hooks/redux.ts @@ -1,4 +1,4 @@ -import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux' +import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' import { CommonDispatch, CommonState } from '../redux' diff --git a/ui/common/hooks/toast.ts b/ui/common/hooks/toast.ts index a2b5c8c..835cefc 100644 --- a/ui/common/hooks/toast.ts +++ b/ui/common/hooks/toast.ts @@ -2,8 +2,8 @@ import { TFunction } from 'i18next' import { useCallback, useMemo } from 'react' import { - showToast as reduxShowToast, closeToast as reduxCloseToast, + showToast as reduxShowToast, } from '@fedi/common/redux' import { ToastArgs } from '@fedi/common/types' import { formatErrorMessage } from '@fedi/common/utils/format' diff --git a/ui/common/hooks/transactions.ts b/ui/common/hooks/transactions.ts index 898eaa2..53d44f6 100644 --- a/ui/common/hooks/transactions.ts +++ b/ui/common/hooks/transactions.ts @@ -2,27 +2,28 @@ import { TFunction } from 'i18next' import { useCallback } from 'react' import { + makeStabilityTxnAmountText as makeStabilityTxnAmountTextUtil, + makeStabilityTxnDetailItems as makeStabilityTxnDetailItemsUtil, + makeStabilityTxnFeeDetails as makeStabilityTxnFeeDetailsUtil, makeTxnAmountText as makeTxnAmountTextUtil, makeTxnDetailItems as makeTxnDetailItemsUtil, makeTxnFeeDetails as makeTxnFeeDetailsUtil, makeTxnNotesText as makeTxnNotesTextUtil, - makeStabilityTxnAmountText as makeStabilityTxnAmountTextUtil, - makeStabilityTxnDetailItems as makeStabilityTxnDetailItemsUtil, - makeStabilityTxnFeeDetails as makeStabilityTxnFeeDetailsUtil, } from '@fedi/common/utils/wallet' import { selectActiveFederationId, selectCurrency, selectEcashFeeSchedule, - selectMaximumAPR, + selectFederationStabilityPoolConfig, selectShowFiatTxnAmounts, + selectStabilityPoolAverageFeeRate, selectStabilityPoolFeeSchedule, } from '../redux' import { fetchTransactions as reduxFetchTransactions, - selectTransactionHistory, selectStabilityTransactionHistory, + selectTransactionHistory, } from '../redux/transactions' import { Federation, MSats, Sats, Transaction } from '../types' import { RpcFeeDetails } from '../types/bindings' @@ -217,42 +218,47 @@ export function useExportTransactions(fedimint: FedimintBridge) { const { fetchTransactions } = useTransactionHistory(fedimint) const { makeFormattedAmountsFromMSats } = useAmountFormatter() - const exportTransactions = useCallback(async (federation: Federation): Promise< - | { success: true; uri: string; fileName: string } - | { success: false; message: string } - > => { - let transactions: Array = [] - - try { - transactions = await fetchTransactions({ - // TODO: find a better way than a hardcoded value - limit: 10000, - }) - - const fileName = makeCSVFilename( - federation?.name - ? 'transactions-' + federation?.name - : 'transactions', - ) - const uri = makeBase64CSVUri( - makeTransactionHistoryCSV( - transactions, - makeFormattedAmountsFromMSats, - ), - ) - - return { - success: true, - uri, - fileName, - } - } catch (e) { - return { - success: false, - message: (e as Error).message, + const exportTransactions = useCallback( + async ( + federation: Federation, + ): Promise< + | { success: true; uri: string; fileName: string } + | { success: false; message: string } + > => { + let transactions: Array = [] + + try { + transactions = await fetchTransactions({ + // TODO: find a better way than a hardcoded value + limit: 10000, + }) + + const fileName = makeCSVFilename( + federation?.name + ? 'transactions-' + federation?.name + : 'transactions', + ) + const uri = makeBase64CSVUri( + makeTransactionHistoryCSV( + transactions, + makeFormattedAmountsFromMSats, + ), + ) + + return { + success: true, + uri, + fileName, + } + } catch (e) { + return { + success: false, + message: (e as Error).message, + } } - } - }, [fetchTransactions, makeFormattedAmountsFromMSats]) + }, + [fetchTransactions, makeFormattedAmountsFromMSats], + ) return exportTransactions } @@ -269,12 +275,15 @@ export type FeeItem = { // Ecash fees are ppm values specified in the federations feeSchedule so we calculate // the fee from the amount and provide all formatted UI display content export function useFeeDisplayUtils(t: TFunction) { - const maxFeeRate = useCommonSelector(selectMaximumAPR) const ecashFeeSchedule = useCommonSelector(selectEcashFeeSchedule) const stabilityPoolFeeSchedule = useCommonSelector( selectStabilityPoolFeeSchedule, ) + const stabilityPoolAverageFeeRate = useCommonSelector( + selectStabilityPoolAverageFeeRate, + ) const { makeFormattedAmountsFromMSats } = useAmountFormatter() + const stabilityConfig = useCommonSelector(selectFederationStabilityPoolConfig) const makeEcashFeeContent = (amount: MSats) => { let fediFee: MSats = 0 as MSats @@ -312,9 +321,8 @@ export function useFeeDisplayUtils(t: TFunction) { return { feeItemsBreakdown: ecashFeeItems, - formattedTotalFee: `${ - totalFees > 0 ? '+' : '' - }${formattedTotalFee}`, + formattedTotalFee: `${totalFees > 0 ? '+' : '' + }${formattedTotalFee}`, } } @@ -358,9 +366,8 @@ export function useFeeDisplayUtils(t: TFunction) { return { feeItemsBreakdown: lightningFeeItems, - formattedTotalFee: `${ - lightningSendTotalFeeMsats > 0 ? '+' : '' - }${formattedTotalFee}`, + formattedTotalFee: `${lightningSendTotalFeeMsats > 0 ? '+' : '' + }${formattedTotalFee}`, } } @@ -396,9 +403,8 @@ export function useFeeDisplayUtils(t: TFunction) { return { feeItemsBreakdown: lightningFeeItems, - formattedTotalFee: `${ - onchainSendTotalFeeMsats > 0 ? '+' : '' - }${formattedTotalFee}`, + formattedTotalFee: `${onchainSendTotalFeeMsats > 0 ? '+' : '' + }${formattedTotalFee}`, } } @@ -427,7 +433,18 @@ export function useFeeDisplayUtils(t: TFunction) { const { formattedPrimaryAmount: formattedTotalFee } = makeFormattedAmountsFromMSats(totalFees) - const ecashFeeItems: FeeItem[] = [ + const averageFeeRatePerCycle = stabilityPoolAverageFeeRate ?? 0 + // convert parts per billion to decimal + const periodicRate = averageFeeRatePerCycle / 1_000_000_000 + // Calculate cycles per year based on cycle_duration + seconds in 1 year + const secondsPerCycle = stabilityConfig?.cycle_duration.secs ?? 0 + const secondsInYear = 365 * 24 * 60 * 60 + const cyclesPerYear = secondsInYear / secondsPerCycle + const compoundedAnnualRate = + 1 - Math.pow(1 - periodicRate, cyclesPerYear) + const formattedFeeAverage = Number((compoundedAnnualRate * 100).toFixed(2)) + + const stabilityFeeItems: FeeItem[] = [ { label: t('phrases.fedi-fee'), formattedAmount: `${formattedFediFee} (${formattedFediFeeSecondary})`, @@ -437,14 +454,22 @@ export function useFeeDisplayUtils(t: TFunction) { formattedAmount: `${formattedFederationFee} (${formattedFederationFeeSecondary})`, }, { - label: `${t('phrases.yearly-fee')}*`, - formattedAmount: `${maxFeeRate}% max`, + label: stabilityPoolAverageFeeRate + ? `${t('phrases.yearly-fee')}*` + : t('words.fees'), + formattedAmount: + typeof stabilityPoolAverageFeeRate === 'number' + ? `${formattedFeeAverage}%` + : '-', }, ] return { - feeItemsBreakdown: ecashFeeItems, - formattedTotalFee: `${formattedTotalFee} + ${maxFeeRate}% yearly`, + feeItemsBreakdown: stabilityFeeItems, + formattedTotalFee: + formattedFeeAverage > 0 + ? `${formattedTotalFee} + ${formattedFeeAverage}% yearly` + : formattedTotalFee, } } diff --git a/ui/common/localization/am/common.json b/ui/common/localization/am/common.json index 48fdfba..5b45b1b 100644 --- a/ui/common/localization/am/common.json +++ b/ui/common/localization/am/common.json @@ -409,7 +409,7 @@ "payment-request": "የክፍያ ጥያቄ ከ {{fediMod}}", "stable-balance-enabled": "የተረጋጋ ሚዛን", "stable-balance-enabled-info": "ሳት ወደ የተረጋጋ ምንዛሬ የመቀየር ችሎታን ያስችላል", - "wants-to-pay-you": "{{fediMod}} ሊከፍልህ ይፈልጋል", + "wants-to-send-you": "{{fediMod}} ልከልከ ይፈልጋል", "wants-you-to-pay": "{{fediMod}} ሊከፍልህ ይፈልጋል", "your-mods": "የእርስዎ Mods" }, diff --git a/ui/common/localization/ar/common.json b/ui/common/localization/ar/common.json index 4a9482a..9cd46c3 100644 --- a/ui/common/localization/ar/common.json +++ b/ui/common/localization/ar/common.json @@ -408,7 +408,7 @@ "payment-request": "طلب الدفع من{{fediMod}}", "stable-balance-enabled": "توازن مستقر ", "stable-balance-enabled-info": "تمكن القدرة على تحويل مقاعد إلي عملة مستقرة. ", - "wants-to-pay-you": "{{fediMod}} يريد ان يدفع لك", + "wants-to-send-you": "{{fediMod}} يريد أن يرسل لك", "wants-you-to-pay": "{{fediMod}} يريد إن يدفع لك", "your-mods": "تعديلاتك " }, diff --git a/ui/common/localization/ara/common.json b/ui/common/localization/ara/common.json index fbc38ea..2801f09 100644 --- a/ui/common/localization/ara/common.json +++ b/ui/common/localization/ara/common.json @@ -409,7 +409,7 @@ "payment-request": "Talabu ta dafa sagit {{fediMod}}", "stable-balance-enabled": "Bagi taki fi mahal to", "stable-balance-enabled-info": "Gadir ashan bi kati sats ta omula al gowi", - "wants-to-pay-you": "{{fediMod}} der dafa inta", + "wants-to-send-you": "{{fediMod}} der dafa inta", "wants-you-to-pay": "{{fediMod}} der dafa inta", "your-mods": "Mods taki" }, diff --git a/ui/common/localization/en/common.json b/ui/common/localization/en/common.json index 5ab2897..1e1888e 100644 --- a/ui/common/localization/en/common.json +++ b/ui/common/localization/en/common.json @@ -360,6 +360,8 @@ "invite-to-group": "Invite to group", "join-a-group": "Join a group", "join-group": "Join group", + "leave-chat": "Leave chat", + "leave-chat-confirmation": "Are you sure you want to leave this chat? All message history will be lost.", "leave-group": "Leave group", "leave-group-confirmation": "Are you sure you want to leave the group? All group message history will be lost.", "member-not-found": "Could not find a member with the username '{{username}}'", @@ -427,7 +429,7 @@ "community": { "add-community": "Add community", "join-a-community": "Join a community", - "join-community-guidance": "Join your favorite community or community to access money and more", + "join-community-guidance": "Join your favorite community to access money and more", "or-visit-awesome-fedimint": "or Visit Awesome Fedimint" }, "developer": { @@ -461,6 +463,8 @@ "leave-federation-withdraw-stable-first": "You must withdraw your entire {{currency}} balance before leaving.", "paste-federation-code": "Paste community code", "paste-federation-code-instead": "Paste community code instead", + "recover-from-scratch": "Recover from scratch", + "recover-from-scratch-warning": "Warning: This takes a long time. You should NOT select this option unless instructed by Fedi support.", "scan-federation-invite": "Scan a Community Invite" }, "fedimods": { @@ -481,7 +485,7 @@ "payment-request": "Payment request from {{fediMod}}", "stable-balance-enabled": "Stable Balance", "stable-balance-enabled-info": "Enables ability to convert sats to stable currency", - "wants-to-pay-you": "{{fediMod}} wants to pay you", + "wants-to-send-you": "{{fediMod}} wants to send you", "wants-you-to-pay": "{{fediMod}} wants you to pay", "your-mods": "Your Mods" }, @@ -635,6 +639,7 @@ "join-to-receive": "Join {{federation}} to receive", "maximum-invoice-amount": "Maximum invoice amount is {{maxAmount}} SATS", "onchain-notice": "On-chain deposits take ~10 hours to confirm. Use Lightning for instant transactions", + "onchain-expert-only": "For your safety: Keep the transaction size under 40 kB and DO NOT reuse this address in the future. This will help prevent any potential issues with your deposit.", "other-methods": "Other methods", "pending-transaction": "pending transaction", "receive-amount-unit": "Receive {{amount}} {{unit}}", @@ -748,7 +753,6 @@ "offline-send-warning": "On the next step, when the QR is presented, the sats will be removed from your wallet", "paste-payment-request": "Paste payment request", "paste-payment-request-instead": "Paste payment request instead", - "refund-in-block": "Refund in block {{block}}", "scan-qr-code": "Scan a Lightning QR Code", "send-amount-unit": "Send {{amount}} {{unit}}", "send-bitcoin": "Send bitcoin", @@ -758,6 +762,7 @@ "send-sats": "Send {{amount}} SATS", "send-to": "Send to", "send-to-offline-user": "Send to an offline user", + "waiting-for-refund": "Waiting for refund", "you-are-sending": "You are sending", "you-are-sending-amount-unit": "You are sending {{amount}} {{unit}}", "you-sent": "You sent", diff --git a/ui/common/localization/es/common.json b/ui/common/localization/es/common.json index 574844c..0dc081c 100644 --- a/ui/common/localization/es/common.json +++ b/ui/common/localization/es/common.json @@ -411,7 +411,7 @@ "community": { "add-community": "Agregar comunidad", "join-a-community": "Únete a una comunidad", - "join-community-guidance": "Únase a su comunidad o federación favorita para acceder a dinero y más", + "join-community-guidance": "Únase a su comunidad favorita para acceder a dinero y más", "or-visit-awesome-fedimint": "o visita Awesome Fedimint" }, "developer": { @@ -462,7 +462,7 @@ "payment-request": "Solicitud de pago de {{fediMod}}", "stable-balance-enabled": "Saldo estable", "stable-balance-enabled-info": "Permite la capacidad de convertir sats en moneda estable", - "wants-to-pay-you": "{{fedimod}} quiere pagarte", + "wants-to-send-you": "{{fediMod}} quiere enviarte", "wants-you-to-pay": "{{fediMod}} quiere que pagues", "your-mods": "Tus modificaciones" }, diff --git a/ui/common/localization/fr/common.json b/ui/common/localization/fr/common.json index 9157f5b..d52013e 100644 --- a/ui/common/localization/fr/common.json +++ b/ui/common/localization/fr/common.json @@ -411,7 +411,7 @@ "community": { "add-community": "Ajouter une communauté", "join-a-community": "Rejoignez une communauté", - "join-community-guidance": "Rejoignez votre communauté ou fédération préférée pour accéder à de l'argent et bien plus encore", + "join-community-guidance": "Rejoignez votre communauté préférée pour accéder à de l'argent et bien plus encore", "or-visit-awesome-fedimint": "ou visitez Awesome Fedimint" }, "developer": { @@ -462,7 +462,7 @@ "payment-request": "Demande de paiement de {{fedimod}}", "stable-balance-enabled": "Solde stable", "stable-balance-enabled-info": "Permet de convertir des sats en monnaie stable", - "wants-to-pay-you": "{{fedimod}} souhaite vous payer", + "wants-to-send-you": "{{fediMod}} veut vous envoyer", "wants-you-to-pay": "{{fediMod}} veut que vous payiez", "your-mods": "Vos modules" }, diff --git a/ui/common/localization/id/common.json b/ui/common/localization/id/common.json index 8039b74..0bf03fb 100644 --- a/ui/common/localization/id/common.json +++ b/ui/common/localization/id/common.json @@ -411,7 +411,7 @@ "community": { "add-community": "Tambahkan komunitas", "join-a-community": "Bergabunglah dengan komunitas", - "join-community-guidance": "Bergabunglah dengan komunitas atau federasi favorit Anda untuk mengakses uang dan banyak lagi", + "join-community-guidance": "Bergabunglah dengan komunitas favorit Anda untuk mengakses uang dan banyak lagi", "or-visit-awesome-fedimint": "atau Kunjungi Fedimint yang Luar Biasa" }, "developer": { @@ -462,7 +462,7 @@ "payment-request": "Permintaan pembayaran dari {{fediMod}}", "stable-balance-enabled": "Saldo Stabil", "stable-balance-enabled-info": "Memungkinkan kemampuan untuk mengkonversi sats ke mata uang stabil", - "wants-to-pay-you": "{{fediMod}} ingin membayar kamu", + "wants-to-send-you": "{{fediMod}} ingin mengirimkan Anda", "wants-you-to-pay": "{{fediMod}} ingin Anda membayar", "your-mods": "Modifikasi Anda" }, diff --git a/ui/common/localization/index.ts b/ui/common/localization/index.ts index 0cef27e..aea06e1 100644 --- a/ui/common/localization/index.ts +++ b/ui/common/localization/index.ts @@ -10,6 +10,7 @@ import commonRN from './rn/common.json' import commonRW from './rw/common.json' import commonSO from './so/common.json' import commonSW from './sw/common.json' +import commonTL from './tl/common.json' export const resources = { en: { @@ -27,6 +28,9 @@ export const resources = { pt: { translation: commonPT, }, + tl: { + translation: commonTL, + }, ar: { translation: commonAR, }, diff --git a/ui/common/localization/pt/common.json b/ui/common/localization/pt/common.json index 379992b..1dbdf37 100644 --- a/ui/common/localization/pt/common.json +++ b/ui/common/localization/pt/common.json @@ -411,7 +411,7 @@ "community": { "add-community": "Adicionar comunidade", "join-a-community": "Junte-se a uma comunidade", - "join-community-guidance": "Junte-se à sua comunidade ou federação favorita para ter acesso a dinheiro e muito mais", + "join-community-guidance": "Junte-se à sua comunidade favorita para ter acesso a dinheiro e muito mais", "or-visit-awesome-fedimint": "ou visite o incrível Fedimint" }, "developer": { @@ -462,7 +462,7 @@ "payment-request": "Pedido de pagamento de {{fediMod}}", "stable-balance-enabled": "Saldo Estável", "stable-balance-enabled-info": "Permite a capacidade de converter sats em moeda estável", - "wants-to-pay-you": "{{fediMod}} quer pagar-lhe", + "wants-to-send-you": "{{fediMod}} deseja enviar-lhe", "wants-you-to-pay": "{{fediMod}} quer que pague", "your-mods": "Os seus Mods" }, diff --git a/ui/common/localization/rn/common.json b/ui/common/localization/rn/common.json index 42703ac..ce8bee2 100644 --- a/ui/common/localization/rn/common.json +++ b/ui/common/localization/rn/common.json @@ -409,7 +409,7 @@ "payment-request": "Icipfuzo co Kwishura kuvuye kuri {{fediMod}}", "stable-balance-enabled": "Amafaranga asigaye arakwiye", "stable-balance-enabled-info": "Gushobora guhindura sats mu mafaranga ahamye ", - "wants-to-pay-you": "{{fediMod}} ishaka kukuriha", + "wants-to-send-you": "{{fediMod}} ishaka kuvuga wewe", "wants-you-to-pay": "{{fediMod}} ishaka ko uriha", "your-mods": "Mods zawe" }, diff --git a/ui/common/localization/rw/common.json b/ui/common/localization/rw/common.json index d936a71..9d309fa 100644 --- a/ui/common/localization/rw/common.json +++ b/ui/common/localization/rw/common.json @@ -408,7 +408,7 @@ "payment-request": "Ukwishyura kwasabwe na {{fediMod}}", "stable-balance-enabled": "Ikinyuranyo gihamye", "stable-balance-enabled-info": "Iha ububasha bwo guhindura SATS mu ifaranga rihamye", - "wants-to-pay-you": "{{fediMod}} ishaka kukwishyura", + "wants-to-send-you": "{{fediMod}} ishaka kuvuga wewe", "wants-you-to-pay": "{{fediMod}} ishaka ko wishyura", "your-mods": "Mods yawe" }, diff --git a/ui/common/localization/so/common.json b/ui/common/localization/so/common.json index 9aa0731..701916c 100644 --- a/ui/common/localization/so/common.json +++ b/ui/common/localization/so/common.json @@ -408,7 +408,7 @@ "payment-request": "Foomka codsiga lacag_bixinta {{fediMod}}", "stable-balance-enabled": "Dheellitirnaan deggan", "stable-balance-enabled-info": "Wuxu uu awood u leeyahay in uu sats u beddelo lacag deggan", - "wants-to-pay-you": "{{fediMod}} wuxu raba inu lacag ku siiyo", + "wants-to-send-you": "{{fediMod}} wuxuu rabaa inuu ku soo diro", "wants-you-to-pay": "{{fediMod}} wuxu raba in aad lacag bixiso ", "your-mods": "Hababkaaga" }, diff --git a/ui/common/localization/sw/common.json b/ui/common/localization/sw/common.json index 21bcbf1..bc21953 100644 --- a/ui/common/localization/sw/common.json +++ b/ui/common/localization/sw/common.json @@ -391,7 +391,7 @@ "payment-request": "Ombi ya malipo kutoka kwa {{fediMod}}", "stable-balance-enabled": "Solde stable", "stable-balance-enabled-info": "Inawezesha uwezo ya kubadilisha sats kuwa makuta stable", - "wants-to-pay-you": "{{fediMod}} inataka kukulipa", + "wants-to-send-you": "{{fediMod}} inataka kukutumia", "wants-you-to-pay": "{{fediMod}} inataka ulipe", "your-mods": "Mods zako" }, diff --git a/ui/common/localization/tl/common.json b/ui/common/localization/tl/common.json new file mode 100644 index 0000000..ad62758 --- /dev/null +++ b/ui/common/localization/tl/common.json @@ -0,0 +1,724 @@ +{ + "words": { + "accept": "Tanggapin", + "actions": "Mga Aksyon", + "address": "Address", + "admin": "Admin", + "amount": "Halaga", + "approved": "Aprubado", + "authorize": "Pahintulutan", + "backup": "Backup", + "balance": "Balanse", + "bitcoin": "Bitcoin", + "cancel": "Kansela", + "canceled": "Nakansela", + "chat": "Chat", + "community": "Komunidad", + "complete": "Kumpleto", + "confirm": "Kumpirmahin", + "confirmed": "Nakumpirma/ kumpirmado", + "continue": "Magpatuloy/ ipagpatuloy", + "copy": "Kopya", + "currency": "Pera/ pambansang pera", + "deposit": "Deposito", + "details": "Mga Detalye", + "done": "Tapos na", + "email": "Email", + "enjoy": "Maging masaya", + "error": "Mali", + "expired": "Paso", + "failed": "Pumalya", + "federation": "Pederasyon", + "federations": "Mga Pederasyon", + "fedimint": "Fedimint", + "fedimods": "FediMods", + "fee": "Bayad", + "fees": "Mga Bayad", + "from": "Mula sa", + "general": "Pangkalahatan", + "group": "Grupo", + "history": "Kasaysayan", + "home": "Home", + "icon": "Simbolo", + "important": "Mahalaga/ importante", + "invite": "Imbitasyon", + "invited": "Inimbitahan/ imbitado", + "join": "Pagsali", + "joined": "Sumali", + "language": "Wika", + "leave": "Umalis/ pag-alis", + "lightning": "Lightning/ kidlat", + "member": "Miyembro", + "members": "Mga Miyembro", + "memo": "Memo", + "message": "Mensahe", + "messages": "Mga Mensahe", + "moderator": "Tagapamagitan", + "next": "Susunod/ kasunod", + "no": "Hindi", + "nostr": "Nostr", + "notes": "Mga isinulat", + "okay": "OK", + "onchain": "On-chain", + "one": "Isa", + "optional": "Opsyonal", + "paid": "Bayad na/ nakapagbayad", + "pay": "Magbayad", + "payments": "Mga Bayad", + "pending": "Nakabinbin", + "people": "Mga Tao", + "receive": "Tanggap/ tumatanggap", + "received": "Nakatanggap", + "receiving": "Pagtanggap", + "refund": "Balik bayad", + "reject": "Tanggihan/ pagtanggi", + "rejected": "Tinanggihan", + "remaining": "natitira", + "request": "Humingi/ hiling", + "required": "Correct", + "retry": "Subukang Muli/ ulitin", + "sats": "sats", + "save": "I-save", + "scan": "I-scan", + "seen": "Nakita", + "send": "Ipadala", + "sent": "Naipadala", + "settings": "Mga Setting", + "share": "Ibahagi/ bahagi", + "skip": "Laktawan/ laktaw", + "status": "Katayuan", + "stay": "Manatili", + "submit": "Ipasa/ isumite", + "time": "Oras", + "title": "Pamagat", + "to": "Correct", + "transactions": "Mga transaksyon", + "two": "dalawa", + "unknown": "Hindi kilala/ hindi alam", + "unsupported": "Hindi suportado", + "upload": "I-upload", + "url": "url", + "URL": "URL", + "username": "Username", + "wallet": "Wallet", + "withdraw": "Mag-withdraw", + "withdrawal": "Pag-withdraw", + "yes": "Oo", + "you": "Ikaw" + }, + "phrases": { + "add-note": "Magdagdag ng tala/ magsulat", + "allow-camera-access": "Pahintulutan ang pag-access sa camera", + "app-settings-security": "Mga setting ng app at seguridad", + "app-version": "Fedi Bravo Version: {{version}}", + "back-to-app": "Bumalik sa app", + "backup-your-wallet": "Bitcoin address", + "bitcoin-address": "Bitcoin address", + "bitcoin-address-created": "Nalikha ang Bitcoin address", + "bitcoin-equivalent": "Katumbas ng Bitcoin", + "camera-settings": "Mga setting ng camera", + "changes-may-not-be-saved": "Maaaring hindi masave ang mga pagbabagong ginawa mo", + "click-for-more-details": "Correct", + "connect-to-federation": "Kumonekta sa test federation", + "copied-bitcoin-address": "Nakopya ang bitcoin address", + "copied-ecash-token": "Nakopya ang ecash token", + "copied-lightning-request": "Nakopya ang lightning request", + "copied-member-code": "Nakopya ang Fedi member code", + "copied-to-clipboard": "Nakopya sa clipboard", + "copied-transaction-id": "Nakopya ang transaction ID", + "display-currency": "Ipakita ang pera/ ipkaita ang pambansang pera", + "edit-note": "I-edit ang Notes/ baguhin ang mga sinulat", + "email-address": "Email address", + "expires-in": "Mag-e-expire sa", + "failed-to-decode-invoice": "Hindi nadecode ang invoice", + "federation-fee": "Bayad sa pederasyon", + "fedi-fee": "Bayad sa Fedi", + "fee-details": "Mga detalye ng bayad", + "generate-invoice": "Bumuo ng invoice", + "go-back": "Bumalik", + "hide-details": "Itago ang mga detalye", + "hold-to-confirm": "Pindutin nang matagal para kumpirmahin", + "i-understand": "Naiintindihan ko", + "invalid-federation-code": "Hindi wastong code ng pederasyon", + "join-another-federation": "Sumali sa ibang pederasyon", + "last-seen": "Huling nakita", + "lightning-address": "Lightning address", + "lightning-network": "Lightning Network", + "lightning-request": "Lightning request", + "network-fee": "Bayad sa network", + "new-member": "Bagong miyembro", + "no-transactions": "Walang mga transaksyon", + "onchain-address": "On-chain address", + "open-in-browser": "Buksan sa browser", + "paste-from-clipboard": "I-paste mula sa clipboard", + "please-confirm": "Paki-kumpirma", + "receive-pending": "Naghihintay ng pagtanggap", + "received-bitcoin": "Natanggap na bitcoin", + "refund-pending": "Naghihintay ng refund/ ang balik bayad ay nakabinbin", + "reload-app": "I-reload ang application", + "save-changes": "I-save ang mga pagbabago", + "sent-bitcoin": "Naipadalang bitcoin", + "start-over": "Magsimula muli", + "terms-and-conditions": "Mga Tuntunin at Kundisyon", + "transaction-id": "Transaction ID", + "transaction-received": "Natanggap na transaksyon", + "view-public-federations": "Tingnan ang mga pampublikong pederasyon", + "yearly-fee": "Taunang bayad", + "you-are-offline": "Ikaw ay kasalukuyang nasa offline mode" + }, + "errors": { + "bad-connection": "Ang iyong koneksyon sa network ay maaaring hindi matatag. Paki subukan muli mamaya o kumonekta sa ibang network.", + "browser-feature-not-supported": "Your browser does not support this feature. - Hindi sinusuportahan ng iyong browser ang tampok na ito.", + "camera-unavailable": "Nabigong makuha ang access sa iyong camera.", + "chat-connection-restoring": "Mahina o offline ang koneksyon sa chat. Sinusubukang ibalik...", + "chat-connection-unhealthy": "Mahina o offline ang koneksyon sa chat. Subukan muli mamaya o i-restart ang app.", + "chat-list-render-error": "Nakaranas ng error sa pag-render ng iyong mga chat", + "chat-member-not-found": "Hindi mahanap ang user na ito", + "chat-message-render-error": "Nakaranas ng error sa pag-render ng mensaheng ito", + "chat-payment-failed": "Hindi ma-update ang bayad sa chat na iyon", + "chat-unavailable": "Ang pederasyong ito ay walang chat server.", + "failed-to-fetch-gateways": "Hindi nakuha ang mga gateway", + "failed-to-fetch-guardian-approval": "Hindi nakuha ang approval ng guardian", + "failed-to-fetch-transactions": "Hindi nakuha ang mga transaksyon", + "failed-to-generate-invoice": "Hindi nabuo ng invoice", + "failed-to-join-federation": "Hindi nakasali sa pederasyon", + "failed-to-leave-federation": "Hindi nakaalis sa pederasyon", + "failed-to-load-tos": "Hindi na-load ang mga tuntunin ng serbisyo", + "failed-to-pay-invoice": "Hindi nabayaran ang invoice", + "failed-to-switch-gateways": "Hindi nakapag-palit ng mga gateway", + "get-nostr-pubkey-failed": "Hindi nakuha ang nostr pub key", + "history-render-error": "Nakaranas ng error sa pag-render ng item na ito", + "insufficient-balance": "Hindi sapat ang balanse. Meron ka nalang {{balance}} sa iyong wallet", + "invalid-amount-max": "Ang maximum na maari mong {{verb}} ay {{amount}}", + "invalid-amount-min": "Ang minimum na maari mong {{verb}} ay {{amount}}", + "invalid-ecash-token": "Hindi wastong ecash token", + "invalid-federation-code": "Hindi wastong code ng pederasyon", + "invalid-group-code": "Hindi ito wastong group code", + "invalid-username": "Dapat ay 21 character o mas kaunti at hindi maaaring maglaman ng mga uppercase na titik", + "no-lightning-gateways": "Walang natagpuang lightning gateways para sa user na ito", + "onchain-deposits-disabled": "Ang mga onchain deposit ay na-disable para sa pederasyong ito", + "only-group-owners-can-change-name": "Tanging mga may-ari ng grupo lamang ang maaaring magbago ng pangalan ng grupo", + "receive-ecash-failed": "Hindi natanggap ang ecash", + "receives-have-been-disabled": "Ang mga pagtanggap ay na-disable para sa pederasyong ito", + "unknown-error": "Nagkaroon ng hindi kilalang error", + "username-already-exists": "May gumagamit na ng username na ito. I-recover ang iyong wallet upang mabalik ang iyong username.", + "webln-canceled": "Nakanselang request", + "webln-method-not-supported": "{{method}} ay hindi suportado", + "webln-payment-rejected": "Tinanggihan ang bayad", + "webln-payment-request-rejected": "Tinanggihan ang request sa pagbabayad", + "you-have-already-joined": "Nakasali ka na sa pederasyong ito" + }, + "feature": { + "backup": { + "backup-social-recovery-file": "I-backup ang iyong social recovery file", + "backup-to-google-drive": "I-backup sa Google Drive", + "backup-wallet": "I-backup ang iyong wallet", + "backups-made": "Mga backup na ginawa", + "choose-method": "Pumili ng paraan ng backup", + "choose-method-instructions": "Ang pag-backup ng iyong wallet ay makakatulong sa iyong mabawi ang iyong pera kung mawawalan ka ng access sa Fedi", + "cloud-backup": "Cloud Backup", + "cloud-backup-instructions": "Gumawa ng backup ng iyong recovery file sa iyong cloud storage. Kailangan mo ring i-backup ang file na ito sa dalawang kaibigan o miyembro ng pamilya.", + "complete-social-backup": "Kumpletuhin ang social backup", + "confirm-backup-video": "Kumpirmahin ang backup video", + "creating-recovery-file": "Lumilikha ng naka-encrypt na recovery file...", + "export-transactions-to-csv": "I-export ang mga transaksyon sa CSV", + "file-backup": "File backup", + "hold-record-button": "Pindutin nang matagal ang record button at sabihin:", + "personal-backup": "Personal na backup", + "personal-backup-instructions": "sulat ang 12 recovery words. Ito ay para sa mga may karanasang miyembro.", + "please-review-backup-video": "Paki-review ang backup video", + "press-record-button": "Pindutin ang record button at sabihin:", + "record-again": "I-record muli", + "record-error": "Nakaranas ng error sa paggamit ng iyong camera", + "record-video": "I-record ang video", + "recovery-words": "Mga recovery words", + "recovery-words-instructions": "Isulat ang mga salitang ito gamit ang panulat at papel. Huwag i-save ang mga salitang ito sa digital na paraan sa iyong device.", + "review-face-confirmation": "Kinukumpirma ko na ang aking mukha ay malinaw na makikita sa video na ito", + "review-voice-confirmation": "Kinukumpirma ko na ang aking boses ay malinaw na maririnig sa video na ito", + "save-file": "I-save ang file", + "save-your-wallet-backup-file": "I-save ang iyong wallet backup file", + "save-your-wallet-backup-file-again": "I-save muli sa ibang lugar", + "social-backup": "Social backup", + "social-backup-instructions": "Mag-record ng video upang patunayan ang iyong pagkakakilanlan. Ang opsyong ito ay pinaka-mainam kung kilala mo nang mabuti ang iyong mga guardian.", + "social-backup-processing-info-1": "Ang recovery file na ito ay naglalaman ng iyong backup video at mga detalye tungkol sa iyong Pederasyon.", + "social-backup-video-prompt": "Fedi!", + "start-personal-backup": "Simulan ang personal na backup", + "start-personal-backup-instructions": "Kumuha ng panulat at papel at isulat ang mga recovery words sa susunod na screen.", + "start-recording": "Simulan ang pag-record", + "start-social-backup": "Simulan ang social backup", + "start-social-backup-instructions": "Ang mga social backup ay nagbibigay-daan sa iyo na ligtas na i-backup ang iyong wallet kasama ang mga kaibigan at pamilya at may mga tagapangalaga ng Pederasyon na tutulong sa iyong mabawi ito kung mawawalan ka ng access", + "stop-recording": "Itigil ang pag-record", + "successfully-backed-up": "Matagumpay mong na-backup ang iyong Fedi wallet" + }, + "bug": { + "description-label": "Ilarawan ang isyu nang detalyado", + "description-placeholder": "Correct", + "email-label": "Email (opsyonal)", + "info-label": "Ipadala ang Pederasyon at Username kasama ang bug report", + "log-disclaimer": "Ang mga application log ay isasama sa iyong ulat upang matulungan ang mga developer ng Fedi na masuri ang isyu", + "report-a-bug": "Iulat ang bug", + "screenshot-label": "Mag-upload ng mga screenshot o recording", + "submit-generating-data": "Lumilikha ng data ng ulat...", + "submit-submitting-report": "Isinusumite ang ulat...", + "submit-uploading-data": "Ina-upload ang data ng ulat...", + "success-subtitle": "Kami ay magsisimula na sa trabaho", + "success-title": "Salamat sa iyong bug report!" + }, + "chat": { + "add-admin": "Magdagdag ng Admin", + "add-an-avatar": "Magdagdag ng avatar", + "add-user-as-an-admin": "Idagdag si {{username}} bilang admin", + "added-admin-to-group": "Nadagdag si {{username}} bilang admin", + "admin-settings": "Mga setting ng admin", + "admin-settings-instructions": "Ang mga miyembrong ito ay maaaring magpadala ng mga mensahe sa mga broadcast only na grupo", + "broadcast-admin-instructions": "Ang mga miyembrong ito ay maaaring magpadala ng mga mensahe sa broadcast na grupo", + "broadcast-admin-settings": "Mga setting ng Broadcast Admin", + "broadcast-admins": "Mga Broadcast Admin", + "broadcast-no-message": "Wala pang ipinapadalang mensahe ang mga admin. Manatiling nakatutok.", + "broadcast-only": "Broadcast only", + "change-group-name": "Baguhin ang pangalan ng grupo", + "change-role": "Baguhin ang role", + "change-role-failure": "Hindi nabago ang role", + "change-role-success": "Matagumpay na nabago ang role", + "changing-broadcast-not-supported": "Ang pagbabago ng broadcast setting ay hindi pa suportado. Lumikha ng bagong grupo.", + "chat-invite": "Imbitasyon sa chat", + "click-to-join-group": "I-click upang sumali sa grupong ito", + "confirm-add-admin-to-group": "Sigurado ka bang gusto mong idagdag si {{username}} bilang admin? Makakapagpadala sila ng mensahe sa grupo na ito.", + "confirm-remove-admin-from-group": "Sigurado ka bang gusto mong tanggalin si {{username}} as an admin? They won't be able to send messages in this group but their previously sent messages will remain.", + "copied-group-invite-code": "Nakopya ang group invite code", + "create-a-display-name": "Lumikha ng display name", + "create-a-group": "Lumikha ng grupo", + "create-group": "Lumikha ng grupo", + "create-or-join-a-new-group": "Lumikha o sumali sa bagong grupo", + "disappearing-messages": "Nawawalang mga mensahe", + "display-name": "Display name", + "display-name-guidance": "Maaari mo itong baguhin mamaya", + "edit-group": "I-edit ang grupo", + "enter-a-username": "Maglagay ng username", + "enter-display-name": "Maglagay ng display name", + "fedi-community": "Komunidad ng Fedi", + "fedi-community-message-preview": "Maligayang pagdating sa Fedi! Ang channel na ito ay magbibigay-alam sa iyo tungkol sa mga kaganapan sa Fedi app", + "go-to-direct-chat": "Pumunta sa direktang chat", + "group-invite": "Imbitasyon sa grupo", + "group-name": "Pangalan ng grupo", + "group-not-found": "Walang natagpuang grupo", + "invalid-group": "Hindi ito valid na chat group", + "invalid-member": "Hindi ito valid na miyembro ng chat", + "invite-to-group": "Imbitahin sa grupo", + "join-a-group": "Sumali sa grupo", + "leave-group": "Umalis sa grupo", + "leave-group-confirmation": "Sigurado ka bang nais mong umalis sa grupo? Mawawala ang lahat ng kasaysayan ng mensahe ng grupo.", + "member-not-found": "Hindi matagpuan ang miyembro na may username na '{{username}}'", + "need-registration-description": "Itakda ang iyong display name upang makapagpadala at makatanggap kasama ang ibang mga gumagamit.", + "need-registration-title": "Maghanda nang mag-chat", + "new-chat": "Bagong chat", + "new-group": "Bagong grupo", + "new-message": "Bagong mensahe", + "new-messages": "Mga bagong mensahe", + "no-admins": "Wala pang broadcast admin", + "no-messages": "Wala pang nag-uusap sa kwartong ito.", + "no-one-is-in-this-group": "Wala pang miyembro sa kwartong ito.", + "no-users-found": "Walang natagpuang mga users", + "open-camera-scanner": "Buksan ang Camera Scanner", + "other-sent-payment": "Nagpadala si {{name}} ng {{recipient}} {{fiat}} ({{amount}}) {{memo}}", + "paid-by-name": "Binayaran ni {{name}}", + "paste-group-invite": "I-paste ang group invite", + "register-a-username": "Magrehistro ng username", + "removed-admin-from-group": "Tinanggal si {{username}} bilang admin", + "room-settings": "Mga setting ng kwarto", + "scan-chat-invite": "I-scan ang chat invite", + "scan-group-invite": "I-scan ang group invite", + "scan-member-code-notice": "Ipakita ang QR upang ibahagi ang iyong username", + "send-a-message-to": "Magpadala ng mensahe kay {{name}}", + "show-history-to-new-members": "Ipakita ang kasaysayan sa mga bagong miyembro", + "start-the-conversation": "Simulan ang pag-uusap", + "they-requested-payment": "Humiling si {{name}} ng {{fiat}} ({{amount}}) {{memo}}", + "they-sent-payment": "Nagpadala sa iyo si {{name}} ng {{fiat}} ({{amount}}) {{memo}}", + "try-inviting-someone": "Subukang imbitahin ang isang tao.", + "type-to-search-members": "Mag-type upang maghanap ng mga miyembro sa grupong ito", + "unknown-member": "Hindi kilalang miyembro", + "upgrade-chat": "I-upgrade ang chat", + "upgrade-chat-guidance": "Ginawa naming mas ligtas at magagamit ang Fedi chat para sa mga tao sa maraming komunidad", + "upgrade-chat-item-subtitle-1": "Makipag-usap sa kahit sino sa Fedi", + "upgrade-chat-item-subtitle-2": "Npubs para sa lahat", + "upgrade-chat-item-subtitle-3": "End to End", + "upgrade-chat-item-subtitle-4": "Magpadala at makatanggap ng bitcoin", + "upgrade-chat-item-subtitle-5": "Malapit na™", + "upgrade-chat-item-title-1": "Mga chat ng maraming komunidad", + "upgrade-chat-item-title-2": "Isang display name", + "upgrade-chat-item-title-3": "Encrypted na mga DM", + "upgrade-chat-item-title-4": "Madaling pagbabayad", + "upgrade-chat-item-title-5": "Marami pang parating!", + "view-group": "Tingnan ang grupo", + "view-shared-media": "Tingnan ang mga ibinahaging media", + "waiting-for-network": "Naghihintay sa network...", + "you-requested-payment": "Magrequest ka ng {{fiat}} ({{amount}}) {{memo}}", + "you-sent-payment": "Nagpadala ka ng {{fiat}} ({{amount}}) {{memo}}" + }, + "developer": { + "developer-mode-activated": "Ikaw ay isa nang developer!", + "developer-mode-deactivated": "Hindi ka na isang developer...", + "download-logs": "I-download ang mga log", + "export-transactions-csv": "I-export ang mga transaksyon CSV", + "logs": "Mga log", + "nightly": "Gabi-gabi", + "share-logs": "Ibahagi ang mga log", + "share-state": "Ibahagi ang estado ng app" + }, + "federations": { + "add-federation": "Magdagdag ng Pederasyon", + "copied-federation-invite": "Nakopya ang federation invite link", + "enter-federation-code": "Maglagay ng federation code", + "federation-details": "Mga Detalye ng Pederasyon", + "federation-invite": "Imbitasyon sa Pederasyon", + "federation-terms": "Mga Tuntunin ng Pederasyon", + "invite-members": "Imbitahan ang mga miyembro", + "join-federation": "Sumali sa bagong Pederasyon", + "leave-federation": "Umalis sa Pederasyon", + "leave-federation-confirmation": "Sigurado ka bang nais mong umalis sa pederasyong ito?", + "leave-federation-withdraw-first": "Kailangan mong i-withdraw ang iyong mga pondo bago umalis", + "leave-federation-withdraw-pending-stable-first": "Ang iyong {{currency}} withdrawal ay pinoproseso pa. Paki-subukan muli sa loob ng 10 minuto.", + "leave-federation-withdraw-stable-first": "Kailangan mong i-withdraw ang buong balanse ng {{currency}} bago umalis.", + "paste-federation-code": "I-paste ang federation code", + "scan-federation-invite": "I-scan ang Imbitasyon sa Pederasyon" + }, + "fedimods": { + "add-a-mod": "Magdagdag ng mod", + "add-fedi-mod": "Magdagdag ng Fedi Mod", + "add-mods-homescreen": "Magdagdag ng Mods sa iyong Fedi home screen", + "debug-mode": "Fedi Mod Debug Mode", + "debug-mode-info": "Nag-i-inject ng dev tool (Eruda) sa browser kapag binubuksan ang Fedi Mods", + "enter-amount-to-withdraw": "Maglagay ng halaga upang i-withdraw mula sa {{fediMod}}", + "fedi-mods": "Fedi Mods", + "leave-page": "Iiwan ang pahina?", + "leave-page-confirmation": "Sigurado ka bang nais mong iwan ang pahinang ito? Maaaring hindi masave ang mga pagbabago", + "login-failed": "Failed ang pag-login", + "login-to": "Mag-login sa", + "mod-title": "Titulo ng Mod", + "payment-request": "Request ng pagbabayad mula sa {{fediMod}}", + "stable-balance-enabled": "Stable na Balanse", + "stable-balance-enabled-info": "Nagbibigay-daan upang i-convert ang sats sa stable na pera", + "wants-to-pay-you": "Nais kang bayaran ng {{fediMod}}", + "wants-you-to-pay": "Nais ng {{fediMod}} na magbayad ka", + "your-mods": "Iyong Mga Mods" + }, + "fees": { + "guidance-ecash": "Ang talino! Ang pagpapadala ng pera sa mga kaibigan sa iyong pederasyon ay mas mura at mas madali—at mas astig pa. 😎", + "guidance-lightning": "Nais magtipid sa mga bayarin? Magpadala na lang sa Chat!", + "guidance-stable-balance": "Ito ang pinakamataas na maaari mong bayaran upang mapanatili ang balanse na ito sa loob ng isang taon. Maaaring mas mababa pa! 😉" + }, + "nostr": { + "kind-application-data": "Data para sa app", + "kind-authentication": "Mag-sign in gamit ang Nostr", + "kind-connect": "Nostr connect", + "kind-default": "Mensahe ng Nostr", + "kind-encrypted-dm": "Encrypted na mensahe", + "kind-highlight": "I-highlight", + "kind-metadata": "Metadata", + "kind-note": "Maikling text", + "kind-reaction": "Reaksyon", + "kind-repost": "Repost", + "kind-zap": "Zap", + "kind-zap-request": "Requuest ng Zap", + "log-in-to-mod": "Mag-login sa {{fediMod}} gamit ang {{method}}", + "wants-you-to-sign": "Nais ng {{fediMod}} na mag-sign ka" + }, + "omni": { + "action-enter-ln-address": "Maglagay ng lightning address", + "action-enter-text": "Maglagay ng Teksto", + "action-enter-username": "Maglagay ng Username", + "action-enter-username-or-ln": "Maglagay ng Username / Lightning Address", + "action-paste": "I-paste", + "action-scan": "I-scan ang QR", + "action-upload": "I-upload ang QR image", + "camera-permission-denied": "Pumunta sa mga setting upang baguhin ang mga permiso sa Camera.", + "camera-permission-request": "Pahintulutan ang pag-access sa camera upang mag-scan.", + "confirm-lnurl-auth": "Nais mo bang mag-login sa {{domain}} gamit ang lightning?", + "search-no-history-header": "Walang kasaysayan kasama ang gumagamit", + "search-no-results": "Walang gumagamit na tumutugma sa “{{query}}”", + "search-placeholder-ln-address": "Maglagay ng lightning address", + "search-placeholder-username": "Maglagay ng username", + "search-placeholder-username-or-ln": "Maglagay ng username o lightning address", + "unsupported-bolt12": "Hindi pa suportado ang mga alok ng BOLT 12. Sorry!", + "unsupported-legacy-chat": "Ang chat QR na ito ay mula sa bersyon ng app na hindi na suportado. Sorry!", + "unsupported-no-federation": "Hindi mo magagamit iyon bago sumali sa isang pederasyon. Subukang i-scan ang isang federation invite sa halip.", + "unsupported-on-chain": "Hindi pa suportado ang mga on-chain bitcoin address. Sorry!" + }, + "onboarding": { + "by-clicking-i-accept": "Sa pag-click ng 'Tinatanggap ko' sumasang-ayon ka sa mga tuntunin ng serbisyo sa {{tos_url}}", + "community-first": "Komunidad muna", + "continue-to-fedi": "Magpatuloy sa Fedi", + "create-username": "Lumikha ng username", + "create-your-username": "Lumikha ng iyong username", + "earn-and-save": "Kumita at Magtipid", + "enter-username": "Maglagay ng username", + "guidance-4": "Ginagamit ng Fedi ang bitcoin at lightning network upang ikonekta ka sa mga pagkakataong kumita sa buong mundo ng pera online ayon sa iyong sariling mga tuntunin.", + "guidance-public-federations": "Subukan ang isang komunidad mula sa Awesome Fedimint list", + "i-accept": "Tinatanggap ko", + "i-do-not-accept": "Hindi ko tinatanggap", + "join-new-member": "Sumali bilang bagong miyembro", + "join-returning-member": "Ako ay isang nagbabalik na miyembro", + "simple-and-private": "Simple at pribado", + "terms-and-conditions": "Mga Tuntunin at Kundisyon", + "unsupported-notice": "Ang pederasyong ito ay hindi na suportado. Hindi ito maaaring salihan.", + "username-guidance": "Maaari mo itong baguhin mamaya", + "username-instructions": "Ang iyong username ang magiging pagkakakilanlan mo sa ibang mga miyembro.", + "welcome-back-to-federation": "Maligayang pagbalik sa {{federation}}", + "welcome-instructions-unknown": "Ang mga bagong miyembro ay makakatanggap ng bagong wallet. Ang mga nagbabalik na miyembro ay awtomatikong mababawi ang kanilang lumang wallet.", + "welcome-to-federation": "Maligayang pagdating sa {{federation}}", + "welcome-to-fedi": "Maligayang pagdating sa Fedi Bravo" + }, + "parser": { + "unrecognized": "Hindi kinikilalang format ng data", + "unsupported-bolt11-zero-amount": "Hindi suportado ang Zero halagang Lightning invoice. Bumuo ng bagong invoice na may halaga at subukan muli.", + "unsupported-lnurl": "Hindi suportadong uri ng LNURL '{{type}}'" + }, + "permissions": { + "allow-camera-title": "Pahintulutan ang pag-access sa camera upang", + "allow-notifications-title": "Pahintulutan ang mga notification upang makita", + "update-later-disclaimer": "Maaari itong ma-update mamaya" + }, + "pin": { + "back-up-your-account": "I-backup ang iyong account", + "change-pin": "Baguhin ang PIN", + "create-a-pin": "Gumawa ng PIN", + "create-new-pin": "Gumawa ng bagong PIN", + "enter-current-pin": "I-lagay ng kasalukuyang PIN", + "enter-pin": "I-lagay ang PIN", + "pin-access": "I-access sa PIN", + "pin-doesnt-match": "Hindi tugma ang PIN", + "pin-setup-successful": "Matagumpay na na-setup ang PIN!", + "re-enter-pin": "Maglagay muli ng PIN", + "unlocking-fedi-app": "Ina-unlock ang Fedi app" + }, + "popup": { + "ended": "Tapos na", + "ended-description": "Ang pansamantalang pederasyong ito ay natapos na noong {{date}}.", + "ending-description": "Ang pansamantalang pederasyong ito ay matatapos na sa {{date}}. Ang natitirang mga pondo ay pamamahalaan ayon sa pagpapasya ng mga tagapangalaga.", + "ending-in": "Matatapos sa loob ng {{time}}" + }, + "receive": { + "add-amount": "Magdagdag ng halaga", + "awaiting-deposit": "Naghihintay ng deposito", + "awaiting-withdrawal-from": "Naghihintay ng pag-withdraw mula sa {{domain}}...", + "balance-not-spendable-offline": "Hindi magagastos ang balanse na ito hangga't hindi ka bumabalik online", + "bitcoin-request": "Request ng bitcoin", + "copied-payment-code": "Nakopya ang request sa pagbabayad", + "create-lightning-request": "Lumikha ng lightning request", + "enable-onchain-deposits": "I-enable ang onchain deposits", + "instructions": "Ilagay kung magkano ang nais mong matanggap", + "maximum-invoice-amount": "Ang maximum na halaga ng invoice ay {{maxAmount}} SATS", + "onchain-notice": "Ang mga on-chain deposit ay tumatagal ng ~10 oras upang makumpirma. Gumamit ng Lightning para sa instant na mga transaksyon", + "pending-transaction": "naghihintay na transaksyon", + "receive-amount-unit": "Tumanggap ng {{amount}} {{unit}}", + "receive-bitcoin": "Tumanggap ng bitcoin", + "receive-bitcoin-offline": "Tumanggap ng bitcoin offline", + "request-bitcoin": "Magrequest ng bitcoin", + "request-sats": "Magrequest ng {{amount}} SATS", + "request-via-lightning": "Humiling sa pamamagitan ng lightning", + "withdraw-from-domain": "Mag-withdraw mula sa {{domain}}", + "you-received": "Natanggap mo", + "you-received-amount-unit": "Natanggap mo ang {{amount}} {{unit}}" + }, + "recovery": { + "cancel-social-recovery": "Kanselahin ang social recovery", + "cancel-social-recovery-detail": "Nais mo bang kanselahin ang social recovery?", + "choose-method": "Pumili ng paraan ng pagbawi", + "choose-method-instructions": "Pumili ng paraan na ginamit mo upang i-backup ang iyong wallet nang unang sumali ka sa {{federation}}", + "choose-wallet-option": "Pumili ng opsyon sa wallet", + "complete-social-recovery": "Kumpletuhin ang social recovery", + "create-a-new-wallet": "Lumikha ng bagong wallet", + "create-a-new-wallet-instead": "Lumikha ng bagong wallet sa halip", + "create-new-wallet": "Lumikha ng bagong wallet", + "download-failed": "Nabigo ang pag-download", + "fresh-wallet": "Bagong wallet sa device na ito", + "from-different-device": "Mula sa ibang device papunta sa device na ito", + "guardian-approval-instructions": "Kailangan ng mga Guardian na kumpirmahin na ikaw ang tao sa iyong Fedi Intro Video upang mabawi ang iyong pera", + "guardian-approval-step-1": "1. Isaayos ang mga meeting sa mga Guardian (tingnan ang mga Guardian sa ibaba)", + "guardian-approval-step-2": "2. Hilingin sa Guardian na i-scan ang iyong QR code", + "guardian-approval-step-3": "3. Panunuorin nila ang iyong video at susuriin ang iyong pagkakakilanlan", + "guardian-approvals": "Pag-apruba ng Guardian", + "guardian-qr-instructions": "Kailangan ng mga Guardian na i-scan ang QR code na ito upang simulan ang proseso ng social recovery", + "guardians-remaining": "{{guardians}} natitira", + "invalid-qr-code": "Hindi wastong social recovery code", + "locate-social-recovery-file": "Buksan ang iyong backup file", + "locate-social-recovery-instructions-1": "Maaaring ibinahagi mo ang file na ito sa mga kaibigan o nilagay sa ilang iba't ibang lugar:", + "locate-social-recovery-instructions-3": "Ang pangalan ng Fedi File ay ganito:", + "locate-social-recovery-instructions-check-1": "Downloads", + "locate-social-recovery-instructions-check-2": "Cloud storage", + "locate-social-recovery-instructions-check-3": "Mga Mensahe", + "locate-social-recovery-instructions-check-4": "atbp.", + "locked-device-guidance-1": "Ang wallet sa device na ito ay nailipat na sa ibang device.", + "locked-device-guidance-2": "Ang {{deviceName}} device na ito ay naka-lock na. ❌", + "new-wallet": "Bagong wallet", + "nothing-to-download": "Walang ma-download mula sa guardian", + "open-qr-code": "Buksan ang QR Code", + "opening-backup-file-failed": "Hindi nabuksan ang backup file", + "opening-backup-file-failed-instructions": "Nabigo ang pagbukas ng backup file {{fileName}}. Subukan ulit at i-recover mula sa ibang lokasyon na iyong ibinahagi.", + "paste-social-recovery-code": "I-paste ang social recovery code", + "personal-recovery": "Personal na recovery", + "personal-recovery-instructions": "Ilagay ang 12 salita na isinulat mo nang unang i-backup ang iyong wallet", + "personal-recovery-method": "Kung sinulat mo ang 12 recovery words maaari mong ilagay muli ang mga ito upang mabawi ang iyong wallet", + "recover-a-wallet": "I-recover ang wallet", + "recover-wallet": "I-recover ang wallet", + "recover-wallet-with-balance": "Ang pagbawi ay kasalukuyang hindi suportado para sa mga wallet na may balanse. Paki-withdraw muna ang iyong mga pondo.", + "recovery-assist": "Tulong sa pagbawi", + "recovery-assist-confirm-check-2": "Ang agarang paligid ng indibidwal ay ligtas", + "recovery-assist-description": "Isang miyembro ng iyong Pederasyon ay humihiling ng iyong tulong sa pagbawi ng kanilang wallet", + "recovery-assist-instructions-1": "1. Suriin kung kalmado at ligtas ang miyembro", + "recovery-assist-instructions-2": "2. I-scan ang QR code ng miyembro", + "recovery-assist-instructions-3": "3. Panoorin ang kanilang Fedi backup video", + "recovery-assist-instructions-4": "4. Kumpirmahin na sila ang parehong tao sa backup video", + "recovery-assist-instructions-5": "5. Aprubahan o tanggihan ang request sa pagbawi ng miyembro", + "recovery-assist-process": "Proseso ng tulong sa pagbawi", + "recovery-assist-thank-you": "Salamat sa pagtulong na mabawi ang pera para sa isang miyembro ng Pederasyon", + "recovery-confirm-identity-instructions-1": "Panoorin ang video upang kumpirmahin ang pagkakakilanlan ng miyembro.", + "recovery-confirm-identity-instructions-2": "Ipinapakita ba ng video na ito ang parehong miyembro na sinusubukang gawin ang social recovery ngayon?", + "recovery-in-progress-balance": "Ang pagbawi ay nasa proseso. Ang iyong mga balanse ay mababalik sa lalong madaling panahon.", + "recovery-in-progress-chat-payments": "Ang pagbawi ay nasa proseso. Ang mga pagbabayad sa chat ay mababalik sa lalong madaling panahon.", + "recovery-in-progress-payments": "Ang pagbawi ay nasa proseso. Ang mga pagbabayad ay mababalik sa lalong madaling panahon.", + "search-files": "Maghanap ng mga file", + "select-a-device": "Pumili ng device", + "select-a-device-guidance": "Pumili ng device kung saan ililipat ang wallet", + "social-recovery": "Social recovery", + "social-recovery-instructions": "Buksan ang iyong social recovery Fedi file na nilikha noong ni-record mo ang iyong backup video. Inuudyukan ka naming i-save ang file at ibahagi ito sa mga kaibigan.", + "social-recovery-steps": "Mga hakbang sa social recovery", + "social-recovery-unsuccessful": "Hindi nagtagumpay ang social recovery", + "social-recovery-unsuccessful-instructions": "Subukang bumalik sa mga guardian at patunayan ang iyong pagkakakilanlan", + "start-personal-recovery": "Simulan ang personal na pagbawi", + "start-social-recovery": "Simulan ang social recovery", + "successfully-opened-fedi-file": "Matagumpay na nabuksan ang iyong Fedi File", + "transfer-existing-wallet": "Ilipat ang wallet", + "transfer-existing-wallet-guidance-1": "Dadalhin nito ang iyong wallet ngayon sa device na ito at i-llock ang wallet sa kabilang device.", + "transfer-existing-wallet-guidance-2": "Hindi mo kailangan ang lumang device para ilipat.", + "try-social-recovery-again": "Subukang muli ang social recovery", + "wallet-transfer": "Paglipat ng wallet", + "wallet-was-transferred": "Nailipat ang wallet", + "you-completed-personal-recovery": "Natapos mo na ang Personal Recovery", + "you-completed-social-recovery": "Natapos mo na ang Social Recovery" + }, + "send": { + "confirm-ecash-send": "Kumpirmahin ang Pagpadala ng Ecash", + "confirm-send": "Kumpirmahin ang Pagpadala", + "copied-offline-payment": "Kinopya ang offline na pagbabayad", + "enter-payment-request": "Ilagay ang isang request sa pagbabayad", + "hold-to-confirm-send": "Pindutin nang matagal upang Kumpirmahin ang Pagpadala", + "i-have-sent-payment": "Ako ay nagpadala na ng pagbabayad", + "paste-payment-request": "I-paste ang request sa pagbabayad", + "refund-in-block": "I-refund sa block {{block}}", + "scan-qr-code": "I-scan ang isang Lightning QR Code", + "send-amount-unit": "Magpadala ng {{amount}} {{unit}}", + "send-bitcoin": "Magpadala ng bitcoin", + "send-bitcoin-offline": "Magpadala ng bitcoin offline", + "send-from": "Magpadala mula sa", + "send-offline": "Magpadala offline", + "send-sats": "Magpadala ng {{amount}} SATS", + "send-to": "Magpadala sa", + "send-to-offline-user": "Magpadala sa isang offline na gumagamit", + "you-are-sending": "Ikaw ay nagpapadala", + "you-are-sending-amount-unit": "Ikaw ay nagpapadala ng {{amount}} {{unit}}", + "you-sent": "Ikaw ay nagpadala", + "you-sent-amount-unit": "Ikaw ay nagpadala ng {{amount}} {{unit}}" + }, + "settings": { + "currency-names": { + "ars": "Argentinian Peso", + "aud": "Australian Dollar", + "bdt": "Bangladeshi Taka", + "bif": "Burundian Franc", + "brl": "Brazilian Real", + "bwp": "Botswana Pula", + "cdf": "Congolese Franc", + "cfa": "Central African Franc", + "clp": "Chilean Peso", + "cop": "Colombian Peso", + "cup": "Cuban Peso", + "czk": "Czech koruna", + "djf": "Djiboutian Franc", + "ern": "Eritrean Nakfa", + "etb": "Ethiopian Birr", + "eur": "EU Euro", + "ghs": "Ghanaian Cedi", + "gtq": "Guatemalan Quetzal", + "hkd": "Hong Kong Dollar", + "hnl": "Honduran Lempira", + "idr": "Indonesian Rupiah", + "inr": "Indian rupee", + "kes": "Kenyan Shilling", + "lbp": "Lebanese Pound", + "mmk": "Myanmar Kyat", + "mwk": "Malawian Kwacha", + "mxn": "Mexican Peso", + "myr": "Malaysian Ringgit", + "nad": "Namibian Dollar", + "ngn": "Nigerian Naira", + "pen": "Peruvian Nuevo Sol", + "php": "Philippine Peso", + "rwf": "Rwandan Franc", + "sdg": "Sudanese Pound", + "sos": "Somali Shilling", + "ssp": "South Sudanese Pound", + "thb": "Thailand Baht", + "ugx": "Ugandan Shillings", + "usd": "US Dollar", + "uyu": "Uruguayan Peso", + "ves": "Bolivares", + "vnd": "Vietnam Dong", + "xaf": "Cameroon", + "zar": "South African Rand", + "zmw": "Zambian Kwacha" + } + }, + "stabilitypool": { + "amount-may-vary": "Maaaring magbago ang halaga", + "amount-may-vary-during-withdraw": "Maaaring magbago ang halaga habang nagwi-withdraw", + "amount-pending": "{{amount}} ay hinihintay", + "available-to-deposit": "Available para sa deposito", + "available-to-withdraw": "Available para sa pag-withdraw", + "bitcoin-amount": "Halaga ng Bitcoin", + "bitcoin-balance": "Balanse ng Bitcoin", + "confirm-deposit": "Kumpirmahin ang deposito", + "confirm-withdrawal": "Kumpirmahin ang pag-withdraw", + "currency-balance": "Balanse ng {{currency}}", + "current-value": "Kasalukuyang halaga", + "deposit-amount": "Halaga ng deposito", + "deposit-from": "Deposito mula sa", + "deposit-intiated": "Sinimulan ang deposito", + "deposit-pending": "+{{amount}} deposito ay hinihintay..", + "deposit-time": "Oras ng deposito", + "deposit-to": "Deposito sa", + "deposit-to-balance": "Deposito sa {{currency}} balanse", + "deposit-value": "Halaga ng deposito", + "deposits-disabled-by-federation": "Ang Stability Pool Deposits ay hindi na pinapayagan ng Pederasyon", + "details-and-fee": "Mga Detalye at Bayad", + "enter-deposit-amount": "Ilagay ang halaga ng deposito", + "enter-withdrawal-amount": "Ilagay ang halaga ng pag-withdraw", + "fees-paid": "Mga binayaran", + "max-stable-balance-amount": "Naabot na ang maximum na halaga ng stable na balanse", + "minutes": "{{minutes}} minuto", + "more-than-an-hour": "1+ oras", + "no-bitcoin-notice": "Kailangan mong magkaroon ng bitcoin upang magdeposito sa {{currency}} balanse", + "one-minute": "1 minuto", + "one-second": "1 segundo", + "pending-withdrawal-blocking": "Paki-hintay na maproseso ang pag-withdraw bago gumawa ng bagong deposito o pag-withdraw", + "seconds": "{{seconds}} segundo", + "will-be-deposited": "{{amount}} ay ide-deposito sa loob ng {{expectedWait}}", + "will-be-withdrawn": "{{amount}} ay i-withdraw sa loob ng {{expectedWait}}", + "withdraw-to": "I-withdraw sa", + "withdrawal-amount": "Halaga ng pag-withdraw", + "withdrawal-from": "I-withdraw mula sa", + "withdrawal-from-balance": "I-withdraw mula sa {{currency}} balanse", + "withdrawal-intiated": "Nagsimula ang pag-withdraw", + "withdrawal-pending": "{{amount}} na winithdraw ay hinihintay...", + "withdrawal-time": "Oras ng pag-withdraw", + "withdrawal-value": "Halaga ng pag-withdraw", + "you-deposited": "Nagdeposito ka", + "you-withdrew": "Nag-withdraw ka" + }, + "wallet": { + "network-notice": "Ang pederasyong ito ay gumagamit ng {{network}} SATS", + "show-fiat-txn-amounts": "Ipakita ang mga halaga ng Fiat Transaction", + "show-fiat-txn-amounts-info": "Ang mga halaga ng transaksyon ay ipapakita sa napiling fiat currency" + } + } +} diff --git a/ui/common/redux/chat.ts b/ui/common/redux/chat.ts index c95a9ce..d8f5b3f 100644 --- a/ui/common/redux/chat.ts +++ b/ui/common/redux/chat.ts @@ -1,8 +1,8 @@ import { - createSlice, PayloadAction, - createSelector, createAsyncThunk, + createSelector, + createSlice, isAnyOf, } from '@reduxjs/toolkit' import isEqual from 'lodash/isEqual' @@ -16,17 +16,17 @@ import { } from '.' import { Chat, - ChatMessage, - ChatMember, ChatGroup, + ChatMember, + ChatMessage, ChatPayment, - Keypair, + ChatPaymentStatus, ChatType, - XmppCredentials, - XmppClientStatus, ChatWithLatestMessage, - ChatPaymentStatus, Federation, + Keypair, + XmppClientStatus, + XmppCredentials, } from '../types' import { getFederationChatServerDomain, diff --git a/ui/common/redux/currency.ts b/ui/common/redux/currency.ts index a0fe2f3..0aadcf5 100644 --- a/ui/common/redux/currency.ts +++ b/ui/common/redux/currency.ts @@ -2,8 +2,8 @@ import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit' import { CommonState, - selectStabilityPoolCycleStartPrice, selectFederationMetadata, + selectStabilityPoolCycleStartPrice, } from '.' import { Federation, SupportedCurrency } from '../types' import { @@ -21,6 +21,7 @@ const initialState = { btcUsdRate: 0 as number, fiatUsdRates: {} as Record, selectedFiatCurrency: null as SupportedCurrency | null, + currencyLocale: undefined as string | undefined, } export type CurrencyState = typeof initialState @@ -37,6 +38,9 @@ export const currencySlice = createSlice({ ) { state.selectedFiatCurrency = action.payload }, + setCurrencyLocale(state, action: PayloadAction) { + state.currencyLocale = action.payload + }, resetCurrencyState() { return { ...initialState } }, @@ -61,8 +65,11 @@ export const currencySlice = createSlice({ /*** Basic actions ***/ -export const { changeSelectedFiatCurrency, resetCurrencyState } = - currencySlice.actions +export const { + changeSelectedFiatCurrency, + setCurrencyLocale, + resetCurrencyState, +} = currencySlice.actions /*** Async thunk actions ***/ @@ -98,6 +105,9 @@ export const fetchCurrencyPrices = createAsyncThunk< /*** Selectors ***/ +export const selectCurrencyLocale = (s: CommonState) => + s.currency.currencyLocale + export const selectCurrency = (s: CommonState) => { if (s.currency.selectedFiatCurrency) return s.currency.selectedFiatCurrency diff --git a/ui/common/redux/federation.ts b/ui/common/redux/federation.ts index 1bc7e13..c7f268e 100644 --- a/ui/common/redux/federation.ts +++ b/ui/common/redux/federation.ts @@ -15,34 +15,35 @@ import { } from '.' import { FEDI_GLOBAL_COMMUNITY } from '../constants/community' import { + ClientConfigMetadata, Federation, + FederationListItem, + FediMod, Guardian, + MatrixRoom, MSats, + Network, PublicFederation, Sats, - FediMod, - MatrixRoom, - FederationListItem, - ClientConfigMetadata, - Network, } from '../types' import { RpcJsonClientConfig, RpcStabilityPoolConfig } from '../types/bindings' import amountUtils from '../utils/AmountUtils' import { + coerceFederationListItem, + fetchFederationsExternalMetadata, + getFederationFediMods, getFederationGroupChats, getFederationMaxBalanceMsats, getFederationMaxInvoiceMsats, - getFederationFediMods, - fetchFederationsExternalMetadata, - getFederationName, getFederationMaxStableBalanceMsats, - coerceFederationListItem, - joinFromInvite, - getFederationWelcomeMessage, + getFederationName, getFederationPinnedMessage, + getFederationWelcomeMessage, + joinFromInvite, } from '../utils/FederationUtils' import type { FedimintBridge } from '../utils/fedimint' import { makeChatFromPreview } from '../utils/matrix' +import { upsertRecordEntityId } from '../utils/redux' import { loadFromStorage } from './storage' /*** Initial State ***/ @@ -132,10 +133,29 @@ export const federationSlice = createSlice({ state, action: PayloadAction, ) { - state.externalMeta = { + const newMeta = { ...state.externalMeta, ...action.payload, } + if (isEqual(newMeta, state.externalMeta)) { + return + } + state.externalMeta = newMeta + }, + setFederationCustomFediMods( + state, + action: PayloadAction<{ + federationId: Federation['id'] + mods: FediMod[] | undefined + }>, + ) { + const { federationId, mods } = action.payload + if (isEqual(mods, state.customFediMods[federationId] || [])) return + + state.customFediMods = { + ...state.customFediMods, + [federationId]: mods, + } }, setFederationExternalMeta( state, @@ -144,10 +164,11 @@ export const federationSlice = createSlice({ meta: ClientConfigMetadata | undefined }>, ) { - const { federationId, meta } = action.payload - state.externalMeta = isEqual(meta, state.externalMeta[federationId]) - ? state.externalMeta - : { ...state.externalMeta, [federationId]: meta } + state.externalMeta = upsertRecordEntityId( + state.externalMeta, + action.payload.meta, + action.payload.federationId, + ) }, changeAuthenticatedGuardian( state, @@ -185,6 +206,9 @@ export const federationSlice = createSlice({ if (state.externalMeta[federationId]) { state.externalMeta = omit(state.externalMeta, federationId) } + if (state.customFediMods[federationId]) { + state.customFediMods = omit(state.customFediMods, federationId) + } }) builder.addCase(loadFromStorage.fulfilled, (state, action) => { @@ -223,6 +247,7 @@ export const { updateFederationBalance, setActiveFederationId, setPayFromFederationId, + setFederationCustomFediMods, updateExternalMeta, setFederationExternalMeta, changeAuthenticatedGuardian, @@ -245,13 +270,29 @@ export const refreshFederations = createAsyncThunk< // TODO Check arguments for listCommunities const communities = await fedimint.listCommunities({}) const communitiesAsFederations = communities.map(coerceFederationListItem) + const externalMeta = await fetchFederationsExternalMetadata( - // include the Fedi Global community used for the global announcements channel - [...federations, ...communitiesAsFederations, FEDI_GLOBAL_COMMUNITY], + [ + ...federations, + ...communitiesAsFederations, + // For the purposes of gathering metadata, we need to + // treat the global community as a "wallet" federation. + // The means we'll fetch the external metadata for it. + { ...FEDI_GLOBAL_COMMUNITY, hasWallet: true }, + ], (federationId, meta) => { dispatch(setFederationExternalMeta({ federationId, meta })) + dispatch( + setFederationCustomFediMods({ + federationId, + mods: getFederationFediMods(meta), + }), + ) }, ) + // First update the federations with the external meta that + // is locally accessible. We update each federation's meta + // as the external fetches return in the background dispatch(updateExternalMeta(externalMeta)) dispatch(setFederations([...federations, ...communitiesAsFederations])) return selectFederations(getState()) @@ -259,12 +300,19 @@ export const refreshFederations = createAsyncThunk< export const joinFederation = createAsyncThunk< FederationListItem, - { fedimint: FedimintBridge; code: string }, + { fedimint: FedimintBridge; code: string; recoverFromScratch?: boolean }, { state: CommonState } >( 'federation/joinFederation', - async ({ fedimint, code }, { dispatch, getState }) => { - const federation = await joinFromInvite(fedimint, code) + async ( + { fedimint, code, recoverFromScratch = false }, + { dispatch, getState }, + ) => { + const federation = await joinFromInvite( + fedimint, + code, + recoverFromScratch, + ) await dispatch(refreshFederations(fedimint)) dispatch(setActiveFederationId(federation.id)) @@ -378,7 +426,7 @@ export const selectActiveFederationId = (s: CommonState) => { return selectActiveFederation(s)?.id } -export const selectPayFromFederation = createSelector( +export const selectPaymentFederation = createSelector( selectWalletFederations, selectActiveFederation, (s: CommonState) => s.federation.payFromFederationId, @@ -475,8 +523,8 @@ export const selectFederationBalance = createSelector( }, ) -export const selectPayFromFederationBalance = createSelector( - selectPayFromFederation, +export const selectPaymentFederationBalance = createSelector( + selectPaymentFederation, payFromFederation => { return payFromFederation ? payFromFederation.balance : (0 as MSats) }, @@ -597,12 +645,18 @@ export const selectReceivesDisabled = createSelector( }, ) +export const selectCommunityMods = createSelector( + (s: CommonState) => s.federation.customFediMods, + customFediMods => Object.values(customFediMods).flatMap(mods => mods ?? []), +) + export const selectActiveFederationFediMods = createSelector( - selectActiveFederation, - selectActiveFederationCustomFediMods, - (federation, customFediMods) => { - if (!federation) return [] - return [...getFederationFediMods(federation.meta), ...customFediMods] + (s: CommonState) => s.federation.activeFederationId, + (s: CommonState) => s.federation.customFediMods, + (activeFederationId, customFediMods) => { + return activeFederationId + ? customFediMods[activeFederationId] || [] + : [] }, ) diff --git a/ui/common/redux/index.ts b/ui/common/redux/index.ts index c70b934..72350bc 100644 --- a/ui/common/redux/index.ts +++ b/ui/common/redux/index.ts @@ -47,9 +47,9 @@ export * from './federation' export * from './matrix' export * from './nux' export * from './recovery' +export * from './security' export * from './toast' export * from './wallet' -export * from './security' export const commonReducers = { chat: chatSlice.reducer, diff --git a/ui/common/redux/matrix.ts b/ui/common/redux/matrix.ts index c0f43e6..65dc1cb 100644 --- a/ui/common/redux/matrix.ts +++ b/ui/common/redux/matrix.ts @@ -1,8 +1,8 @@ import { - createSlice, PayloadAction, createAsyncThunk, createSelector, + createSlice, } from '@reduxjs/toolkit' import orderBy from 'lodash/orderBy' import { v4 as uuidv4 } from 'uuid' @@ -16,28 +16,28 @@ import { selectWalletFederations, } from '.' import { - MatrixUser, - MatrixRoom, + FederationListItem, + MSats, MatrixAuth, - MatrixRoomMember, + MatrixCreateRoomOptions, MatrixError, - MatrixPowerLevel, - MatrixSearchResults, + MatrixEvent, + MatrixGroupPreview, MatrixPaymentEvent, - MSats, - MatrixPaymentStatus, MatrixPaymentEventContent, - MatrixRoomListObservableUpdates, - MatrixTimelineObservableUpdates, + MatrixPaymentStatus, + MatrixPowerLevel, + MatrixRoom, MatrixRoomListItem, - MatrixTimelineItem, - MatrixEvent, + MatrixRoomListObservableUpdates, + MatrixRoomMember, MatrixRoomPowerLevels, + MatrixSearchResults, MatrixSyncStatus, - MatrixCreateRoomOptions, + MatrixTimelineItem, + MatrixTimelineObservableUpdates, + MatrixUser, Sats, - MatrixGroupPreview, - FederationListItem, } from '../types' import { RpcRoomId, RpcRoomNotificationMode } from '../types/bindings' import amountUtils from '../utils/AmountUtils' @@ -47,6 +47,7 @@ import { FedimintBridge } from '../utils/fedimint' import { makeLog } from '../utils/log' import { getReceivablePaymentEvents, + getRoomEventPowerLevel, getUserSuffix, isPaymentEvent, makeChatFromPreview, @@ -54,7 +55,6 @@ import { mxcUrlToHttpUrl, shouldShowUnreadIndicator, } from '../utils/matrix' -import { getRoomEventPowerLevel } from '../utils/matrix' import { applyObservableUpdates } from '../utils/observable' import { isBolt11 } from '../utils/parser' import { upsertListItem, upsertRecordEntity } from '../utils/redux' @@ -94,6 +94,7 @@ const initialState = { errors: [] as MatrixError[], pushNotificationToken: null as string | null, groupPreviews: {} as Record, + drafts: {} as Record, } export type MatrixState = typeof initialState @@ -190,6 +191,17 @@ export const matrixSlice = createSlice({ resetMatrixState() { return { ...initialState } }, + setChatDraft( + state, + action: PayloadAction<{ roomId: MatrixRoom['id']; text: string }>, + ) { + const { roomId, text } = action.payload + const id = roomId as keyof MatrixState['drafts'] + + if (text.length === 0 && state.drafts[id]) delete state.drafts[id] + + state.drafts[id] = text + }, }, extraReducers: builder => { builder.addCase(startMatrixClient.pending, state => { @@ -324,6 +336,7 @@ export const { handleMatrixRoomListObservableUpdates, handleMatrixRoomTimelineObservableUpdates, resetMatrixState, + setChatDraft, } = matrixSlice.actions /*** Async thunk actions ***/ @@ -684,12 +697,12 @@ export const checkForReceivablePayments = createAsyncThunk< const timeline = roomId ? state.matrix.roomTimelines[roomId] : // flattens all timelines into 1 array - Object.values(state.matrix.roomTimelines).reduce< - MatrixTimelineItem[] - >((result, t) => { - if (!t) return result - return [...result, ...t] - }, []) + Object.values(state.matrix.roomTimelines).reduce< + MatrixTimelineItem[] + >((result, t) => { + if (!t) return result + return [...result, ...t] + }, []) if (!myId || !timeline) return const walletFederations = selectWalletFederations(getState()) log.info('Looking for receivable payment events...') @@ -1028,9 +1041,9 @@ export const selectMatrixRooms = createSelector( ...room, broadcastOnly: powerLevels ? getRoomEventPowerLevel(powerLevels, [ - 'm.room.message', - 'm.room.encrypted', - ]) >= MatrixPowerLevel.Moderator + 'm.room.message', + 'm.room.encrypted', + ]) >= MatrixPowerLevel.Moderator : false, }) } @@ -1425,3 +1438,5 @@ export const selectDefaultMatrixRoomIds = createSelector( return defaultMatrixRoomIds }, ) + +export const selectChatDrafts = (s: CommonState) => s.matrix.drafts diff --git a/ui/common/redux/mod.ts b/ui/common/redux/mod.ts index 336102f..82e8e01 100644 --- a/ui/common/redux/mod.ts +++ b/ui/common/redux/mod.ts @@ -1,20 +1,29 @@ import { PayloadAction, createSelector, createSlice } from '@reduxjs/toolkit' import omit from 'lodash/omit' -import { CommonState, selectGlobalCommunityMeta } from '.' +import { CommonState, federationSlice, selectGlobalCommunityMeta } from '.' import { FediMod } from '../types' import { getFederationFediMods } from '../utils/FederationUtils' +import { deduplicate } from '../utils/fedimods' +import { upsertRecordEntityId } from '../utils/redux' import { loadFromStorage } from './storage' // using an interface here to explicitly define "visibility" instead of an ambigious bool export interface ModVisibility { isHidden: boolean + // true if the mod is included in the global mods list + isGlobal?: boolean + // true if the mod is included in a community's mods list + isCommunity?: boolean + // true if the mod was created by the user + isCustom?: boolean } const initialState = { + // User-created mods list customGlobalMods: {} as Record, - customGlobalModVisibility: {} as Record, - suggestedGlobalModVisibility: {} as Record, + // Tracks which mods are visible to the user + modVisibility: {} as Record, } export type ModState = typeof initialState @@ -23,7 +32,7 @@ export const modSlice = createSlice({ name: 'mod', initialState, reducers: { - addCustomGlobalMod( + addCustomMod( state, action: PayloadAction<{ fediMod: FediMod @@ -32,8 +41,18 @@ export const modSlice = createSlice({ const { fediMod } = action.payload state.customGlobalMods[fediMod.id] = fediMod + const visibility: ModVisibility = { + ...(state.modVisibility[fediMod.id] ?? {}), + isHidden: false, + isCustom: true, + } + state.modVisibility = upsertRecordEntityId( + state.modVisibility, + visibility, + fediMod.id, + ) }, - removeCustomGlobalMod( + removeCustomMod( state, action: PayloadAction<{ modId: FediMod['id'] }>, ) { @@ -43,19 +62,19 @@ export const modSlice = createSlice({ if (state.customGlobalMods[modId]) { state.customGlobalMods = omit(state.customGlobalMods, modId) } + if (state.modVisibility[modId].isCommunity) { + state.modVisibility = { + // sets isCustom to false on the visibility + // object without touching anything else + ...omit(state.modVisibility, modId), + [modId]: { + ...state.modVisibility[modId], + isCustom: false, + }, + } + } }, - setCustomGlobalModVisibility( - state, - action: PayloadAction<{ - modId: FediMod['id'] - isHidden: boolean - }>, - ) { - const { modId, isHidden } = action.payload - - state.customGlobalModVisibility[modId] = { isHidden } - }, - setSuggestedGlobalModVisibility( + setModVisibility( state, action: PayloadAction<{ modId: FediMod['id'] @@ -63,8 +82,10 @@ export const modSlice = createSlice({ }>, ) { const { modId, isHidden } = action.payload - - state.suggestedGlobalModVisibility[modId] = { isHidden } + state.modVisibility[modId] = { + ...(state.modVisibility[modId] ?? {}), + isHidden, + } }, }, extraReducers: builder => { @@ -72,25 +93,48 @@ export const modSlice = createSlice({ if (!action.payload) return state.customGlobalMods = action.payload.customGlobalMods || {} - state.customGlobalModVisibility = - action.payload.customGlobalModVisibility || {} - state.suggestedGlobalModVisibility = - action.payload.suggestedGlobalModVisibility || {} + state.modVisibility = action.payload.modVisibility || {} }) + builder.addCase( + // When a federation's mods are updated, we need to + // set the visibility the mods + federationSlice.actions.setFederationCustomFediMods, + (state, action) => { + if (!action.payload?.mods) return + for (const mod of action.payload.mods) { + // If the mod is already tracked as a community mod, + // we don't need to do anything + if (state.modVisibility[mod.id]?.isCommunity) continue + state.modVisibility = upsertRecordEntityId( + state.modVisibility, + { + ...state.modVisibility[mod.id], + isHidden: false, + isCommunity: true, + } as ModVisibility, + mod.id, + ) as Record + } + }, + ) }, }) -export const { - addCustomGlobalMod, - removeCustomGlobalMod, - setCustomGlobalModVisibility, - setSuggestedGlobalModVisibility, -} = modSlice.actions +export const { addCustomMod, removeCustomMod, setModVisibility } = + modSlice.actions -export const selectGlobalCustomMods = (s: CommonState) => +export const selectCustomMods = (s: CommonState) => Object.values(s.mod.customGlobalMods) -export const selectGlobalSuggestedMods = createSelector( +// Community-set mods +export const selectCommunityMods = createSelector( + (s: CommonState) => s.federation.customFediMods, + communityMods => + Object.values(communityMods).flatMap(modList => modList ?? []), +) + +// Global mods +export const selectGlobalMods = createSelector( (s: CommonState) => selectGlobalCommunityMeta(s), globalCommunityMeta => { if (!globalCommunityMeta) return [] @@ -99,12 +143,13 @@ export const selectGlobalSuggestedMods = createSelector( }, ) -export const selectVisibleSuggestedMods = createSelector( - (s: CommonState) => s.mod.suggestedGlobalModVisibility, - selectGlobalSuggestedMods, - (suggestedGlobalModVisibility, mods) => +// Global mods +export const selectVisibleGlobalMods = createSelector( + (s: CommonState) => s.mod.modVisibility, + selectGlobalMods, + (modVisibility, mods) => mods.filter(mod => { - const visibility = suggestedGlobalModVisibility[mod.id] + const visibility = modVisibility[mod.id] if (!visibility) { return true } @@ -113,12 +158,13 @@ export const selectVisibleSuggestedMods = createSelector( }), ) +// User-created mods export const selectVisibleCustomMods = createSelector( - (s: CommonState) => s.mod.customGlobalModVisibility, - selectGlobalCustomMods, - (customGlobalModVisibility, mods) => + (s: CommonState) => s.mod.modVisibility, + selectCustomMods, + (modVisibility, mods) => mods.filter(mod => { - const visibility = customGlobalModVisibility[mod.id] + const visibility = modVisibility[mod.id] if (!visibility) { return true } @@ -127,8 +173,36 @@ export const selectVisibleCustomMods = createSelector( }), ) +// Community-set mods +export const selectVisibleCommunityMods = createSelector( + (s: CommonState) => s.mod.modVisibility, + selectCommunityMods, + (modVisibility, mods) => + mods.filter(mod => { + const visibility = modVisibility[mod.id] + if (!visibility) { + return true + } + return !visibility.isHidden + }), +) + +export const selectModsVisibility = (s: CommonState) => s.mod.modVisibility +export const selectModVisibility = (s: CommonState, id: string) => + s.mod.modVisibility[id] + +export const selectConfigurableMods = createSelector( + selectGlobalMods, + selectCustomMods, + (global, custom) => + // Filter out duplicate mods + deduplicate([...global, ...custom]), +) + export const selectAllVisibleMods = createSelector( - selectVisibleSuggestedMods, + selectVisibleGlobalMods, selectVisibleCustomMods, - (suggested, custom) => [...suggested, ...custom], + (global, custom) => + // Filter out duplicate mods + deduplicate([...global, ...custom]), ) diff --git a/ui/common/redux/storage.ts b/ui/common/redux/storage.ts index 4e50da9..766b896 100644 --- a/ui/common/redux/storage.ts +++ b/ui/common/redux/storage.ts @@ -1,4 +1,4 @@ -import { createSlice, createAsyncThunk } from '@reduxjs/toolkit' +import { createAsyncThunk, createSlice } from '@reduxjs/toolkit' import { CommonState } from '.' import type { LatestStoredState, StorageApi } from '../types' diff --git a/ui/common/redux/transactions.ts b/ui/common/redux/transactions.ts index 99a3ef2..010c4a7 100644 --- a/ui/common/redux/transactions.ts +++ b/ui/common/redux/transactions.ts @@ -1,8 +1,8 @@ import { - createSlice, PayloadAction, createAsyncThunk, createSelector, + createSlice, } from '@reduxjs/toolkit' import orderBy from 'lodash/orderBy' @@ -200,8 +200,10 @@ export const selectTransactionHistory = createSelector( if ( txn.bitcoin && txn.direction === TransactionDirection.receive && - txn.onchainState?.type === 'waitingForTransaction' && - Date.now() / 1000 - txn.createdAt > 3600 + Date.now() / 1000 - txn.createdAt > 3600 && + (!txn.onchainState || + (txn.onchainState.type !== 'waitingForConfirmation' && + txn.onchainState.type !== 'claimed')) ) { return false } diff --git a/ui/common/redux/wallet.ts b/ui/common/redux/wallet.ts index d3e028a..26522e2 100644 --- a/ui/common/redux/wallet.ts +++ b/ui/common/redux/wallet.ts @@ -1,8 +1,8 @@ import { - createSlice, PayloadAction, createAsyncThunk, createSelector, + createSlice, } from '@reduxjs/toolkit' import { TFunction } from 'i18next' @@ -39,6 +39,7 @@ type FederationPayloadAction = PayloadAction< const initialFederationWalletState = { stabilityPoolAccountInfo: null as RpcStabilityPoolAccountInfo | null, cycleStartPrice: null as number | null, + averageFeeRate: null as number | null, } type FederationWalletState = typeof initialFederationWalletState @@ -95,6 +96,18 @@ export const walletSlice = createSlice({ }, ) + builder.addCase( + fetchStabilityPoolAverageFeeRate.fulfilled, + (state, action) => { + const { federationId } = action.meta.arg + const federation = getFederationWalletState(state, federationId) + state[federationId] = { + ...federation, + averageFeeRate: action.payload, + } + }, + ) + builder.addCase( fetchStabilityPoolCycleStartPrice.fulfilled, (state, action) => { @@ -155,6 +168,22 @@ export const fetchStabilityPoolCycleStartPrice = createAsyncThunk< }, ) +export const fetchStabilityPoolAverageFeeRate = createAsyncThunk< + number, + { fedimint: FedimintBridge; federationId: string; numCycles: number } +>( + 'wallet/fetchStabilityPoolAverageFeeRate', + async ({ fedimint, federationId, numCycles }) => { + const feeRate = await fedimint.stabilityPoolAverageFeeRate( + federationId, + numCycles, + ) + + log.info('stabilityPoolAverageFeeRate', { feeRate }) + return Number(feeRate) + }, +) + export const refreshActiveStabilityPool = createAsyncThunk< void, { fedimint: FedimintBridge }, @@ -170,6 +199,14 @@ export const refreshActiveStabilityPool = createAsyncThunk< dispatch(fetchCurrencyPrices()) dispatch(fetchStabilityPoolCycleStartPrice({ fedimint, federationId })) + dispatch( + fetchStabilityPoolAverageFeeRate({ + fedimint, + federationId, + numCycles: 10, + }), + ) + await dispatch( fetchStabilityPoolAccountInfo({ fedimint, @@ -689,28 +726,6 @@ export const selectFormattedDepositTime = createSelector( } }, ) -/** - * Get the max APR from the max allowed fee rate in parts per billion - * This calculates what % of a deposit the user can expect to pay in fees - * after 1 full year, deducting fees every 10 minutes compounding every cycle - */ -export const selectMaximumAPR = createSelector( - (s: CommonState) => selectFederationStabilityPoolConfig(s), - config => { - if (!config) return 0 - const maxFeeRatePerCycle = config.max_allowed_provide_fee_rate_ppb || 0 - // convert parts per billion to decimal - const periodicRate = maxFeeRatePerCycle / 1_000_000_000 - // Number of 10 minute cycles in a year - const { secs: secondsPerCycle } = config.cycle_duration - const secondsInYear = 365 * 24 * 60 * 60 - const cyclesPerYear = secondsInYear / secondsPerCycle - const compoundedAnnualRate = - 1 - Math.pow(1 - periodicRate, cyclesPerYear) - const maxFeePercentage = (compoundedAnnualRate * 100).toFixed(2) - return Number(maxFeePercentage) - }, -) export const selectStabilityPoolCycleStartPrice = ( s: CommonState, @@ -723,3 +738,15 @@ export const selectStabilityPoolCycleStartPrice = ( ? selectFederationWalletState(s, federationId).cycleStartPrice : null } + +export const selectStabilityPoolAverageFeeRate = ( + s: CommonState, + federationId?: Federation['id'], +) => { + if (!federationId) { + federationId = selectActiveFederationId(s) + } + return federationId + ? selectFederationWalletState(s, federationId).averageFeeRate + : null +} diff --git a/ui/common/tests/utils/AmountUtils.test.ts b/ui/common/tests/utils/AmountUtils.test.ts index 107635c..742ff6e 100644 --- a/ui/common/tests/utils/AmountUtils.test.ts +++ b/ui/common/tests/utils/AmountUtils.test.ts @@ -276,31 +276,111 @@ describe('AmountUtils', () => { }) }) describe('parseFiatString', () => { - const expectedResult = 1234.56 const testCases = [ { locale: 'en-US', fiat: '$1,234.56', + expectedResult: 1234.56, }, { locale: 'en-CA', fiat: 'US$1,234.56', + expectedResult: 1234.56, }, { locale: 'de-DE', fiat: '1.234,56 €', // careful for non-standard whitespace char + expectedResult: 1234.56, }, { locale: 'fr-TG', fiat: '1 234,56 CFA', // careful for non-standard whitespace char + expectedResult: 1234.56, + }, + { + locale: 'en-US', + fiat: '$0.05', + expectedResult: 0.05, + }, + { + locale: 'en-CA', + fiat: 'US$0.05', + expectedResult: 0.05, + }, + { + locale: 'de-DE', + fiat: '0,05 €', // careful for non-standard whitespace char + expectedResult: 0.05, + }, + { + locale: 'fr-TG', + fiat: '0,05 CFA', // careful for non-standard whitespace char + expectedResult: 0.05, }, ] - testCases.forEach(({ locale, fiat }) => { + testCases.forEach(({ locale, fiat, expectedResult }) => { it(`should parse ${expectedResult} from ${fiat} in ${locale} locale`, () => { const result = amountUtils.parseFiatString(fiat, { locale }) expect(result).toEqual(expectedResult) }) }) + + // Note: there used to be a bug where getThousandsSeparator returned + // an empty string, breaking the RegExp in parseFiatString. this + // shouldn't happen if a valid locale is provided but keep this + // test as a safeguard + it('should handle locale if thousands separator is empty', () => { + // Mock getThousandsSeparator to return an empty string + const originalGetThousandsSeparator = + amountUtils.getThousandsSeparator + amountUtils.getThousandsSeparator = jest.fn().mockReturnValue('') + + const result = amountUtils.parseFiatString('0.005') + expect(result).toEqual(0.005) + amountUtils.getThousandsSeparator = originalGetThousandsSeparator + }) + }) + describe('getThousandsSeparator', () => { + const testCases = [ + { locale: 'en-US', expectedResult: ',' }, + { locale: 'de-DE', expectedResult: '.' }, + { locale: 'fr-FR', expectedResult: ' ' }, // careful for non-standard whitespace char + ] + + testCases.forEach(({ locale, expectedResult }) => { + it(`should return '${expectedResult}' for ${locale} locale`, () => { + const result = amountUtils.getThousandsSeparator({ locale }) + expect(result).toEqual(expectedResult) + }) + }) + + it('should use the system default locale when no locale is provided', () => { + const defaultSeparator = amountUtils.getThousandsSeparator({ + locale: undefined, + }) + expect(typeof defaultSeparator).toBe('string') + expect(defaultSeparator.length).toBe(1) + }) + }) + describe('getDecimalSeparator', () => { + const testCases = [ + { locale: 'en-US', expectedResult: '.' }, + { locale: 'de-DE', expectedResult: ',' }, + { locale: 'fr-FR', expectedResult: ',' }, + ] + + testCases.forEach(({ locale, expectedResult }) => { + it(`should return '${expectedResult}' for ${locale} locale`, () => { + const result = amountUtils.getDecimalSeparator({ locale }) + expect(result).toEqual(expectedResult) + }) + }) + + it('should use the system default locale when no locale is provided', () => { + const defaultSeparator = amountUtils.getDecimalSeparator() + expect(typeof defaultSeparator).toBe('string') + expect(defaultSeparator.length).toBe(1) + }) }) }) diff --git a/ui/common/tests/utils/matrix.test.ts b/ui/common/tests/utils/matrix.test.ts index f6d9b62..e0a5376 100644 --- a/ui/common/tests/utils/matrix.test.ts +++ b/ui/common/tests/utils/matrix.test.ts @@ -1,6 +1,6 @@ import { - encodeFediMatrixUserUri, decodeFediMatrixUserUri, + encodeFediMatrixUserUri, isValidMatrixUserId, } from '../../utils/matrix' diff --git a/ui/common/types/bindings.ts b/ui/common/types/bindings.ts index d734f3b..5ae8df7 100644 --- a/ui/common/types/bindings.ts +++ b/ui/common/types/bindings.ts @@ -65,6 +65,9 @@ export type ErrorCode = | 'timeout' | 'recovery' | { invalidJson: string } + | 'payLnInvoiceAlreadyPaid' + | 'payLnInvoiceAlreadyInProgress' + | 'noLnGatewayAvailable' export type Event = | { transaction: TransactionEvent } @@ -144,7 +147,6 @@ export type RpcBackPaginationStatus = export interface RpcBitcoinDetails { address: string - expiresAt: number } export interface RpcBridgeStatus { @@ -247,8 +249,8 @@ export interface RpcLightningGateway { export type RpcLnPayState = | { type: 'created' } | { type: 'canceled' } - | { type: 'funded' } - | { type: 'waitingForRefund'; block_height: number; gateway_error: string } + | { type: 'funded'; block_height: number } + | { type: 'waitingForRefund'; error_reason: string } | { type: 'awaitingChange' } | { type: 'success'; preimage: string } | { type: 'refunded'; gateway_error: string } @@ -314,7 +316,7 @@ export interface RpcMethods { ] onAppForeground: [Record, null] joinFederation: [ - { inviteCode: string }, + { inviteCode: string; recoverFromScratch: boolean }, { balance: RpcAmount id: RpcFederationId @@ -477,7 +479,11 @@ export interface RpcMethods { }>, ] socialRecoveryDownloadVerificationDoc: [ - { federationId: RpcFederationId; recoveryId: RpcRecoveryId }, + { + federationId: RpcFederationId + recoveryId: RpcRecoveryId + peerId: RpcPeerId + }, string | null, ] approveSocialRecoveryRequest: [ @@ -490,7 +496,7 @@ export interface RpcMethods { null, ] signLnurlMessage: [ - { message: string; domain: string; federationId: RpcFederationId }, + { message: string; domain: string }, { signature: string; pubkey: RpcPublicKey }, ] backupStatus: [ @@ -507,10 +513,7 @@ export interface RpcMethods { ] getNostrPubKey: [Record, string] getNostrPubKeyBech32: [Record, string] - signNostrEvent: [ - { eventHash: string; federationId: RpcFederationId }, - string, - ] + signNostrEvent: [{ eventHash: string }, string] stabilityPoolAccountInfo: [ { federationId: RpcFederationId; forceUpdate: boolean }, { @@ -537,7 +540,7 @@ export interface RpcMethods { string, ] stabilityPoolAverageFeeRate: [ - { federationId: RpcFederationId; numCycles: bigint }, + { federationId: RpcFederationId; numCycles: number }, bigint, ] stabilityPoolAvailableLiquidity: [{ federationId: RpcFederationId }, MSats] @@ -775,7 +778,6 @@ export type RpcOOBState = RpcOOBSpendState | RpcOOBReissueState export type RpcOnchainDepositState = | { type: 'waitingForTransaction' } | ({ type: 'waitingForConfirmation' } & RpcOnchainDepositTransactionData) - | ({ type: 'confirmed' } & RpcOnchainDepositTransactionData) | ({ type: 'claimed' } & RpcOnchainDepositTransactionData) | { type: 'failed' } diff --git a/ui/common/types/fedimint.ts b/ui/common/types/fedimint.ts index 505141a..c6158c7 100644 --- a/ui/common/types/fedimint.ts +++ b/ui/common/types/fedimint.ts @@ -1,23 +1,23 @@ import { BalanceEvent, + CommunityMetadataUpdatedEvent, + DeviceRegistrationEvent, LogEvent, + ObservableUpdate, + PanicEvent, + RecoveryCompleteEvent, + RecoveryProgressEvent, + RpcCommunity, RpcFederation, + RpcFederationPreview, RpcInvoice, RpcLightningGateway, RpcResponse, - SocialRecoveryEvent, RpcTransaction, SocialRecoveryApproval, - PanicEvent, - StabilityPoolWithdrawalEvent, + SocialRecoveryEvent, StabilityPoolDepositEvent, - RpcFederationPreview, - RecoveryCompleteEvent, - RecoveryProgressEvent, - ObservableUpdate, - DeviceRegistrationEvent, - RpcCommunity, - CommunityMetadataUpdatedEvent, + StabilityPoolWithdrawalEvent, } from './bindings' import { Usd, UsdCents } from './units' diff --git a/ui/common/types/index.ts b/ui/common/types/index.ts index c7d338a..5d3ea5e 100644 --- a/ui/common/types/index.ts +++ b/ui/common/types/index.ts @@ -1,10 +1,10 @@ -export * from '@fedi/common/types/chat' -export type { SocialRecoveryEvent } from '@fedi/common/types/bindings' export * as bindings from '@fedi/common/types/bindings' +export type { SocialRecoveryEvent } from '@fedi/common/types/bindings' +export * from '@fedi/common/types/chat' +export * from '@fedi/common/types/fediInternal' export * from '@fedi/common/types/fedimint' export * from '@fedi/common/types/matrix' +export * from '@fedi/common/types/parser' export * from '@fedi/common/types/storage' export * from '@fedi/common/types/toast' export * from '@fedi/common/types/units' -export * from '@fedi/common/types/parser' -export * from '@fedi/common/types/fediInternal' diff --git a/ui/common/types/storage.ts b/ui/common/types/storage.ts index fba4bbc..fb07624 100644 --- a/ui/common/types/storage.ts +++ b/ui/common/types/storage.ts @@ -4,7 +4,7 @@ import { ProtectedFeatures } from '../redux' import { ModVisibility } from '../redux/mod' import { Chat, ChatGroup, ChatMember, ChatMessage } from './chat' -import { Federation, Guardian, FediMod, SupportedCurrency } from './fedimint' +import { Federation, FediMod, Guardian, SupportedCurrency } from './fedimint' export interface StoredStateV0 { version: 0 // Not a real version, just implemented for demonstrative purposes @@ -182,6 +182,15 @@ export interface StoredStateV18 extends Omit { suggestedGlobalModVisibility: Record } +export interface StoredStateV19 + extends Omit< + StoredStateV18, + 'version' | 'customGlobalModVisibility' | 'suggestedGlobalModVisibility' + > { + version: 19 + modVisibility: Record +} + /*** Union of all past shapes of stored state ***/ export type AnyStoredState = | StoredStateV0 @@ -203,9 +212,10 @@ export type AnyStoredState = | StoredStateV16 | StoredStateV17 | StoredStateV18 + | StoredStateV19 /*** Alias for the latest version of stored state ***/ -export type LatestStoredState = StoredStateV18 +export type LatestStoredState = StoredStateV19 export interface StorageApi { getItem(key: string): Promise diff --git a/ui/common/utils/AmountUtils.ts b/ui/common/utils/AmountUtils.ts index aae6c96..12c7e44 100644 --- a/ui/common/utils/AmountUtils.ts +++ b/ui/common/utils/AmountUtils.ts @@ -221,8 +221,8 @@ class AmountUtils { fiat: string, options: { locale?: string | string[] } = {}, ): number => { - const thousandSeparator = this.getThousandsSeparator(options) - const decimalSeparator = this.getDecimalSeparator(options) + const thousandSeparator = this.getThousandsSeparator(options) || ',' + const decimalSeparator = this.getDecimalSeparator(options) || '.' return parseFloat( fiat .replace(new RegExp('\\' + thousandSeparator, 'g'), '') diff --git a/ui/common/utils/FederationUtils.ts b/ui/common/utils/FederationUtils.ts index 62c0fea..d1f5fe2 100644 --- a/ui/common/utils/FederationUtils.ts +++ b/ui/common/utils/FederationUtils.ts @@ -6,15 +6,15 @@ import { XMPP_RESOURCE } from '../constants/xmpp' import { ClientConfigMetadata, Federation, - MSats, + FederationListItem, FediMod, + JoinPreview, + MSats, + Network, + PublicFederation, SupportedCurrency, SupportedMetaFields, XmppConnectionOptions, - PublicFederation, - FederationListItem, - Network, - JoinPreview, } from '../types' import { RpcCommunity } from '../types/bindings' import { FedimintBridge } from './fedimint' @@ -80,6 +80,7 @@ const fetchExternalMetadata = async ( if (timeoutId) { clearTimeout(timeoutId) } + onBackgroundSuccess && onBackgroundSuccess(metaJson) return metaJson } @@ -165,20 +166,22 @@ export const fetchFederationsExternalMetadata = async ( // Assemble all the promises and return the first pass of results. If they // provided onBackgroundSuccess, we'll call those as they come in. - const federationsMeta = await Promise.all( - externalUrls.map(async url => - fetchExternalMetadata(url, handleBackgroundSuccess), - ), - ).then(results => - results.reduce((prev, extMeta) => { + const federationsMeta = await Promise.all([ + ...externalUrls.map(url => { + return fetchExternalMetadata(url, res => { + return handleBackgroundSuccess && handleBackgroundSuccess(res) + }) + }), + ]).then(results => { + return results.reduce((prev, extMeta) => { if (!extMeta) return prev const entries = getFederationMetaEntries(extMeta) for (const entry of entries) { prev[entry[0]] = entry[1] } return prev - }, {}), - ) + }, {}) + }) return { ...communitiesMeta, ...federationsMeta } } @@ -657,11 +660,15 @@ export const detectInviteCodeType = ( export const joinFromInvite = async ( fedimint: FedimintBridge, code: string, + recoverFromScratch = false, ): Promise => { const codeType = detectInviteCodeType(code) if (codeType === 'federation') { log.info(`joinFromInvite: joining federation with code '${code}'`) - const { network, ...federation } = await fedimint.joinFederation(code) + const { network, ...federation } = await fedimint.joinFederation( + code, + recoverFromScratch, + ) return { ...federation, hasWallet: true, diff --git a/ui/common/utils/MatrixChatClient.ts b/ui/common/utils/MatrixChatClient.ts index 84aa923..a54c62a 100644 --- a/ui/common/utils/MatrixChatClient.ts +++ b/ui/common/utils/MatrixChatClient.ts @@ -5,21 +5,21 @@ import { INVALID_NAME_PLACEHOLDER, } from '../constants/matrix' import { - MatrixRoom, - MatrixUser, - MatrixError, - MatrixRoomMember, - MatrixSearchResults, MatrixAuth, MatrixCreateRoomOptions, - MatrixTimelineObservableUpdates, - MatrixRoomListObservableUpdates, + MatrixError, + MatrixEventStatus, + MatrixRoom, MatrixRoomListItem, MatrixRoomListItemStatus, - MatrixTimelineItem, - MatrixEventStatus, + MatrixRoomListObservableUpdates, + MatrixRoomMember, MatrixRoomPowerLevels, + MatrixSearchResults, MatrixSyncStatus, + MatrixTimelineItem, + MatrixTimelineObservableUpdates, + MatrixUser, } from '../types' import { ObservableUpdate, diff --git a/ui/common/utils/csv.ts b/ui/common/utils/csv.ts index 13d1d12..44aa4e5 100644 --- a/ui/common/utils/csv.ts +++ b/ui/common/utils/csv.ts @@ -30,11 +30,7 @@ export function makeTransactionHistoryCSV( } else if (txn.onchainState) { const { type } = txn.onchainState - return ( - type === 'succeeded' || - type === 'claimed' || - type === 'confirmed' - ) + return type === 'succeeded' || type === 'claimed' } else if (txn.oobState) { const { type } = txn.oobState diff --git a/ui/common/utils/fedimint.ts b/ui/common/utils/fedimint.ts index fcca8fa..28250ed 100644 --- a/ui/common/utils/fedimint.ts +++ b/ui/common/utils/fedimint.ts @@ -49,6 +49,10 @@ export class FedimintBridge { return this.rpcTyped('federationPreview', { inviteCode }) } + async stabilityPoolAverageFeeRate(federationId: string, numCycles: number) { + return this.rpcTyped('stabilityPoolAverageFeeRate', { federationId, numCycles }) + } + async stabilityPoolWithdraw( lockedBps: number, unlockedAmount: RpcAmount, @@ -118,8 +122,11 @@ export class FedimintBridge { }) } - async joinFederation(inviteCode: string) { - return this.rpcTyped('joinFederation', { inviteCode }) + async joinFederation(inviteCode: string, recoverFromScratch = false) { + return this.rpcTyped('joinFederation', { + inviteCode, + recoverFromScratch, + }) } async leaveFederation(federationId: string) { @@ -201,15 +208,10 @@ export class FedimintBridge { }) } - async signLnurlMessage( - message: string, - domain: string, - federationId: string, - ) { + async signLnurlMessage(message: string, domain: string) { return this.rpcTyped('signLnurlMessage', { message, domain, - federationId, }) } @@ -217,10 +219,9 @@ export class FedimintBridge { return this.rpcTyped('getNostrPubKey', {}) } - async signNostrEvent(eventHash: string, federationId: string) { + async signNostrEvent(eventHash: string) { return this.rpcTyped('signNostrEvent', { eventHash, - federationId, }) } @@ -334,10 +335,12 @@ export class FedimintBridge { async socialRecoveryDownloadVerificationDoc( recoveryId: string, federationId: string, + peerId: number, ) { return this.rpcTyped('socialRecoveryDownloadVerificationDoc', { federationId, recoveryId, + peerId, }) } diff --git a/ui/common/utils/fedimods.ts b/ui/common/utils/fedimods.ts index 458ef69..a7ae49f 100644 --- a/ui/common/utils/fedimods.ts +++ b/ui/common/utils/fedimods.ts @@ -178,3 +178,14 @@ export async function fetchMetadataFromUrl( fetchedTitle, } } + +/** + * Filters out duplicate mods + */ +export const deduplicate = (arr: T[]) => { + return arr.reduce((acc, curr) => { + if (acc.some(item => item?.id === curr.id)) return acc + acc.push(curr) + return acc + }, [] as Array) +} diff --git a/ui/common/utils/lnurl.ts b/ui/common/utils/lnurl.ts index 9f67099..15926fd 100644 --- a/ui/common/utils/lnurl.ts +++ b/ui/common/utils/lnurl.ts @@ -13,13 +13,11 @@ import { FedimintBridge } from './fedimint' */ export async function lnurlAuth( fedimint: FedimintBridge, - federationId: string, lnurlData: ParsedLnurlAuth['data'], ) { const { signature, pubkey } = await fedimint.signLnurlMessage( lnurlData.k1, lnurlData.domain, - federationId, ) const callbackUrl = new URL(lnurlData.callback) callbackUrl.searchParams.set('sig', signature) diff --git a/ui/common/utils/parser.ts b/ui/common/utils/parser.ts index 9865bea..5e0878f 100644 --- a/ui/common/utils/parser.ts +++ b/ui/common/utils/parser.ts @@ -6,29 +6,29 @@ import qs from 'query-string' import { Btc, MSats } from '../types' import { AnyParsedData, - ParserDataType, ParsedBip21, ParsedBitcoinAddress, ParsedBolt11, ParsedBolt12, + ParsedCommunityInvite, ParsedFederationInvite, + ParsedFediChatRoom, + ParsedFediChatUser, ParsedFedimintEcash, + ParsedLegacyFediChatGroup, + ParsedLegacyFediChatMember, ParsedLnurlAuth, ParsedLnurlPay, ParsedLnurlWithdraw, ParsedUnknownData, ParsedWebsite, - ParsedLegacyFediChatGroup, - ParsedLegacyFediChatMember, - ParsedFediChatUser, - ParsedFediChatRoom, - ParsedCommunityInvite, + ParserDataType, } from '../types/parser' import { FedimintBridge } from './fedimint' import { makeLog } from './log' import { decodeFediMatrixRoomUri, decodeFediMatrixUserUri } from './matrix' import { isValidInternetIdentifier } from './validation' -import { decodeGroupInvitationLink, decodeDirectChatLink } from './xmpp' +import { decodeDirectChatLink, decodeGroupInvitationLink } from './xmpp' const log = makeLog('common/utils/parser') diff --git a/ui/common/utils/redux.ts b/ui/common/utils/redux.ts index 5acfb13..b749bb1 100644 --- a/ui/common/utils/redux.ts +++ b/ui/common/utils/redux.ts @@ -68,3 +68,43 @@ export function upsertRecordEntity( }, } } + +/** + * Same logic as upsertRecordEntity but allows us to pass in the entityId + */ +export function upsertRecordEntityId( + record: Record | null | undefined, + entity: T, + entityId: string, +) { + record = record || {} + if (record[entityId] && isEqual(record[entityId], entity)) { + return record + } + return { + ...record, + [entityId]: { + ...(record[entityId] || {}), + ...entity, + }, + } +} + +/** + * Same logic as upsertRecordEntityId but allows us to pass + * in the entityId + */ +export function upsertRecordList( + record: Record | null | undefined, + entity: T[], + entityId: string, +) { + record = record || {} + if (record[entityId] && isEqual(record[entityId], entity)) { + return record + } + return { + ...record, + [entityId]: [...(record[entityId] || []), ...entity], + } +} diff --git a/ui/common/utils/storage.ts b/ui/common/utils/storage.ts index 3736bfa..6c7d932 100644 --- a/ui/common/utils/storage.ts +++ b/ui/common/utils/storage.ts @@ -3,6 +3,7 @@ import omit from 'lodash/omit' import uniq from 'lodash/uniq' import { CommonState } from '../redux' +import { ModVisibility } from '../redux/mod' import { Chat } from '../types' import { AnyStoredState, @@ -15,8 +16,8 @@ import { StoredStateV4, } from '../types/storage' import { - getLatestMessageIdsForChats, getLatestMessage, + getLatestMessageIdsForChats, getLatestPaymentUpdate, getLatestPaymentUpdateIdsForChats, } from './chat' @@ -28,7 +29,7 @@ export const STATE_STORAGE_KEY = 'fedi:state' */ export function transformStateToStorage(state: CommonState): LatestStoredState { return { - version: 18, + version: 19, onchainDepositsEnabled: state.environment.onchainDepositsEnabled, developerMode: state.environment.developerMode, stableBalanceEnabled: state.environment.stableBalanceEnabled, @@ -68,8 +69,7 @@ export function transformStateToStorage(state: CommonState): LatestStoredState { matrixAuth: state.matrix.auth, protectedFeatures: state.security.protectedFeatures, customGlobalMods: state.mod.customGlobalMods, - customGlobalModVisibility: state.mod.customGlobalModVisibility, - suggestedGlobalModVisibility: state.mod.suggestedGlobalModVisibility, + modVisibility: state.mod.modVisibility, } } @@ -111,13 +111,13 @@ export function hasStorageStateChanged( ['federation', 'activeFederationId'], ['federation', 'authenticatedGuardian'], ['federation', 'externalMeta'], + // TODO: migrate legacy mods to customGlobalMods ['federation', 'customFediMods'], ['matrix', 'auth'], ['nux', 'steps'], ['security', 'protectedFeatures'], ['mod', 'customGlobalMods'], - ['mod', 'customGlobalModVisibility'], - ['mod', 'suggestedGlobalModVisibility'], + ['mod', 'modVisibility'], ] // Check all federation's chat states, including old and new. @@ -508,6 +508,7 @@ async function migrateStoredState( // storage.removeItem('deviceId') } + // Version 16 -> 17 if (migrationState.version === 16) { migrationState = { ...migrationState, @@ -519,6 +520,7 @@ async function migrateStoredState( } } + // Version 17 -> 18 if (migrationState.version === 17) { migrationState = { ...migrationState, @@ -529,5 +531,56 @@ async function migrateStoredState( } } + // Version 18 -> 19 + if (migrationState.version === 18) { + const { + customGlobalModVisibility, + suggestedGlobalModVisibility, + ...rest + } = migrationState + migrationState = { + ...rest, + version: 19, + modVisibility: { + // migrate the global mods visibility settings + ...Object.entries(suggestedGlobalModVisibility ?? {}).reduce( + (acc, [modId, visibility]) => { + acc[modId] = { + ...visibility, + isGlobal: true, + } + return acc + }, + {} as Record, + ), + // migrate all the stored custom mods + ...Object.entries(migrationState.customGlobalMods ?? {}).reduce( + (acc, [modId, mod]) => { + if (!mod) return acc + acc[modId] = { + isHidden: false, + isCustom: true, + } as ModVisibility + return acc + }, + {} as Record, + ), + // Override the default visibility setting + // with any existing settings on the custom mods + ...Object.entries(customGlobalModVisibility ?? {}).reduce( + (acc, [modId, visibility]) => { + if (!visibility) return acc + acc[modId] = { + ...visibility, + isCustom: true, + } as ModVisibility + return acc + }, + {} as Record, + ), + }, + } + } + return migrationState } diff --git a/ui/common/utils/wallet.ts b/ui/common/utils/wallet.ts index 8cf6e7a..da5670f 100644 --- a/ui/common/utils/wallet.ts +++ b/ui/common/utils/wallet.ts @@ -47,9 +47,7 @@ export const makeTxnDetailStatusText = ( // direction=receive instead of direction=send switch (txn.lnState?.type) { case 'waitingForRefund': - return t('feature.send.refund-in-block', { - block: txn.lnState.block_height, - }) + return t('feature.send.waiting-for-refund') case 'refunded': return t('words.refund') case 'canceled': @@ -85,9 +83,7 @@ export const makeTxnDetailStatusText = ( if (!txn.lnState) return `${t('phrases.receive-pending')}` switch (txn.lnState.type) { case 'waitingForRefund': - return t('feature.send.refund-in-block', { - block: txn.lnState.block_height, - }) + return t('feature.send.waiting-for-refund') case 'refunded': return t('words.refund') case 'waitingForPayment': @@ -105,8 +101,6 @@ export const makeTxnDetailStatusText = ( return t('words.pending') case 'waitingForConfirmation': return t('words.seen') - case 'confirmed': - return t('words.seen') case 'claimed': return t('words.complete') default: diff --git a/ui/injections/src/index.ts b/ui/injections/src/index.ts index 249d309..dee12a8 100644 --- a/ui/injections/src/index.ts +++ b/ui/injections/src/index.ts @@ -1,8 +1,8 @@ import { AnyInjectionRequestMessage, - InjectionMessageType, - InjectionMessageHandlers, InjectionMessageHandler, + InjectionMessageHandlers, + InjectionMessageType, } from './types' export * from './types' diff --git a/ui/injections/src/injectables/fediInternal.ts b/ui/injections/src/injectables/fediInternal.ts index f1089fa..5d871f2 100644 --- a/ui/injections/src/injectables/fediInternal.ts +++ b/ui/injections/src/injectables/fediInternal.ts @@ -6,7 +6,7 @@ import { SupportedCurrency, } from '@fedi/common/types' -import { InjectionMessageType, InjectionMessageResponseMap } from '../types' +import { InjectionMessageResponseMap, InjectionMessageType } from '../types' import { sendInjectorMessage } from '../utils' class InjectionFediProvider { diff --git a/ui/injections/src/injectables/webln.ts b/ui/injections/src/injectables/webln.ts index 98c01c7..0dd74e0 100644 --- a/ui/injections/src/injectables/webln.ts +++ b/ui/injections/src/injectables/webln.ts @@ -1,6 +1,6 @@ -import type { WebLNProvider, RequestInvoiceArgs, KeysendArgs } from 'webln' +import type { KeysendArgs, RequestInvoiceArgs, WebLNProvider } from 'webln' -import { InjectionMessageType, InjectionMessageResponseMap } from '../types' +import { InjectionMessageResponseMap, InjectionMessageType } from '../types' import { sendInjectorMessage } from '../utils' class InjectionWebLNProvider implements WebLNProvider { diff --git a/ui/native/Router.tsx b/ui/native/Router.tsx index e5f3e26..5ca86d8 100644 --- a/ui/native/Router.tsx +++ b/ui/native/Router.tsx @@ -4,7 +4,7 @@ import { useNavigationContainerRef, } from '@react-navigation/native' import { useTheme } from '@rneui/themed' -import React, { useCallback, useRef } from 'react' +import { useCallback, useRef } from 'react' import { useToast } from '@fedi/common/hooks/toast' import { makeLog } from '@fedi/common/utils/log' @@ -17,8 +17,8 @@ import SwitchingFederations from './screens/SwitchingFederations' import { useOmniLinkContext } from './state/contexts/OmniLinkContext' import { useMatrixHealthCheck, useMatrixPushNotifications } from './state/hooks' import { - MainNavigatorDrawerParamList, DRAWER_NAVIGATION_ID, + MainNavigatorDrawerParamList, } from './types/navigation' import { useIsFeatureUnlocked } from './utils/hooks/security' import { getLinkingConfig } from './utils/linking' diff --git a/ui/native/android/app/build.gradle b/ui/native/android/app/build.gradle index 95d1b68..05a025d 100644 --- a/ui/native/android/app/build.gradle +++ b/ui/native/android/app/build.gradle @@ -115,7 +115,7 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 240051929 - versionName "1.18.2" + versionName "1.19.3" } packagingOptions { diff --git a/ui/native/android/app/src/main/AndroidManifest.xml b/ui/native/android/app/src/main/AndroidManifest.xml index 6354387..d9fd032 100644 --- a/ui/native/android/app/src/main/AndroidManifest.xml +++ b/ui/native/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - + @@ -9,6 +9,9 @@ + + + ( method: string, payload: object, ): Promise { - log.info('rpc method', method) const jsonPayload = JSON.stringify(payload) const json: string = await new Promise(resolve => { setTimeout(() => resolve(FedimintFfi.rpc(method, jsonPayload))) diff --git a/ui/native/components/FediBridgeInitializer.tsx b/ui/native/components/FediBridgeInitializer.tsx index 79f181d..76ac370 100644 --- a/ui/native/components/FediBridgeInitializer.tsx +++ b/ui/native/components/FediBridgeInitializer.tsx @@ -32,9 +32,11 @@ import { useAppDispatch, useAppSelector } from '../state/hooks' import theme from '../styles/theme' import { generateDeviceId } from '../utils/device-info' import { useAppIsInForeground } from '../utils/hooks/notifications' +import { formatBridgeFfiLog } from '../utils/log' import { displayPaymentReceivedNotification } from '../utils/notifications' const log = makeLog('FediBridgeInitializer') +const ffiLog = makeLog('ffi') interface Props { children: React.ReactNode @@ -155,9 +157,8 @@ export const FediBridgeInitializer: React.FC = ({ children }) => { const unsubscribeLog = fedimint.addListener( 'log', (event: LogEvent) => { - // Strip escape characters - const stripped = event.log.replace('\\', '') - log.info('OS:', Platform.OS, `": log" -> "${stripped}"`) + const formattedLog = formatBridgeFfiLog(event) + ffiLog.info(formattedLog) }, ) diff --git a/ui/native/components/feature/admin/SettingsItem.tsx b/ui/native/components/feature/admin/SettingsItem.tsx index f612a45..2fb809a 100644 --- a/ui/native/components/feature/admin/SettingsItem.tsx +++ b/ui/native/components/feature/admin/SettingsItem.tsx @@ -10,7 +10,7 @@ import * as Svgs from '../../../assets/images/svgs' import { Pressable } from '../../ui/Pressable' import SvgImage from '../../ui/SvgImage' -type SettingsItemProps = { +export type SettingsItemProps = { disabled?: boolean image: React.ReactNode label: string diff --git a/ui/native/components/feature/backup/BackupVideoRecorder.tsx b/ui/native/components/feature/backup/BackupVideoRecorder.tsx index bb10ac3..1a9d532 100644 --- a/ui/native/components/feature/backup/BackupVideoRecorder.tsx +++ b/ui/native/components/feature/backup/BackupVideoRecorder.tsx @@ -1,5 +1,4 @@ import { Theme, useTheme } from '@rneui/themed' -import React from 'react' import { StyleSheet, View } from 'react-native' import { useBackupRecoveryContext } from '../../../state/contexts/BackupRecoveryContext' diff --git a/ui/native/components/feature/backup/RecordVideo.tsx b/ui/native/components/feature/backup/RecordVideo.tsx index e0ebb82..2ef857b 100644 --- a/ui/native/components/feature/backup/RecordVideo.tsx +++ b/ui/native/components/feature/backup/RecordVideo.tsx @@ -1,5 +1,5 @@ import { Text, Theme, useTheme } from '@rneui/themed' -import React, { useMemo, useRef, useState } from 'react' +import { useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { ImageBackground, Pressable, StyleSheet, View } from 'react-native' import type { CameraDeviceFormat } from 'react-native-vision-camera' diff --git a/ui/native/components/feature/backup/ReviewVideo.tsx b/ui/native/components/feature/backup/ReviewVideo.tsx index de8f31d..55c6514 100644 --- a/ui/native/components/feature/backup/ReviewVideo.tsx +++ b/ui/native/components/feature/backup/ReviewVideo.tsx @@ -1,6 +1,6 @@ import { useNavigation } from '@react-navigation/native' import { Button, Text, Theme, useTheme } from '@rneui/themed' -import React, { useEffect, useRef, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { ImageBackground, Pressable, StyleSheet, View } from 'react-native' import RNFS from 'react-native-fs' diff --git a/ui/native/components/feature/chat/ChatConnectionBadge.tsx b/ui/native/components/feature/chat/ChatConnectionBadge.tsx index 2658afb..dd17752 100644 --- a/ui/native/components/feature/chat/ChatConnectionBadge.tsx +++ b/ui/native/components/feature/chat/ChatConnectionBadge.tsx @@ -2,10 +2,10 @@ import { Text, Theme, useTheme } from '@rneui/themed' import React, { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { - Animated, ActivityIndicator, - StyleSheet, + Animated, Easing, + StyleSheet, ViewStyle, } from 'react-native' import { useSafeAreaInsets } from 'react-native-safe-area-context' diff --git a/ui/native/components/feature/chat/ChatConversation.tsx b/ui/native/components/feature/chat/ChatConversation.tsx index b39453a..bf8d9d8 100644 --- a/ui/native/components/feature/chat/ChatConversation.tsx +++ b/ui/native/components/feature/chat/ChatConversation.tsx @@ -1,4 +1,4 @@ -import { Theme, useTheme, Text } from '@rneui/themed' +import { Text, Theme, useTheme } from '@rneui/themed' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { diff --git a/ui/native/components/feature/chat/ChatConversationHeader.tsx b/ui/native/components/feature/chat/ChatConversationHeader.tsx index 46b3d6d..ef7602b 100644 --- a/ui/native/components/feature/chat/ChatConversationHeader.tsx +++ b/ui/native/components/feature/chat/ChatConversationHeader.tsx @@ -31,7 +31,6 @@ const ChatConversationHeader: React.FC = () => { const room = useAppSelector(s => selectMatrixRoom(s, roomId)) const preview = useAppSelector(s => selectGroupPreview(s, roomId)) const user = useAppSelector(s => selectMatrixUser(s, userId)) - const isGroupChat = room?.directUserId === undefined const style = styles(theme) @@ -74,14 +73,12 @@ const ChatConversationHeader: React.FC = () => { centerContainerStyle={style.headerCenterContainer} headerCenter={ { // make sure we have joined room and its not just a preview to show admin settings - // TODO: implement admin settings for 1on1 chat - if (isGroupChat && room) { - navigation.navigate('GroupAdmin', { roomId }) + if (room) { + navigation.navigate('RoomSettings', { roomId }) } }}> {avatar} diff --git a/ui/native/components/feature/chat/ChatPaymentEvent.tsx b/ui/native/components/feature/chat/ChatPaymentEvent.tsx index b149895..563929c 100644 --- a/ui/native/components/feature/chat/ChatPaymentEvent.tsx +++ b/ui/native/components/feature/chat/ChatPaymentEvent.tsx @@ -2,7 +2,7 @@ import { useNavigation } from '@react-navigation/native' import { Button, Text, Theme, useTheme } from '@rneui/themed' import React from 'react' import { useTranslation } from 'react-i18next' -import { View, StyleSheet } from 'react-native' +import { StyleSheet, View } from 'react-native' import { useMatrixPaymentEvent } from '@fedi/common/hooks/matrix' import { useToast } from '@fedi/common/hooks/toast' diff --git a/ui/native/components/feature/chat/ChatPreviewConversation.tsx b/ui/native/components/feature/chat/ChatPreviewConversation.tsx index 63b913d..377cee3 100644 --- a/ui/native/components/feature/chat/ChatPreviewConversation.tsx +++ b/ui/native/components/feature/chat/ChatPreviewConversation.tsx @@ -1,5 +1,5 @@ import { useIsFocused } from '@react-navigation/native' -import { Theme, useTheme, Text } from '@rneui/themed' +import { Text, Theme, useTheme } from '@rneui/themed' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { diff --git a/ui/native/components/feature/chat/ChatRoomActions.tsx b/ui/native/components/feature/chat/ChatRoomActions.tsx index 2007eea..100830e 100644 --- a/ui/native/components/feature/chat/ChatRoomActions.tsx +++ b/ui/native/components/feature/chat/ChatRoomActions.tsx @@ -43,7 +43,6 @@ const ChatRoomActions: React.FC = ({ room, dismiss }: Props) => { const notificationMode = useAppSelector(s => selectMatrixRoomNotificationMode(s, room.id), ) - const isGroupChat = room?.directUserId === undefined const actions: Action[] = [ { @@ -59,9 +58,7 @@ const ChatRoomActions: React.FC = ({ room, dismiss }: Props) => { setLoadingAction(null) }, }, - ] - if (isGroupChat) { - actions.push({ + { id: 1, label: t('feature.chat.chat-settings'), icon: 'Cog', @@ -71,8 +68,8 @@ const ChatRoomActions: React.FC = ({ room, dismiss }: Props) => { dismiss() setLoadingAction(null) }, - }) - } + }, + ] const handleUpdateNotificationMode = async ( id: number, mode: RpcRoomNotificationMode, diff --git a/ui/native/components/feature/chat/ChatRoomActionsOverlay.tsx b/ui/native/components/feature/chat/ChatRoomActionsOverlay.tsx index ea5b843..66e61c2 100644 --- a/ui/native/components/feature/chat/ChatRoomActionsOverlay.tsx +++ b/ui/native/components/feature/chat/ChatRoomActionsOverlay.tsx @@ -1,4 +1,4 @@ -import { Theme, useTheme, Text } from '@rneui/themed' +import { Text, Theme, useTheme } from '@rneui/themed' import React from 'react' import { StyleSheet, View } from 'react-native' diff --git a/ui/native/components/feature/chat/ChatSettingsAvatar.tsx b/ui/native/components/feature/chat/ChatSettingsAvatar.tsx index dba75db..3c3ab23 100644 --- a/ui/native/components/feature/chat/ChatSettingsAvatar.tsx +++ b/ui/native/components/feature/chat/ChatSettingsAvatar.tsx @@ -1,7 +1,6 @@ import { Text, Theme, useTheme } from '@rneui/themed' import React from 'react' -import { StyleSheet } from 'react-native' -import { View } from 'react-native' +import { StyleSheet, View } from 'react-native' import { MatrixRoom } from '@fedi/common/types' diff --git a/ui/native/components/feature/chat/ChatTile.tsx b/ui/native/components/feature/chat/ChatTile.tsx index a897d0a..76ccdc8 100644 --- a/ui/native/components/feature/chat/ChatTile.tsx +++ b/ui/native/components/feature/chat/ChatTile.tsx @@ -1,6 +1,6 @@ import { Text, Theme, useTheme } from '@rneui/themed' import { t } from 'i18next' -import React, { useMemo } from 'react' +import { useMemo } from 'react' import { Pressable, StyleSheet, View } from 'react-native' import dateUtils from '@fedi/common/utils/DateUtils' diff --git a/ui/native/components/feature/chat/ChatsList.tsx b/ui/native/components/feature/chat/ChatsList.tsx index b97ebd2..0c2f06b 100644 --- a/ui/native/components/feature/chat/ChatsList.tsx +++ b/ui/native/components/feature/chat/ChatsList.tsx @@ -12,11 +12,11 @@ import { import { ErrorBoundary } from '@fedi/common/components/ErrorBoundary' import { - selectMatrixChatsList, - selectMatrixStatus, + previewDefaultGroupChats, refetchMatrixRoomList, selectIsChatEmpty, - previewDefaultGroupChats, + selectMatrixChatsList, + selectMatrixStatus, } from '@fedi/common/redux' import { ChatType, MatrixRoom, MatrixSyncStatus } from '@fedi/common/types' diff --git a/ui/native/components/feature/chat/DirectChatHeader.tsx b/ui/native/components/feature/chat/DirectChatHeader.tsx index 1cac864..1e7eca7 100644 --- a/ui/native/components/feature/chat/DirectChatHeader.tsx +++ b/ui/native/components/feature/chat/DirectChatHeader.tsx @@ -1,7 +1,7 @@ import { RouteProp, useRoute } from '@react-navigation/native' import { Text, Theme, useTheme } from '@rneui/themed' import React from 'react' -import { View, StyleSheet } from 'react-native' +import { StyleSheet, View } from 'react-native' import { selectChatMember } from '@fedi/common/redux' diff --git a/ui/native/components/feature/chat/EmbeddedJoinGroupButton.tsx b/ui/native/components/feature/chat/EmbeddedJoinGroupButton.tsx index 4d20d4b..a5ed4be 100644 --- a/ui/native/components/feature/chat/EmbeddedJoinGroupButton.tsx +++ b/ui/native/components/feature/chat/EmbeddedJoinGroupButton.tsx @@ -3,7 +3,7 @@ import { useNavigation } from '@react-navigation/native' import { Button, Text, Theme, useTheme } from '@rneui/themed' import React from 'react' import { useTranslation } from 'react-i18next' -import { View, StyleSheet } from 'react-native' +import { StyleSheet, View } from 'react-native' import { useToast } from '@fedi/common/hooks/toast' import { encodeFediMatrixRoomUri } from '@fedi/common/utils/matrix' diff --git a/ui/native/components/feature/chat/GroupHeader.tsx b/ui/native/components/feature/chat/GroupHeader.tsx index 0ebbc33..5d9f743 100644 --- a/ui/native/components/feature/chat/GroupHeader.tsx +++ b/ui/native/components/feature/chat/GroupHeader.tsx @@ -2,7 +2,7 @@ import { RouteProp, useRoute } from '@react-navigation/native' import { Text, Theme, useTheme } from '@rneui/themed' import { t } from 'i18next' import React from 'react' -import { View, StyleSheet } from 'react-native' +import { StyleSheet, View } from 'react-native' import { selectChatGroup } from '@fedi/common/redux' diff --git a/ui/native/components/feature/chat/GroupIcon.tsx b/ui/native/components/feature/chat/GroupIcon.tsx index 2582773..db0629b 100644 --- a/ui/native/components/feature/chat/GroupIcon.tsx +++ b/ui/native/components/feature/chat/GroupIcon.tsx @@ -1,9 +1,6 @@ -import React from 'react' - import { ChatGroup } from '@fedi/common/types' -import Avatar from '../../ui/Avatar' -import { AvatarSize } from '../../ui/Avatar' +import Avatar, { AvatarSize } from '../../ui/Avatar' type GroupIconProps = { chat: Pick diff --git a/ui/native/components/feature/chat/LegacyChatTile.tsx b/ui/native/components/feature/chat/LegacyChatTile.tsx index 385fe95..f37bdea 100644 --- a/ui/native/components/feature/chat/LegacyChatTile.tsx +++ b/ui/native/components/feature/chat/LegacyChatTile.tsx @@ -1,5 +1,4 @@ import { Text, Theme, useTheme } from '@rneui/themed' -import React from 'react' import { useTranslation } from 'react-i18next' import { Pressable, StyleSheet, View } from 'react-native' @@ -11,8 +10,7 @@ import { makePaymentText } from '@fedi/common/utils/chat' import { DEFAULT_GROUP_NAME } from '../../../constants' import { useAppSelector } from '../../../state/hooks' -import Avatar from '../../ui/Avatar' -import { AvatarSize } from '../../ui/Avatar' +import Avatar, { AvatarSize } from '../../ui/Avatar' import GroupIcon from './GroupIcon' type LegacyChatTileProps = { diff --git a/ui/native/components/feature/chat/MessageInput.tsx b/ui/native/components/feature/chat/MessageInput.tsx index 13a33b8..58c6d24 100644 --- a/ui/native/components/feature/chat/MessageInput.tsx +++ b/ui/native/components/feature/chat/MessageInput.tsx @@ -15,12 +15,15 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context' import { theme as fediTheme } from '@fedi/common/constants/theme' import { useToast } from '@fedi/common/hooks/toast' +import { useDebouncedEffect } from '@fedi/common/hooks/util' import { + selectChatDrafts, selectMatrixRoom, selectMatrixRoomIsReadOnly, + setChatDraft, } from '@fedi/common/redux' -import { useAppSelector } from '../../../state/hooks' +import { useAppDispatch, useAppSelector } from '../../../state/hooks' import SvgImage, { SvgImageSize } from '../../ui/SvgImage' import ChatWalletButton from './ChatWalletButton' @@ -39,16 +42,26 @@ const MessageInput: React.FC = ({ const { theme } = useTheme() const insets = useSafeAreaInsets() const existingRoom = useAppSelector(s => selectMatrixRoom(s, id)) + const dispatch = useAppDispatch() const toast = useToast() const isReadOnly = useAppSelector(s => selectMatrixRoomIsReadOnly(s, id)) - const [messageText, setMessageText] = useState('') + const drafts = useAppSelector(s => selectChatDrafts(s)) const [inputHeight, setInputHeight] = useState( theme.sizes.minMessageInputHeight, ) const [keyboardHeight, setKeyboardHeight] = useState(0) + const [messageText, setMessageText] = useState(drafts[id] ?? '') const inputRef = useRef(null) + useDebouncedEffect( + () => { + dispatch(setChatDraft({ roomId: id, text: messageText })) + }, + [messageText, dispatch], + 500, + ) + useEffect(() => { const keyboardShownListener = Keyboard.addListener( 'keyboardWillShow', @@ -77,7 +90,7 @@ const MessageInput: React.FC = ({ } catch (err) { toast.error(t, err, 'errors.chat-unavailable') } - }, [isSending, messageText, onMessageSubmitted, toast, t]) + }, [isSending, messageText, onMessageSubmitted, toast, setMessageText, t]) // Re-focus input after it had been disabled const inputDisabled = isSending || isReadOnly diff --git a/ui/native/components/feature/chat/MessagesList.tsx b/ui/native/components/feature/chat/MessagesList.tsx index 1dcd4de..a2a0445 100644 --- a/ui/native/components/feature/chat/MessagesList.tsx +++ b/ui/native/components/feature/chat/MessagesList.tsx @@ -1,5 +1,5 @@ import { useNavigation } from '@react-navigation/native' -import { Theme, useTheme, Text } from '@rneui/themed' +import { Text, Theme, useTheme } from '@rneui/themed' import React, { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { diff --git a/ui/native/components/feature/federations/CommunityTile.tsx b/ui/native/components/feature/federations/CommunityTile.tsx index d74c0bc..3559c23 100644 --- a/ui/native/components/feature/federations/CommunityTile.tsx +++ b/ui/native/components/feature/federations/CommunityTile.tsx @@ -1,5 +1,4 @@ import { Text, Theme, useTheme } from '@rneui/themed' -import React from 'react' import { StyleSheet, View } from 'react-native' import { useAmountFormatter } from '@fedi/common/hooks/amount' diff --git a/ui/native/components/feature/federations/FederationSelector.tsx b/ui/native/components/feature/federations/FederationSelector.tsx index 64e0698..809f484 100644 --- a/ui/native/components/feature/federations/FederationSelector.tsx +++ b/ui/native/components/feature/federations/FederationSelector.tsx @@ -7,8 +7,8 @@ import { selectActiveFederation } from '@fedi/common/redux' import { useAppSelector, usePrevious } from '../../../state/hooks' import { - DrawerNavigationHook, DRAWER_NAVIGATION_ID, + DrawerNavigationHook, NavigationHook, } from '../../../types/navigation' import HoloGradient from '../../ui/HoloGradient' diff --git a/ui/native/components/feature/federations/PopupFederationCountdown.tsx b/ui/native/components/feature/federations/PopupFederationCountdown.tsx index ad7f7a0..9017334 100644 --- a/ui/native/components/feature/federations/PopupFederationCountdown.tsx +++ b/ui/native/components/feature/federations/PopupFederationCountdown.tsx @@ -1,13 +1,13 @@ -import { Theme, useTheme, Text, Overlay, Button } from '@rneui/themed' +import { Button, Overlay, Text, Theme, useTheme } from '@rneui/themed' import React, { useState } from 'react' import { Trans, useTranslation } from 'react-i18next' import { + Linking, Pressable, StyleProp, StyleSheet, - ViewStyle, View, - Linking, + ViewStyle, } from 'react-native' import { usePopupFederationInfo } from '@fedi/common/hooks/federation' diff --git a/ui/native/components/feature/fedimods/AuthOverlay.tsx b/ui/native/components/feature/fedimods/AuthOverlay.tsx index 7530f73..34afc5b 100644 --- a/ui/native/components/feature/fedimods/AuthOverlay.tsx +++ b/ui/native/components/feature/fedimods/AuthOverlay.tsx @@ -4,12 +4,10 @@ import { Trans, useTranslation } from 'react-i18next' import { RejectionError } from 'webln' import { useToast } from '@fedi/common/hooks/toast' -import { selectActiveFederationId } from '@fedi/common/redux' import { lnurlAuth } from '@fedi/common/utils/lnurl' import { makeLog } from '@fedi/common/utils/log' import { fedimint } from '../../../bridge' -import { useAppSelector } from '../../../state/hooks' import { FediMod, ParsedLnurlAuth } from '../../../types' import CustomOverlay from '../../ui/CustomOverlay' @@ -30,15 +28,14 @@ export const AuthOverlay: React.FC = ({ }) => { const { t } = useTranslation() const toast = useToast() - const federationId = useAppSelector(selectActiveFederationId) const [isLoading, setIsLoading] = useState(false) // Overlay components for LNURL-Auth UX const handleAccept = async () => { setIsLoading(true) try { - if (!lnurlAuthRequest || !federationId) throw new Error() - await lnurlAuth(fedimint, federationId, lnurlAuthRequest) + if (!lnurlAuthRequest) throw new Error() + await lnurlAuth(fedimint, lnurlAuthRequest) onAccept() } catch (e) { log.error('Failed to LNURL auth', e) diff --git a/ui/native/components/feature/fedimods/FediModBrowserHeader.tsx b/ui/native/components/feature/fedimods/FediModBrowserHeader.tsx index 168ff66..956687e 100644 --- a/ui/native/components/feature/fedimods/FediModBrowserHeader.tsx +++ b/ui/native/components/feature/fedimods/FediModBrowserHeader.tsx @@ -47,6 +47,7 @@ const FediModBrowserHeader: React.FC = ({ caption medium numberOfLines={1} + ellipsizeMode="tail" adjustsFontSizeToFit style={style.titleText}> {fediMod.title} @@ -79,8 +80,12 @@ const styles = (theme: Theme) => flexShrink: 0, }, titleContainer: { + display: 'flex', flexGrow: 1, + flexShrink: 1, + flexDirection: 'row', alignItems: 'center', + overflow: 'hidden', }, arrow: { paddingHorizontal: 0, diff --git a/ui/native/components/feature/fedimods/GenerateEcashoverlay.tsx b/ui/native/components/feature/fedimods/GenerateEcashoverlay.tsx index ee8f247..2a0da91 100644 --- a/ui/native/components/feature/fedimods/GenerateEcashoverlay.tsx +++ b/ui/native/components/feature/fedimods/GenerateEcashoverlay.tsx @@ -7,7 +7,7 @@ import { RejectionError } from 'webln' import { useMinMaxSendAmount, useRequestForm } from '@fedi/common/hooks/amount' import { useToast } from '@fedi/common/hooks/toast' import { useUpdatingRef } from '@fedi/common/hooks/util' -import { selectActiveFederationId } from '@fedi/common/redux' +import { selectActiveFederation } from '@fedi/common/redux' import amountUtils from '@fedi/common/utils/AmountUtils' import { BridgeError } from '@fedi/common/utils/fedimint' import { makeLog } from '@fedi/common/utils/log' @@ -34,7 +34,7 @@ export const GenerateEcashOverlay: React.FC = ({ const { t } = useTranslation() const { theme } = useTheme() const toast = useToast() - const federationId = useAppSelector(selectActiveFederationId) + const activeFederation = useAppSelector(selectActiveFederation) const onRejectRef = useUpdatingRef(onReject) const onAcceptRef = useUpdatingRef(onAccept) const [submitAttempts, setSubmitAttempts] = useState(0) @@ -44,7 +44,9 @@ export const GenerateEcashOverlay: React.FC = ({ useRequestForm({ ecashRequest }) // Ecash notes are generated from your current balance // Instead of an almost-unbound balance from useRequestForm, set the upper bound to the active user's balance - const { maximumAmount } = useMinMaxSendAmount() + const { maximumAmount } = useMinMaxSendAmount({ + selectedPaymentFederation: true, + }) // Reset form when it appears const isShowing = Boolean(ecashRequest) @@ -65,12 +67,12 @@ export const GenerateEcashOverlay: React.FC = ({ try { setIsLoading(true) - if (!federationId) throw new Error() + if (!activeFederation) throw new Error() const msats = amountUtils.satToMsat(inputAmount) const res = await fedimint.generateEcash( msats as MSats, - federationId, + activeFederation.id, ) onAcceptRef.current(res.ecash) @@ -101,7 +103,13 @@ export const GenerateEcashOverlay: React.FC = ({ contents={{ title: t('feature.stabilitypool.enter-deposit-amount'), body: ( - + = ({ minimumAmount={minimumAmount} maximumAmount={maximumAmount} readOnly={!!exactAmount} - verb={t('words.request')} + verb={t('words.deposit')} onChangeAmount={amount => { setSubmitAttempts(0) setInputAmount(amount) diff --git a/ui/native/components/feature/fedimods/MakeInvoiceOverlay.tsx b/ui/native/components/feature/fedimods/MakeInvoiceOverlay.tsx index 987dcb1..d17ba29 100644 --- a/ui/native/components/feature/fedimods/MakeInvoiceOverlay.tsx +++ b/ui/native/components/feature/fedimods/MakeInvoiceOverlay.tsx @@ -38,8 +38,8 @@ export const MakeInvoiceOverlay: React.FC = ({ const { t } = useTranslation() const { theme } = useTheme() const toast = useToast() - const { generateInvoice } = useBridge() const federationId = useAppSelector(selectActiveFederationId) + const { generateInvoice } = useBridge(federationId) const onRejectRef = useUpdatingRef(onReject) const onAcceptRef = useUpdatingRef(onAccept) const [submitAttempts, setSubmitAttempts] = useState(0) @@ -108,7 +108,7 @@ export const MakeInvoiceOverlay: React.FC = ({ } contents={{ title: exactAmount - ? t('feature.fedimods.wants-to-pay-you', { + ? t('feature.fedimods.wants-to-send-you', { fediMod: fediMod.title, }) : t('feature.fedimods.enter-amount-to-withdraw', { diff --git a/ui/native/components/feature/fedimods/NostrSignOverlay.tsx b/ui/native/components/feature/fedimods/NostrSignOverlay.tsx index 1b5319a..eead99d 100644 --- a/ui/native/components/feature/fedimods/NostrSignOverlay.tsx +++ b/ui/native/components/feature/fedimods/NostrSignOverlay.tsx @@ -4,7 +4,6 @@ import { Trans, useTranslation } from 'react-i18next' import { RejectionError } from 'webln' import { useToast } from '@fedi/common/hooks/toast' -import { selectActiveFederationId } from '@fedi/common/redux' import { makeLog } from '@fedi/common/utils/log' import { getNostrEventDisplay } from '@fedi/common/utils/nostr' import { @@ -14,7 +13,6 @@ import { import { eventHashFromEvent } from '@fedi/injections/src/injectables/nostr/utils' import { fedimint } from '../../../bridge' -import { useAppSelector } from '../../../state/hooks' import { FediMod } from '../../../types' import CustomOverlay from '../../ui/CustomOverlay' @@ -36,17 +34,16 @@ export const NostrSignOverlay: React.FC = ({ const { t } = useTranslation() const toast = useToast() const { theme } = useTheme() - const federationId = useAppSelector(selectActiveFederationId) const [isLoading, setIsLoading] = useState(false) const handleAccept = async () => { log.info('Signature approved') setIsLoading(true) try { - if (!nostrEvent || !federationId) throw new Error() + if (!nostrEvent) throw new Error() const pubkey = await fedimint.getNostrPubKey() const id = eventHashFromEvent(pubkey, nostrEvent) - const result = await fedimint.signNostrEvent(id, federationId) + const result = await fedimint.signNostrEvent(id) onAccept({ id, pubkey, diff --git a/ui/native/components/feature/fedimods/SendPaymentOverlay.tsx b/ui/native/components/feature/fedimods/SendPaymentOverlay.tsx index 172779a..82cc663 100644 --- a/ui/native/components/feature/fedimods/SendPaymentOverlay.tsx +++ b/ui/native/components/feature/fedimods/SendPaymentOverlay.tsx @@ -7,7 +7,7 @@ import { RejectionError } from 'webln' import { useSendForm } from '@fedi/common/hooks/amount' import { useToast } from '@fedi/common/hooks/toast' import { useUpdatingRef } from '@fedi/common/hooks/util' -import { selectActiveFederationId } from '@fedi/common/redux' +import { selectPaymentFederation } from '@fedi/common/redux' import amountUtils from '@fedi/common/utils/AmountUtils' import { BridgeError } from '@fedi/common/utils/fedimint' import { lnurlPay } from '@fedi/common/utils/lnurl' @@ -18,6 +18,7 @@ import { useAppSelector, useBridge } from '../../../state/hooks' import { FediMod, Invoice, ParsedLnurlPay } from '../../../types' import AmountInput from '../../ui/AmountInput' import CustomOverlay from '../../ui/CustomOverlay' +import FederationWalletSelector from '../send/FederationWalletSelector' const log = makeLog('SendPaymentOverlay') @@ -39,8 +40,8 @@ export const SendPaymentOverlay: React.FC = ({ const { t } = useTranslation() const { theme } = useTheme() const toast = useToast() - const { payInvoice } = useBridge() - const federationId = useAppSelector(selectActiveFederationId) + const paymentFederation = useAppSelector(selectPaymentFederation) + const { payInvoice } = useBridge(paymentFederation?.id) const [submitAttempts, setSubmitAttempts] = useState(0) const [amountInputKey, setAmountInputKey] = useState(0) const [isLoading, setIsLoading] = useState(false) @@ -72,14 +73,14 @@ export const SendPaymentOverlay: React.FC = ({ setIsLoading(true) try { - if (!federationId) throw new Error() + if (!paymentFederation) throw new Error() if (invoice) { const res = await payInvoice(invoice.invoice) onAcceptRef.current(res) } else if (lnurlPayment) { const res = await lnurlPay( fedimint, - federationId, + paymentFederation.id, lnurlPayment, amountUtils.satToMsat(inputAmount), ) @@ -115,7 +116,14 @@ export const SendPaymentOverlay: React.FC = ({ fediMod: fediMod.title, }), body: ( - + + ({ } const handleAuth = async () => { - if (!activeFederationId || parsedData.type !== ParserDataType.LnurlAuth) - return + if (parsedData.type !== ParserDataType.LnurlAuth) return setIsLoading(true) try { - await lnurlAuth(fedimint, activeFederationId, parsedData.data) + await lnurlAuth(fedimint, parsedData.data) onSuccess(parsedData) } catch (err) { toast.error(t, err) diff --git a/ui/native/components/feature/omni/OmniInput.tsx b/ui/native/components/feature/omni/OmniInput.tsx index e2fe5a9..b4be754 100644 --- a/ui/native/components/feature/omni/OmniInput.tsx +++ b/ui/native/components/feature/omni/OmniInput.tsx @@ -2,7 +2,7 @@ import Clipboard from '@react-native-clipboard/clipboard' import { Theme, useTheme } from '@rneui/themed' import { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' -import { View, StyleSheet } from 'react-native' +import { StyleSheet, View } from 'react-native' import { useToast } from '@fedi/common/hooks/toast' import { useUpdatingRef } from '@fedi/common/hooks/util' diff --git a/ui/native/components/feature/omni/OmniQrScanner.tsx b/ui/native/components/feature/omni/OmniQrScanner.tsx index 46b1a79..567c545 100644 --- a/ui/native/components/feature/omni/OmniQrScanner.tsx +++ b/ui/native/components/feature/omni/OmniQrScanner.tsx @@ -1,8 +1,7 @@ import { Button, Text, Theme, useTheme } from '@rneui/themed' import React from 'react' import { useTranslation } from 'react-i18next' -import { View, StyleSheet } from 'react-native' -import { Linking } from 'react-native' +import { Linking, StyleSheet, View } from 'react-native' import { EdgeInsets, useSafeAreaInsets } from 'react-native-safe-area-context' import { diff --git a/ui/native/components/feature/onboarding/FederationPreview.tsx b/ui/native/components/feature/onboarding/FederationPreview.tsx index dab6b87..cdfbd7b 100644 --- a/ui/native/components/feature/onboarding/FederationPreview.tsx +++ b/ui/native/components/feature/onboarding/FederationPreview.tsx @@ -1,5 +1,5 @@ import { useNavigation } from '@react-navigation/native' -import { Button, Card, Text, Theme, useTheme } from '@rneui/themed' +import { Button, Card, Switch, Text, Theme, useTheme } from '@rneui/themed' import React, { useState } from 'react' import { Trans, useTranslation } from 'react-i18next' import { ScrollView, StyleSheet, View } from 'react-native' @@ -20,7 +20,7 @@ import AcceptTermsOfService from './AcceptTermsOfService' type Props = { federation: JoinPreview - onJoin: () => void | Promise + onJoin: (recoverFromScratch?: boolean) => void | Promise onBack: () => void } @@ -30,11 +30,16 @@ const FederationPreview: React.FC = ({ federation, onJoin, onBack }) => { const [showTerms, setShowTerms] = useState(false) const showJoinFederation = shouldShowJoinFederation(federation.meta) const [isJoining, setIsJoining] = useState(false) + const [selectedRecoverFromScratch, setSelectedRecoverFromScratch] = + useState(false) const tosUrl = getFederationTosUrl(federation.meta) const welcomeMessage = getFederationWelcomeMessage(federation.meta) const isSupported = getIsFederationSupported(federation) const popupInfo = usePopupFederationInfo(federation.meta) const navigation = useNavigation() + const isReturningMember = + federation.hasWallet && + federation.returningMemberStatus.type === 'returningMember' const style = styles(theme) @@ -89,7 +94,7 @@ const FederationPreview: React.FC = ({ federation, onJoin, onBack }) => { if (showTerms) { return ( onJoin()} + onAccept={() => onJoin(selectedRecoverFromScratch)} onReject={() => setShowTerms(false)} federation={federation} /> @@ -102,7 +107,7 @@ const FederationPreview: React.FC = ({ federation, onJoin, onBack }) => { setShowTerms(true) } else { try { - await onJoin() + await onJoin(selectedRecoverFromScratch) } catch { /* no-op, onJoin should handle */ } @@ -110,21 +115,18 @@ const FederationPreview: React.FC = ({ federation, onJoin, onBack }) => { setIsJoining(false) } - const welcomeTitle = - federation.hasWallet && - federation.returningMemberStatus.type === 'returningMember' - ? t('feature.onboarding.welcome-back-to-federation', { - federation: federation?.name, - }) - : t('feature.onboarding.welcome-to-federation', { - federation: federation?.name, - }) + const welcomeTitle = isReturningMember + ? t('feature.onboarding.welcome-back-to-federation', { + federation: federation?.name, + }) + : t('feature.onboarding.welcome-to-federation', { + federation: federation?.name, + }) const welcomeInstructions = federation.hasWallet && federation.returningMemberStatus.type === 'newMember' ? t('feature.onboarding.welcome-instructions-new') - : federation.hasWallet && - federation.returningMemberStatus.type === 'returningMember' + : isReturningMember ? t('feature.onboarding.welcome-instructions-returning') : t('feature.onboarding.welcome-instructions-unknown') @@ -166,6 +168,28 @@ const FederationPreview: React.FC = ({ federation, onJoin, onBack }) => { {showJoinFederation ? ( <> + {isReturningMember && ( + + + + {t( + 'feature.federations.recover-from-scratch', + )} + + + {t( + 'feature.federations.recover-from-scratch-warning', + )} + + + { + setSelectedRecoverFromScratch(value) + }} + /> + + )}