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
62 changes: 62 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,68 @@ 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.19.0

Synced to [`flipcash2-protobuf-api@1897108a`](https://github.com/code-payments/flipcash2-protobuf-api/commit/1897108ae75e032fc5f7de13cf6e9cadcec9deda),
picking up [#139](https://github.com/code-payments/flipcash2-protobuf-api/pull/139) (docs only),
[#140](https://github.com/code-payments/flipcash2-protobuf-api/pull/140),
[#141](https://github.com/code-payments/flipcash2-protobuf-api/pull/141),
[#142](https://github.com/code-payments/flipcash2-protobuf-api/pull/142),
[#143](https://github.com/code-payments/flipcash2-protobuf-api/pull/143),
[#144](https://github.com/code-payments/flipcash2-protobuf-api/pull/144),
[#145](https://github.com/code-payments/flipcash2-protobuf-api/pull/145) and
[#146](https://github.com/code-payments/flipcash2-protobuf-api/pull/146). `poll.v1` is new;
`intent.v1` and `messaging.v1` moved; `chat.v1` changed only in comments.

This release adds polls, payments in group chats, link previews and structured system messages. One
enum moved, which is wire-compatible but breaks source in both languages.

### Moved

- `ChatMetadata.DmPayment.Action` is now the top-level enum `PaymentAction`, shared by DM and
group payments. Its cases keep their values (`DEFAULT = 0`, `SEND = 1`, `TIP = 2`) and
`DmPayment.action` keeps field 2, so the wire format is unchanged. Code naming the old type has
to be updated: `Flipcash_Intent_V1_ChatMetadata.DmPayment.Action` becomes
`Flipcash_Intent_V1_PaymentAction` in Swift, and `ChatMetadata.DmPayment.Action` becomes
`PaymentAction` in Kotlin.

### Added

- A `Poll` service in `poll.v1` with `CreatePoll`, `GetPoll`, `GetPolls` and `Vote`, and its model:
count or balance-weighted polls of 2 to 10 options, single or multiple choice, a required end
time 5 minutes to 30 days out, and question text that is plaintext in a group that is not
private and encrypted in a private one. Results come back as count, balance, ranked or withheld,
and every vote result model carries `total_voters`.
- `WidgetContent.poll` (field 2), a `PollWidget` carrying only the poll's ID. In a group that is not
private, `SendMessage` accepts it only from the poll's creator, in the poll's own chat, while the
poll is `OPEN`. A private group sends it inside `EncryptedContent`, where clients do those checks
and render a mismatch as unsupported.
- `ChatMetadata.group_payment` (field 4), a `GroupPayment` for paying another member of a group
chat. The payment's destination owner names the recipient, who must be a member. Only `DEFAULT`
and `SEND` are accepted; the server denies `TIP`.
- `CashContent.receiver` (field 3, previously reserved), the user who received the cash. It is
always set in a group chat. In a DM it is set on new messages only, so a client reading older DM
messages still has to treat the other member as the receiver when it is unset.
- `TextContent.link_previews` (field 2), at most one `LinkPreview` with a `url`, `title`, optional
`description` and optional `image`. The sending device builds the preview, so its title,
description and image are the sender's claim; the comments on `LinkPreview` spell out the
validation rules and how clients have to render the host.
- `SystemContent.type`, a required oneof whose first case is `user_joined` (field 2). `UserJoined`
names the user and how they joined: `direct`, or `admitted` with the user who let them in.
`fallback_text` is unchanged and still always set; a client renders it only for a variant it
does not recognize.

### Changed

- `EncryptedContent.ciphertext` may now be up to 28672 bytes, up from 17408, to fit a maximum-length
text with a link preview.

### Unchanged

Nothing was renumbered. Every result enum in this release is new, so no existing case moved. Apart
from the `PaymentAction` move, no existing field changed type or meaning, and no service, RPC,
message or enum case was removed.

## 0.18.0

Synced to [`flipcash2-protobuf-api@9d44350b`](https://github.com/code-payments/flipcash2-protobuf-api/commit/9d44350b8d4d8eda9d63cff405238bd0e2920409),
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.18.0-dev"
public static let protoCommit = "9f67566fd0297a27ad2de7a98474634adf4d3a24"
public static let version = "0.19.0-dev"
public static let protoCommit = "1897108ae75e032fc5f7de13cf6e9cadcec9deda"

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

Expand Down
160 changes: 119 additions & 41 deletions Sources/Flipcash2ClientProtocol/intent_v1_model.pb.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,47 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP
typealias Version = _2
}

/// The action being performed for a payment in a chat
public enum Flipcash_Intent_V1_PaymentAction: SwiftProtobuf.Enum, Swift.CaseIterable {
public typealias RawValue = Int

/// Same as SEND: the payment is shown as "sent", not "tipped"
case `default` // = 0
case send // = 1
case tip // = 2
case UNRECOGNIZED(Int)

public init() {
self = .default
}

public init?(rawValue: Int) {
switch rawValue {
case 0: self = .default
case 1: self = .send
case 2: self = .tip
default: self = .UNRECOGNIZED(rawValue)
}
}

public var rawValue: Int {
switch self {
case .default: return 0
case .send: return 1
case .tip: return 2
case .UNRECOGNIZED(let i): return i
}
}

// The compiler won't synthesize support with the UNRECOGNIZED case.
public static let allCases: [Flipcash_Intent_V1_PaymentAction] = [
.default,
.send,
.tip,
]

}

public struct Flipcash_Intent_V1_AppMetadata: Sendable {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
Expand Down Expand Up @@ -78,11 +119,20 @@ public struct Flipcash_Intent_V1_ChatMetadata: Sendable {
set {type = .dmPayment(newValue)}
}

public var groupPayment: Flipcash_Intent_V1_ChatMetadata.GroupPayment {
get {
if case .groupPayment(let v)? = type {return v}
return Flipcash_Intent_V1_ChatMetadata.GroupPayment()
}
set {type = .groupPayment(newValue)}
}

public var unknownFields = SwiftProtobuf.UnknownStorage()

public enum OneOf_Type: Equatable, Sendable {
case contactDmPayment(Flipcash_Intent_V1_ChatMetadata.ContactDmPayment)
case dmPayment(Flipcash_Intent_V1_ChatMetadata.DmPayment)
case groupPayment(Flipcash_Intent_V1_ChatMetadata.GroupPayment)

}

Expand Down Expand Up @@ -129,7 +179,8 @@ public struct Flipcash_Intent_V1_ChatMetadata: Sendable {

public var location: Flipcash_Intent_V1_ChatMetadata.DmPayment.Location = .flipcard

public var action: Flipcash_Intent_V1_ChatMetadata.DmPayment.Action = .default
/// The action being performed for the payment
public var action: Flipcash_Intent_V1_PaymentAction = .default

public var unknownFields = SwiftProtobuf.UnknownStorage()

Expand Down Expand Up @@ -168,46 +219,26 @@ public struct Flipcash_Intent_V1_ChatMetadata: Sendable {

}

/// The action being performed for the payment
public enum Action: SwiftProtobuf.Enum, Swift.CaseIterable {
public typealias RawValue = Int

/// Same as SEND: the payment is shown as "sent", not "tipped"
case `default` // = 0
case send // = 1
case tip // = 2
case UNRECOGNIZED(Int)

public init() {
self = .default
}
public init() {}
}

public init?(rawValue: Int) {
switch rawValue {
case 0: self = .default
case 1: self = .send
case 2: self = .tip
default: self = .UNRECOGNIZED(rawValue)
}
}
/// For sending a payment directly to another member of a group chat. The
/// chat_id must be a group, and the payment's destination owner account
/// names the recipient, who must be a Flipcash user and a member of the
/// group. The sender must be able to speak in the group: the payment posts
/// a CashContent message into it as the sender, naming the recipient as
/// its receiver.
public struct GroupPayment: 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.

public var rawValue: Int {
switch self {
case .default: return 0
case .send: return 1
case .tip: return 2
case .UNRECOGNIZED(let i): return i
}
}
/// The action being performed for the payment. Only DEFAULT and SEND
/// are supported today, and the payment is shown as SENT; the server
/// denies TIP.
public var action: Flipcash_Intent_V1_PaymentAction = .default

// The compiler won't synthesize support with the UNRECOGNIZED case.
public static let allCases: [Flipcash_Intent_V1_ChatMetadata.DmPayment.Action] = [
.default,
.send,
.tip,
]

}
public var unknownFields = SwiftProtobuf.UnknownStorage()

public init() {}
}
Expand All @@ -221,6 +252,10 @@ public struct Flipcash_Intent_V1_ChatMetadata: Sendable {

fileprivate let _protobuf_package = "flipcash.intent.v1"

extension Flipcash_Intent_V1_PaymentAction: SwiftProtobuf._ProtoNameProviding {
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0DEFAULT\0\u{1}SEND\0\u{1}TIP\0")
}

extension Flipcash_Intent_V1_AppMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".AppMetadata"
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}chat\0")
Expand Down Expand Up @@ -269,7 +304,7 @@ extension Flipcash_Intent_V1_AppMetadata: SwiftProtobuf.Message, SwiftProtobuf._

extension Flipcash_Intent_V1_ChatMetadata: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ChatMetadata"
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}chat_id\0\u{3}contact_dm_payment\0\u{3}dm_payment\0")
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{3}chat_id\0\u{3}contact_dm_payment\0\u{3}dm_payment\0\u{3}group_payment\0")

public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
Expand Down Expand Up @@ -304,6 +339,19 @@ extension Flipcash_Intent_V1_ChatMetadata: SwiftProtobuf.Message, SwiftProtobuf.
self.type = .dmPayment(v)
}
}()
case 4: try {
var v: Flipcash_Intent_V1_ChatMetadata.GroupPayment?
var hadOneofValue = false
if let current = self.type {
hadOneofValue = true
if case .groupPayment(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.type = .groupPayment(v)
}
}()
default: break
}
}
Expand All @@ -326,6 +374,10 @@ extension Flipcash_Intent_V1_ChatMetadata: SwiftProtobuf.Message, SwiftProtobuf.
guard case .dmPayment(let v)? = self.type else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
}()
case .groupPayment?: try {
guard case .groupPayment(let v)? = self.type else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
}()
case nil: break
}
try unknownFields.traverse(visitor: &visitor)
Expand Down Expand Up @@ -417,6 +469,32 @@ extension Flipcash_Intent_V1_ChatMetadata.DmPayment.Location: SwiftProtobuf._Pro
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0FLIPCARD\0\u{1}CHAT\0")
}

extension Flipcash_Intent_V1_ChatMetadata.DmPayment.Action: SwiftProtobuf._ProtoNameProviding {
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{2}\0DEFAULT\0\u{1}SEND\0\u{1}TIP\0")
extension Flipcash_Intent_V1_ChatMetadata.GroupPayment: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Flipcash_Intent_V1_ChatMetadata.protoMessageName + ".GroupPayment"
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}action\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.decodeSingularEnumField(value: &self.action) }()
default: break
}
}
}

public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.action != .default {
try visitor.visitSingularEnumField(value: self.action, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}

public static func ==(lhs: Flipcash_Intent_V1_ChatMetadata.GroupPayment, rhs: Flipcash_Intent_V1_ChatMetadata.GroupPayment) -> Bool {
if lhs.action != rhs.action {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,9 @@ public struct Flipcash_Messaging_V1_SendMessageRequest: Sendable {
/// - TextContent
/// - ReplyContent
/// - MediaContent
/// - WidgetContent with a PollWidget, in group chats that are not private
/// only. A private group sends it inside EncryptedContent. See
/// PollWidget for when it is accepted.
/// - EncryptedContent, in DMs and private groups only. A private group
/// accepts nothing else.
///
Expand Down
Loading
Loading