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
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,54 @@ called out explicitly even when nothing else did.
release notes, so a version with no entry here does not release. Write the entry in the same PR that
syncs the contract, while the diff is still in front of you.

## 0.20.0

Synced to [`flipcash2-protobuf-api@733ea7f9`](https://github.com/code-payments/flipcash2-protobuf-api/commit/733ea7f9f33291b9631f0176fab5485acf161fab),
picking up [#147](https://github.com/code-payments/flipcash2-protobuf-api/pull/147),
[#148](https://github.com/code-payments/flipcash2-protobuf-api/pull/148) and
[#149](https://github.com/code-payments/flipcash2-protobuf-api/pull/149) (docs only). `community.v1`
is new. `activity.v1`, `chat.v1`, `intent.v1` and `messaging.v1` moved.

This release adds the Community service, paid reaction boosts and a holdings summary on gated group
chats. Everything is additive. Two enums gained a case, appended at the end, so no existing value
moved. An exhaustive `switch` or `when` over either enum needs the new case before it compiles.

### Added

- `community.v1.Community`, a new service with one RPC, `GetCommunity`. It looks a community up by
`mint` and returns `CommunityMetadata` (`mint`, `name`, `leader`, and up to 25
`top_holder_chats`), or `NOT_FOUND`.
- Reaction boosts. A payer puts money behind a reaction they already hold on a group message:
- `intent.v1.ChatMetadata.reaction_boost` (oneof field 5), a `ReactionBoost` naming the
`message_id` and `emoji`.
- A boost that pays two people, the sender and the group's creator split 80/20, is an ocp
`SendPublicMultiPayment`, so it needs `ocp-client-protocol` 0.8.0 or later. A boost that pays
one person is a `SendPublicPayment`.
- `messaging.v1.Reactor.boost_usd` (field 4), `EmojiReaction.boost_usd` (field 6),
`ReactionUpdate.boost_usd` (field 8) and `ReactionUpdate.actor_boost_usd` (field 9).
- `ReactionUpdate.Action.BOOSTED = 3`.
- `RemoveReactionResponse.Result.CANNOT_REMOVE_BOOSTED = 3`. A boosted reaction is permanent.
- `activity.v1.BoostedReaction`, set as `boosted_reaction` (field 3) on both
`DirectlySentCryptoNotificationMetadata` and `ReceivedCryptoNotificationMetadata` when the
payment was a boost.
- `chat.v1.Metadata.holdings_summary` (field 18), a `HoldingsSummary` of the group members' holdings
of the currency the group is gated on (`mint`, `quarks`, `holder_count`, `as_of`). It is set only
for public groups gated on a single Flipcash-launched currency with enough holders. It is a
periodic snapshot, and no event announces a change.

### Changed

- Reactor lists, `sample_reactors` and `ReactionSummary.reactions` now sort boosted entries first,
by `boost_usd` descending, then fall back to the previous order. Nothing changed on the wire, but
a client that re-sorts by `version` alone will disagree with the server.
- `GetReactors` now documents that a paging token the server no longer recognises, such as one
issued under the old order, is answered with the first page rather than an error. Don't keep
tokens across sessions.

### Unchanged

Nothing was renumbered. No service, RPC, message, field or enum case was removed or changed type.

## 0.19.0

Synced to [`flipcash2-protobuf-api@1897108a`](https://github.com/code-payments/flipcash2-protobuf-api/commit/1897108ae75e032fc5f7de13cf6e9cadcec9deda),
Expand Down
4 changes: 2 additions & 2 deletions Sources/Flipcash2ClientProtocol/ContractInfo.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Generated by scripts/generate-swift.sh. Do not edit.

public enum Flipcash2ContractInfo {
public static let version = "0.19.0-dev"
public static let protoCommit = "1897108ae75e032fc5f7de13cf6e9cadcec9deda"
public static let version = "0.20.0-dev"
public static let protoCommit = "733ea7f9f33291b9631f0176fab5485acf161fab"

public static var isLocal: Bool { protoCommit == localSentinel }

Expand Down
137 changes: 135 additions & 2 deletions Sources/Flipcash2ClientProtocol/activity_v1_model.pb.swift
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,19 @@ public struct Flipcash_Activity_V1_DirectlySentCryptoNotificationMetadata: Senda
set {destinationIdentifier = .userID(newValue)}
}

/// Set when the payment boosted a reaction (see BoostedReaction). A boost
/// that paid one person names them in destination_identifier; one that
/// paid both the message's sender and the group's creator names neither,
/// and payment_amount is the whole boost.
public var boostedReaction: Flipcash_Activity_V1_BoostedReaction {
get {return _boostedReaction ?? Flipcash_Activity_V1_BoostedReaction()}
set {_boostedReaction = newValue}
}
/// Returns true if `boostedReaction` has been explicitly set.
public var hasBoostedReaction: Bool {return self._boostedReaction != nil}
/// Clears the value of `boostedReaction`. Subsequent reads from it will return its default value.
public mutating func clearBoostedReaction() {self._boostedReaction = nil}

public var unknownFields = SwiftProtobuf.UnknownStorage()

public enum OneOf_DestinationIdentifier: Equatable, Sendable {
Expand All @@ -345,6 +358,8 @@ public struct Flipcash_Activity_V1_DirectlySentCryptoNotificationMetadata: Senda
}

public init() {}

fileprivate var _boostedReaction: Flipcash_Activity_V1_BoostedReaction? = nil
}

public struct Flipcash_Activity_V1_ReceivedCryptoNotificationMetadata: Sendable {
Expand All @@ -370,6 +385,19 @@ public struct Flipcash_Activity_V1_ReceivedCryptoNotificationMetadata: Sendable
set {sourceIdentifier = .userID(newValue)}
}

/// Set when the payment was the recipient's share of a boost of a
/// reaction (see BoostedReaction), paid to them as the boosted message's
/// sender or the group's creator. source_identifier names the payer, and
/// payment_amount is the recipient's share alone.
public var boostedReaction: Flipcash_Activity_V1_BoostedReaction {
get {return _boostedReaction ?? Flipcash_Activity_V1_BoostedReaction()}
set {_boostedReaction = newValue}
}
/// Returns true if `boostedReaction` has been explicitly set.
public var hasBoostedReaction: Bool {return self._boostedReaction != nil}
/// Clears the value of `boostedReaction`. Subsequent reads from it will return its default value.
public mutating func clearBoostedReaction() {self._boostedReaction = nil}

public var unknownFields = SwiftProtobuf.UnknownStorage()

public enum OneOf_SourceIdentifier: Equatable, Sendable {
Expand All @@ -379,6 +407,57 @@ public struct Flipcash_Activity_V1_ReceivedCryptoNotificationMetadata: Sendable
}

public init() {}

fileprivate var _boostedReaction: Flipcash_Activity_V1_BoostedReaction? = nil
}

/// The reaction a payment boosted: the payer's reaction with emoji on a
/// message in a group chat (see intent.v1.ChatMetadata.ReactionBoost). It is
/// what the payment was for when it was made and is not kept up to date: the
/// message may since have been deleted, and the viewer may no longer be a
/// member of the chat.
public struct Flipcash_Activity_V1_BoostedReaction: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.

/// The group chat the boosted message is in.
public var chatID: Flipcash_Common_V1_ChatId {
get {return _chatID ?? Flipcash_Common_V1_ChatId()}
set {_chatID = newValue}
}
/// Returns true if `chatID` has been explicitly set.
public var hasChatID: Bool {return self._chatID != nil}
/// Clears the value of `chatID`. Subsequent reads from it will return its default value.
public mutating func clearChatID() {self._chatID = nil}

/// The message whose reaction was boosted.
public var messageID: Flipcash_Messaging_V1_MessageId {
get {return _messageID ?? Flipcash_Messaging_V1_MessageId()}
set {_messageID = newValue}
}
/// Returns true if `messageID` has been explicitly set.
public var hasMessageID: Bool {return self._messageID != nil}
/// Clears the value of `messageID`. Subsequent reads from it will return its default value.
public mutating func clearMessageID() {self._messageID = nil}

/// The emoji of the boosted reaction.
public var emoji: Flipcash_Messaging_V1_Emoji {
get {return _emoji ?? Flipcash_Messaging_V1_Emoji()}
set {_emoji = newValue}
}
/// Returns true if `emoji` has been explicitly set.
public var hasEmoji: Bool {return self._emoji != nil}
/// Clears the value of `emoji`. Subsequent reads from it will return its default value.
public mutating func clearEmoji() {self._emoji = nil}

public var unknownFields = SwiftProtobuf.UnknownStorage()

public init() {}

fileprivate var _chatID: Flipcash_Common_V1_ChatId? = nil
fileprivate var _messageID: Flipcash_Messaging_V1_MessageId? = nil
fileprivate var _emoji: Flipcash_Messaging_V1_Emoji? = nil
}

public struct Flipcash_Activity_V1_WithdrewCryptoNotificationMetadata: Sendable {
Expand Down Expand Up @@ -837,7 +916,7 @@ extension Flipcash_Activity_V1_Notification: SwiftProtobuf.Message, SwiftProtobu

extension Flipcash_Activity_V1_DirectlySentCryptoNotificationMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".DirectlySentCryptoNotificationMetadata"
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}phone\0\u{3}user_id\0")
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}phone\0\u{3}user_id\0\u{3}boosted_reaction\0")

public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
Expand Down Expand Up @@ -871,6 +950,7 @@ extension Flipcash_Activity_V1_DirectlySentCryptoNotificationMetadata: SwiftProt
self.destinationIdentifier = .userID(v)
}
}()
case 3: try { try decoder.decodeSingularMessageField(value: &self._boostedReaction) }()
default: break
}
}
Expand All @@ -892,19 +972,23 @@ extension Flipcash_Activity_V1_DirectlySentCryptoNotificationMetadata: SwiftProt
}()
case nil: break
}
try { if let v = self._boostedReaction {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}

public static func ==(lhs: Flipcash_Activity_V1_DirectlySentCryptoNotificationMetadata, rhs: Flipcash_Activity_V1_DirectlySentCryptoNotificationMetadata) -> Bool {
if lhs.destinationIdentifier != rhs.destinationIdentifier {return false}
if lhs._boostedReaction != rhs._boostedReaction {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

extension Flipcash_Activity_V1_ReceivedCryptoNotificationMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ReceivedCryptoNotificationMetadata"
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}phone\0\u{3}user_id\0")
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}phone\0\u{3}user_id\0\u{3}boosted_reaction\0")

public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
Expand Down Expand Up @@ -938,6 +1022,7 @@ extension Flipcash_Activity_V1_ReceivedCryptoNotificationMetadata: SwiftProtobuf
self.sourceIdentifier = .userID(v)
}
}()
case 3: try { try decoder.decodeSingularMessageField(value: &self._boostedReaction) }()
default: break
}
}
Expand All @@ -959,11 +1044,59 @@ extension Flipcash_Activity_V1_ReceivedCryptoNotificationMetadata: SwiftProtobuf
}()
case nil: break
}
try { if let v = self._boostedReaction {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}

public static func ==(lhs: Flipcash_Activity_V1_ReceivedCryptoNotificationMetadata, rhs: Flipcash_Activity_V1_ReceivedCryptoNotificationMetadata) -> Bool {
if lhs.sourceIdentifier != rhs.sourceIdentifier {return false}
if lhs._boostedReaction != rhs._boostedReaction {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

extension Flipcash_Activity_V1_BoostedReaction: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".BoostedReaction"
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}chat_id\0\u{3}message_id\0\u{1}emoji\0")

public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularMessageField(value: &self._chatID) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._messageID) }()
case 3: try { try decoder.decodeSingularMessageField(value: &self._emoji) }()
default: break
}
}
}

public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182
try { if let v = self._chatID {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try { if let v = self._messageID {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try { if let v = self._emoji {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}

public static func ==(lhs: Flipcash_Activity_V1_BoostedReaction, rhs: Flipcash_Activity_V1_BoostedReaction) -> Bool {
if lhs._chatID != rhs._chatID {return false}
if lhs._messageID != rhs._messageID {return false}
if lhs._emoji != rhs._emoji {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
Expand Down
Loading
Loading