xmtp / xmtp-react-native-old

ARCHIVED: See the README for alternative approaches to building an XMTP app with React Native.
MIT License
2 stars 0 forks source link

iOS Support #10

Open nakajima opened 1 year ago

nakajima commented 1 year ago

Here are my learnings after trying to make the iOS SDK available in React Native.

We distribute our SDK via Swift Package Manager (the recommended approach for all Swift packages these days). React Native doesn't support this though, and given the lack of activity on the issue proposing it, I don't think we can expect it to happen any time soon. So Swift Package Manager was out.

Next we tried to add CocoaPods support to the SDK. This was a non-starter as well.

gRPC Swift, perhaps the most important dependency in our SDK, dropped support for CocoaPods in April '22 (see here). This happened after SwiftNIO, its networking dependency dropped support for it. I considered trying to fork these projects to add support but for SwiftNIO, that would be extremely difficult. From the announcement:

However, supporting it comes with additional maintenance cost: each release requires the SwiftNIO team to publish 40+ Podspecs over the various SwiftNIO repositories. While this is semi-automated, it is still a time consuming task which is prone to failure.

So that was that.

The final idea was to try to compile the SDK into a large static library. This ran into a wall when it was discovered that the swift-atomics package, a dependency of SwiftNIO, doesn't support being packaged in a static library (see this issue for more details).

Given all of these issues, we can't support the current iOS SDK in React Native at this time.

michaelx11 commented 1 year ago

Even if we nuke the GRPC dependency, looks like web3.swift still brings in Swift-NIO:

.
├── proto<https://github.com/xmtp/proto@unspecified>
│   └── swift-protobuf<https://github.com/apple/swift-protobuf.git@1.21.0>
├── secp256k1.swift<https://github.com/GigaBitcoin/secp256k1.swift.git@unspecified>
├── web3.swift<https://github.com/argentlabs/web3.swift@1.6.0>
│   ├── bigint<https://github.com/attaswift/BigInt@5.3.0>
│   ├── generic-json-swift<https://github.com/iwill/generic-json-swift@2.0.2>
│   ├── secp256k1.swift<https://github.com/GigaBitcoin/secp256k1.swift.git@unspecified>
│   ├── websocket-kit<https://github.com/vapor/websocket-kit.git@2.8.0>
│   │   ├── swift-nio<https://github.com/apple/swift-nio.git@2.50.0>
│   │   │   ├── swift-atomics<https://github.com/apple/swift-atomics.git@1.1.0>
│   │   │   └── swift-collections<https://github.com/apple/swift-collections.git@1.0.4>
│   │   ├── swift-nio-extras<https://github.com/apple/swift-nio-extras.git@1.19.0>
│   │   │   └── swift-nio<https://github.com/apple/swift-nio.git@2.50.0>
│   │   │       ├── swift-atomics<https://github.com/apple/swift-atomics.git@1.1.0>
│   │   │       └── swift-collections<https://github.com/apple/swift-collections.git@1.0.4>
│   │   ├── swift-nio-ssl<https://github.com/apple/swift-nio-ssl.git@2.23.0>
│   │   │   └── swift-nio<https://github.com/apple/swift-nio.git@2.50.0>
│   │   │       ├── swift-atomics<https://github.com/apple/swift-atomics.git@1.1.0>
│   │   │       └── swift-collections<https://github.com/apple/swift-collections.git@1.0.4>
│   │   ├── swift-nio-transport-services<https://github.com/apple/swift-nio-transport-services.git@1.16.0>
│   │   │   ├── swift-nio<https://github.com/apple/swift-nio.git@2.50.0>
│   │   │   │   ├── swift-atomics<https://github.com/apple/swift-atomics.git@1.1.0>
│   │   │   │   └── swift-collections<https://github.com/apple/swift-collections.git@1.0.4>
│   │   │   └── swift-atomics<https://github.com/apple/swift-atomics.git@1.1.0>
│   │   └── swift-atomics<https://github.com/apple/swift-atomics.git@1.1.0>
│   └── swift-log<https://github.com/apple/swift-log.git@1.5.2>
├── gzipswift<https://github.com/1024jp/GzipSwift@5.2.0>
└── swift-docc-plugin<https://github.com/apple/swift-docc-plugin.git@1.2.0>
    └── swift-docc-symbolkit<https://github.com/apple/swift-docc-symbolkit@1.0.0>
nakajima commented 1 year ago

I feel pretty confident we can remove that web3 dependency altogether.

michaelx11 commented 1 year ago

I'm taking a second look at the cocoapods route. Assuming (naively) the invariant that: "if a cocoapod exists for a dependency, it'll work if we convert xmtp-ios to a cocoapod" then:

secp256k1 doesn't but I can shove that functionality into the Rust framework pretty quickly. It might be good cause the Swift library appears to be more experimental than the RustCrypto ones we use.

XMTPProto isn't a cocoapod but doesn't seem crazy to either vendor it or make it one.

Finally seems like we can specify the XMTPRustSwift.xcframework as a vendored binary and just stick it in the xmtp-ios repo. Not ideal but theoretically seems fine.

I'm sure this strategy is full of holes but wanted to get your thoughts @nakajima

nakajima commented 1 year ago

Ya, I think this is the way. React Native already knows about cocoapods so we should be good here.

I am confused about how web3.swift has a cocoapod but still relies on SwiftNIO. Looking at the pod spec, it doesn't seem like they're pulling in websocket-kit which is what was bringing in SwiftNIO?

michaelx11 commented 1 year ago

Update for future reference:

We were able to string together a solution that completely unblocks xmtp-ios as the backend for a React Native app (or SDK).

https://github.com/xmtp/libxmtp/tree/michaelx_secp256k1_in_rust_swift https://github.com/xmtp/xmtp-rust-swift/tree/0.1.2-beta0 (overview of rough plan in README, but only for Swift Package side. The cocoapod work can be traced by following podspecs) https://github.com/xmtp/xmtp-ios/releases/tag/0.1.3-beta0

Two cocoapods were manually pushed (XMTPRust => 0.1.2-beta0) and (XMTP => 0.1.3-beta0)

Current work is productionizing the Rust side of things.