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
2 changes: 1 addition & 1 deletion FlipcashAPI/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ let contractDependencies: [Package.Dependency] = protoLocalRoot.map { root in
]
} ?? [
.package(url: "https://github.com/code-payments/ocp-client-protocol", exact: "0.2.0"),
.package(url: "https://github.com/code-payments/flipcash2-client-protocol", exact: "0.1.0"),
.package(url: "https://github.com/code-payments/flipcash2-client-protocol", exact: "0.2.0"),
]

let package = Package(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,10 @@ extension FlipClient {
public func updateTipCard(_ customization: TipCardCustomization, owner: KeyPair) async throws {
try await profileService.updateTipCard(color: customization.colorProto, owner: owner)
}

/// Sets the minimum fee another user must pay to initialize a DM chat with
/// the caller, replacing any fee already set.
public func setMinDmChatInitFee(_ fee: FiatAmount, owner: KeyPair) async throws {
try await profileService.setMinDmChatInitFee(fee, owner: owner)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,35 @@ final class ProfileService: Sendable {
throw ErrorUpdateTipCard.unknown
}
}

/// Sets the minimum fee another user must pay to initialize a DM chat with
/// the caller, replacing any fee already set.
func setMinDmChatInitFee(_ fee: FiatAmount, owner: KeyPair) async throws {
logger.info("Setting minimum DM chat init fee")

var request = Flipcash_Profile_V1_SetMinDmChatInitFeeRequest()
request.minDmChatInitFee = .with {
$0.currency = fee.currency.rawValue
$0.nativeAmount = fee.doubleValue
}
request.auth = owner.authFor(message: request)

do {
let response = try await service.setMinDmChatInitFee(request, options: .unaryDefault)
let error = ErrorSetMinDmChatInitFee(rawValue: response.result.rawValue) ?? .unknown
guard error == .ok else {
logger.error("Failed to set minimum DM chat init fee", metadata: ["error": "\(error)"])
throw error
}
logger.info("Minimum DM chat init fee set")
} catch let error as ErrorSetMinDmChatInitFee {
throw error
} catch let error as RPCError {
throw ErrorSetMinDmChatInitFee.from(transportError: error)
} catch {
throw ErrorSetMinDmChatInitFee.unknown
}
}
}

// MARK: - Errors -
Expand Down Expand Up @@ -225,6 +254,28 @@ extension ErrorUpdateTipCard: ServerError, TransportClassifiableError {
}
}

public enum ErrorSetMinDmChatInitFee: Int, Error {
case ok
case denied
/// e.g. unsupported currency, or amount outside the allowed range.
case invalidAmount
case unknown = -1
case transportFailure = -2
case cancelled = -3
case rejected = -4
}

extension ErrorSetMinDmChatInitFee: ServerError, TransportClassifiableError {
public var reportingLevel: ErrorReportingLevel {
switch self {
case .ok, .transportFailure: .suppressed
case .cancelled: .info
case .denied, .invalidAmount: .info
case .unknown, .rejected: .error
}
}
}

public enum ErrorProfile: Error, Sendable {
case denied
case invalidDisplayName
Expand Down
19 changes: 15 additions & 4 deletions FlipcashCore/Sources/FlipcashCore/Models/Profile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ public struct Profile: Codable, Equatable, Sendable {
/// Public — the server returns it for any user, not just the caller.
public let username: Username?

/// The minimum fee another user must pay to initialize a DM chat with this
/// user. Public — returned for any user, not just the caller. `nil` when
/// the user hasn't set one, in which case the server default applies.
public let minDmChatInitFee: FiatAmount?

public var isPhoneVerified: Bool {
phone != nil
}
Expand All @@ -56,7 +61,7 @@ public struct Profile: Codable, Equatable, Sendable {
phone != nil && phone?.e164 != previous?.phone?.e164
}

public init(displayName: String?, phone: String?, email: String?, profilePicture: ProfilePicture? = nil, joinedAt: Date? = nil, tipCardCustomization: TipCardCustomization? = nil, userID: UserID? = nil, username: Username? = nil) throws {
public init(displayName: String?, phone: String?, email: String?, profilePicture: ProfilePicture? = nil, joinedAt: Date? = nil, tipCardCustomization: TipCardCustomization? = nil, userID: UserID? = nil, username: Username? = nil, minDmChatInitFee: FiatAmount? = nil) throws {

// Only parse phone if it's not empty
var parsedPhone: Phone?
Expand All @@ -80,11 +85,12 @@ public struct Profile: Codable, Equatable, Sendable {
joinedAt: joinedAt,
tipCardCustomization: tipCardCustomization,
userID: userID,
username: username
username: username,
minDmChatInitFee: minDmChatInitFee
)
}

public init(displayName: String?, phone: Phone?, email: String?, profilePicture: ProfilePicture? = nil, joinedAt: Date? = nil, tipCardCustomization: TipCardCustomization? = nil, userID: UserID? = nil, username: Username? = nil) {
public init(displayName: String?, phone: Phone?, email: String?, profilePicture: ProfilePicture? = nil, joinedAt: Date? = nil, tipCardCustomization: TipCardCustomization? = nil, userID: UserID? = nil, username: Username? = nil, minDmChatInitFee: FiatAmount? = nil) {
self.displayName = displayName
self.phone = phone
self.email = email
Expand All @@ -93,6 +99,7 @@ public struct Profile: Codable, Equatable, Sendable {
self.tipCardCustomization = tipCardCustomization
self.userID = userID
self.username = username
self.minDmChatInitFee = minDmChatInitFee
}
}

Expand Down Expand Up @@ -126,7 +133,11 @@ extension Profile {
joinedAt: proto.hasJoinTs ? proto.joinTs.date : nil,
tipCardCustomization: proto.hasTipCardCustomization ? TipCardCustomization(proto.tipCardCustomization) : nil,
userID: proto.hasUserID ? try? UUID(data: proto.userID.value) : nil,
username: proto.hasUsername ? Username(proto.username) : nil
username: proto.hasUsername ? Username(proto.username) : nil,
minDmChatInitFee: proto.hasMinDmChatInitFee ? FiatAmount(
value: Decimal(proto.minDmChatInitFee.nativeAmount),
currency: try CurrencyCode(currencyCode: proto.minDmChatInitFee.currency)
) : nil
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct TransportClassificationTests {
@Test func errorUnlinkEmail() { assertClassifies(ErrorUnlinkEmail.self) }
@Test func errorFetchProfile() { assertClassifies(ErrorFetchProfile.self) }
@Test func errorUpdateTipCard() { assertClassifies(ErrorUpdateTipCard.self) }
@Test func errorSetMinDmChatInitFee() { assertClassifies(ErrorSetMinDmChatInitFee.self) }
@Test func errorBlocklist() { assertClassifies(ErrorBlocklist.self) }
@Test func errorRateHistory() { assertClassifies(ErrorRateHistory.self) }
@Test func errorGetSwap() { assertClassifies(ErrorGetSwap.self) }
Expand Down