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

No contract change. `ocp.lock` points at the same upstream commit as `0.2.0`, and the generated
Kotlin and Swift are unchanged. Swift consumers have nothing to gain from this release.

### Added

- The Kotlin artifact now ships R8 keep rules, at `META-INF/proguard/ocp-client-protocol.pro`:

```proguard
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
<fields>;
}
```

protobuf-javalite ships no keep rules of its own, so until now every Android consumer had to
write one, and the obvious `-keep class * extends GeneratedMessageLite { *; }` is far wider
than javalite needs. javalite resolves *fields* reflectively — the schema built from
`newMessageInfo` looks up `java.lang.reflect.Field` by the generated `<name>_` field — while
builders and message methods are reached from ordinary call sites, so R8 traces those without
help. `-keepclassmembers` also does not keep the class, so a message type nothing references is
still removed entirely.

On upgrading, an Android consumer can delete its own protobuf keep rules. Dropping the wide
pair from `code-android-app` cut 25,542 live methods and 568 live classes, and moved its R8
optimization score from 89.3% to 96.3%.

The rule is deliberately not scoped to `com.codeinc.opencode.gen.**`. The well-known types (`Any`, `Timestamp`,
`Duration`, `Struct`) come from protobuf-javalite itself, and other dependencies ship generated
messages with no rules of their own, so a package-scoped rule would leave those broken under R8
full mode. Both contract packages ship identical rule text; R8 collapses them into one entry.

## 0.2.0

Synced to [`ocp-protobuf-api@ea6418c5`](https://github.com/code-payments/ocp-protobuf-api/commit/ea6418c5561e16771d456062be2fcbd3ddeb9caf).
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@ They are separate packages because the contracts are: flipcash2 does not import
## Install

```kotlin
implementation("com.flipcash:ocp-client-protocol:0.1.0")
implementation("com.flipcash:ocp-client-protocol:0.3.0")
```

```swift
.package(url: "https://github.com/code-payments/ocp-client-protocol", from: "0.1.0")
.package(url: "https://github.com/code-payments/ocp-client-protocol", from: "0.3.0")
```

`code-android-app` pins the version in `gradle/libs.versions.toml`. `code-ios-app` pins it in
`FlipcashAPI/Package.swift` and re-exports the module, so app code still reaches these types
through `import FlipcashAPI`.

The Kotlin artifact ships its own R8 keep rules, so an Android consumer needs no protobuf keep
rule of its own.

## What it contains

Four services — `Account`, `Currency`, `Messaging`, `Transaction` — plus the shared
Expand All @@ -38,6 +41,8 @@ this package was generated from.
proto/ contract, synced from upstream at the SHA in ocp.lock
proto_deps/validate/ include-path dependency, never generated
Sources/OCPClientProtocol/ generated Swift, committed (SPM ships source)
src/main/resources/
META-INF/proguard/ R8 keep rules, shipped to Kotlin consumers
build.gradle.kts Kotlin generation + publishing
scripts/
sync-protos.sh pull upstream at a pinned SHA, re-namespace
Expand Down
19 changes: 19 additions & 0 deletions src/main/resources/META-INF/proguard/ocp-client-protocol.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# R8/ProGuard rules for the generated protobuf messages in this artifact.
#
# protobuf-javalite ships no keep rules of its own, so without this every consumer
# app has to write it. javalite resolves fields reflectively: the schema built from
# newMessageInfo looks up java.lang.reflect.Field by the generated `<name>_` field.
# Methods and builders are reached from ordinary call sites, so R8 traces them
# without help and they are deliberately not kept here.
#
# -keepclassmembers does not keep the class, so a message type nothing references
# is still removed entirely. The rule only applies to messages that survive on
# their own merit.
#
# Deliberately not scoped to this artifact's own package. The well-known types
# (Any, Timestamp, Duration, Struct) come from protobuf-javalite itself, and other
# dependencies ship generated messages with no rules of their own; a rule scoped to
# the generated package would leave those broken under R8 full mode.
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
<fields>;
}
Loading