Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,9 @@ Baseline.json
remote-config-defaults.plist
service-data.plist
GoogleService-Info.plist

/SourcePackages
/brainwallet/launch-resources/GoogleService-Info.plist
/brainwallet/launch-resources/remote-config-defaults.plist
/brainwallet/launch-resources/service-data.plist
# Storekit
/Storekit
*.storekit
Brainwallet-StoreKit-v1.storekit

# Storekit
*.storekit
/fastlane/report.xml
**/fastlane/test_output/
## Games protection
Expand Down
6 changes: 6 additions & 0 deletions BrainwalletHybrid.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "2660"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "75A2A78F1DA5934300A983D8"
BuildableName = "Brainwallet.app"
BlueprintName = "brainwallet"
ReferencedContainer = "container:brainwallet.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
queueDebuggingEnableBacktraceRecording = "Yes">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "75A2A78F1DA5934300A983D8"
BuildableName = "Brainwallet.app"
BlueprintName = "brainwallet"
ReferencedContainer = "container:brainwallet.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<StoreKitConfigurationFileReference
identifier = "../brainwallet/PreLaunchResources/bw-iap-config-v2.storekit">
</StoreKitConfigurationFileReference>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "75A2A78F1DA5934300A983D8"
BuildableName = "Brainwallet.app"
BlueprintName = "brainwallet"
ReferencedContainer = "container:brainwallet.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,6 @@
identifier = "San Francisco, CA, USA"
referenceType = "1">
</LocationScenarioReference>
<StoreKitConfigurationFileReference
identifier = "../Private/general-purpose/BrainwalletiOSPrivateGeneralPurpose/brainwallet-private-general-purpose.storekit">
</StoreKitConfigurationFileReference>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
98 changes: 98 additions & 0 deletions BrainwalletUnitTests/Settings Tests/NetworkFeeTierTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//
// NetworkFeeTierTests.swift
// brainwallet
//
// Covers the fee-tier math backing the Network Fee picker in
// SettingsLitecoinDetailView (litoshis-per-tier, nearest-tier lookup for a
// persisted preference, and litoshi -> fiat formatting).
//
// Copyright © 2025 Grunt Software, LTD. All rights reserved.

@testable import brainwallet
import XCTest

class NetworkFeeTierTests: XCTestCase {

private let fees = Fees(luxury: 66746, regular: 25000, economy: 8000, timestamp: 0)
private let usdRate = Rate(code: "USD", name: "US Dollar", rate: 60.0, lastTimestamp: Date())

// MARK: - litoshis(from:)

func testLitoshisFromMapsEachTierToItsFeesField() {
XCTAssertEqual(NetworkFeeTier.economy.litoshis(from: fees), fees.economy)
XCTAssertEqual(NetworkFeeTier.regular.litoshis(from: fees), fees.regular)
XCTAssertEqual(NetworkFeeTier.luxury.litoshis(from: fees), fees.luxury)
}

// MARK: - closest(to:in:)

func testClosestReturnsExactTierOnExactMatch() {
XCTAssertEqual(NetworkFeeTier.closest(to: Int(fees.economy), in: fees), .economy)
XCTAssertEqual(NetworkFeeTier.closest(to: Int(fees.regular), in: fees), .regular)
XCTAssertEqual(NetworkFeeTier.closest(to: Int(fees.luxury), in: fees), .luxury)
}

func testClosestPicksNearerNeighborBetweenTwoTiers() {
// Between economy (8000) and regular (25000); nearer to economy.
XCTAssertEqual(NetworkFeeTier.closest(to: 10_000, in: fees), .economy)
// Between regular (25000) and luxury (66746); nearer to luxury.
XCTAssertEqual(NetworkFeeTier.closest(to: 60_000, in: fees), .luxury)
}

func testClosestClampsToEconomyBelowLowestTier() {
XCTAssertEqual(NetworkFeeTier.closest(to: 0, in: fees), .economy)
}

func testClosestClampsToLuxuryAboveHighestTier() {
XCTAssertEqual(NetworkFeeTier.closest(to: 1_000_000, in: fees), .luxury)
}

func testClosestBreaksTiesTowardTheLowerTier() {
// Exactly halfway between economy (8000) and regular (25000) is 16500;
// a tie should favor the lower (economy) tier.
let tieFees = Fees(luxury: 30000, regular: 20000, economy: 10000, timestamp: 0)
XCTAssertEqual(NetworkFeeTier.closest(to: 15000, in: tieFees), .economy)
// Halfway between regular (20000) and luxury (30000) is 25000.
XCTAssertEqual(NetworkFeeTier.closest(to: 25000, in: tieFees), .regular)
}

func testClosestFallsBackToDefaultValuesWhenNothingIsStored() {
// UserDefaults.userSetPreferredNetworkFee falls back to Fees.usingDefaultValues.luxury
// when the user has never picked a fee — confirm that round-trips to .luxury.
let defaults = Fees.usingDefaultValues
let storedFee = Int(defaults.luxury)
XCTAssertEqual(NetworkFeeTier.closest(to: storedFee, in: defaults), .luxury)
}

// MARK: - formattedFiatAmount(litoshis:rate:)

func testFormattedFiatAmountConvertsLitoshisThroughLTCToFiat() {
// 100_000_000 litoshis == 1 LTC == $60 at a $60/LTC rate.
let result = NetworkFeeTier.formattedFiatAmount(litoshis: 100_000_000, rate: usdRate)
XCTAssertEqual(result, "60.000 USD")
}

func testFormattedFiatAmountForRealisticRegularFee() {
// 25000 litoshis at $60/LTC = 0.00025 LTC * 60 = 0.015.
let result = NetworkFeeTier.formattedFiatAmount(litoshis: fees.regular, rate: usdRate)
XCTAssertEqual(result, "0.015 USD")
}

func testFormattedFiatAmountIsEmptyWhenFeeIsZero() {
XCTAssertEqual(NetworkFeeTier.formattedFiatAmount(litoshis: 0, rate: usdRate), "")
}

func testFormattedFiatAmountIsEmptyWhenRateIsZero() {
let noRate = Rate(code: "", name: "", rate: 0.0, lastTimestamp: Date())
XCTAssertEqual(NetworkFeeTier.formattedFiatAmount(litoshis: fees.luxury, rate: noRate), "")
}

// MARK: - CaseIterable ordering (Picker tags rely on rawValue == 0/1/2)

func testAllCasesOrderMatchesPickerTagOrder() {
XCTAssertEqual(NetworkFeeTier.allCases.map(\.rawValue), [0, 1, 2])
XCTAssertEqual(NetworkFeeTier.economy.rawValue, 0)
XCTAssertEqual(NetworkFeeTier.regular.rawValue, 1)
XCTAssertEqual(NetworkFeeTier.luxury.rawValue, 2)
}
}
4 changes: 2 additions & 2 deletions BrainwalletUnitTests/Settings Tests/SettingsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class SettingsHelpersTests: XCTestCase {
// MARK: - Constants Tests

func testClosedRowHeight() {
XCTAssertEqual(closedRowHeight, 65.0, "closedRowHeight should be 65.0")
XCTAssertEqual(closedRowHeight, 50.0, "closedRowHeight should be 50.0")
}

func testToggleRowHeight() {
Expand Down Expand Up @@ -42,7 +42,7 @@ class SettingsHelpersTests: XCTestCase {
}

func testExpandArrowSize() {
XCTAssertEqual(expandArrowSize, 20.0, "expandArrowSize should be 20.0")
XCTAssertEqual(expandArrowSize, 16.0, "expandArrowSize should be 16.0")
}

func testPickerViewHeight() {
Expand Down
2 changes: 1 addition & 1 deletion Modules/core
2 changes: 1 addition & 1 deletion Private/general-purpose
Loading
Loading