Compare commits

..

17 Commits
0.1.0 ... main

Author SHA1 Message Date
Pat Nakajima 56c4f9f5d0
Add group chat features (#109)
* sendable

* resolved

* Add some group chat codecs

* Add isGroup to Conversation
2023-06-13 13:45:12 -07:00
Daniel McCartney b5db26c75d
fix: use the proper production URL (#107) 2023-06-06 12:41:39 -07:00
Daniel McCartney 83d76e897e
feat: add batch message listing, use updated libxmtp (#106) 2023-06-02 16:16:17 -07:00
Pat Nakajima dc2040a6b9
Cocoapods integration (#91)
* feat: crappy XMTPRustSwift usage

* feat: get Rust networking selftest in

* feat: add gRPC selftest

* test: grpc test

* feat: cleaned up Swift package to use local reference, works great

* feat: query using gRPC library works

* fix: refactor a bit but query still works

* feat: with local_test_only_005 branch, publish/query pass

* feat: all tests pass with rustClient

* feat: checkpoint - no more GRPC dependency

* Use remote package

* checkpoint: Getting closer to building, need to fix secp256k1 issues

* wip: commit code calling secp256k1

* wip

* wip

* Bring in the proto types for now

* Make version match XMTPRust

* add swift version

* wip

* Integrate xmtp-rust-swift 0.2.0-beta0 (#97)

* wip: does not build yet, no progress on subscribe needs AsyncIterator

* fix: some tests pass, subscribe still not implemented

* feat: initialize rust client outside of GRPCApiClient

* feat: partial integration of newest Rust<>Swift bindings

* feat: implement polling subscribe

* test: add test for content in testStreamingMessagesFromV2Conversations

* feat: working if you comment out NotificationService logic

* Get tests building again

* Cleanups

* Format

* Ignore pods

* Updates

* Update package.resolved

* Fix lint

* Fix more lint

* update pod

* Bump XMTPRust version

* Get example app building again

* Move everything to cocoapods

* Get rid of cocoapods for the example app

* Try to get XMTP buildable for testing

* Fix test building

* wip: tests seemed to pass

* fix: reset the cocoapod

* fix: tests pass with new paging info changes, removed some printlns, need to address QueryResponse ownership

* fix: upgrade to XMTPRust=0.2.2-beta0 to attempt to fix Package.resolved issue in Xcode cloud

* fix: delete Package.resolved from xcshareddata

* fix: attempt to use Package.resolved from a passing commit

* fix: open Example app and let swift re-resolve

* fix: use package.resolved after running example app successfully

* fix: try to undo changes to XMTP.xcscheme

---------

Co-authored-by: Michael Xu <michaelx@xmtp.com>

* Use Buf to generate proto code (#93)

* fix: remove proto dependency from Package.swift (#101)

* feat: remove proto Package.swift dependency

* fix: try a pod install

* fix: local tests failing due to improper mem copying, .bytes extension not available in pods (#102)

* fix: re-introduce 16.0 restriction

* fix: passes pod lint now

* fix: use exact secp256k1 version

* fix: utilize QueryResponse paging info

* fix: use 0.2.2-beta0 XMTPRust

* feat: prep for 0.2.0-alpha0 test release

* fix: commit updated dependency manifests

* fix: make sure to return cursor information from response

* style: fix indent in the ApiClient.swift file

* test: remove empty no-op gRPC test

* style: fix indents and remove imports

* fix: remove unnecessary Data extension and replace with existing for RustVecs

* test: add a PaginationTest class

* test: need to do unused client initializations to upload contact bundles

* fix: remove unnecessary comment and remaining unneeded Data<>RustVec extensions

* docs: add comment and flush out podspec description

* style: add spaces to example podfile

* test: remove extraneous takesAWallet test

* test: remove unnecessary test lines in TestHelper

* docs: fix comment about empty PublishResponse

* test: fix pagination test race condition with duplicate convos

* fix: attempt to see if xcode cloud works without cocoapods

* fix: attempt to revert example app to main

* fix: updated Package.resolved

* fix: delete unnecessary new schemes that are missing from main

* test: pagination tests should be local node only

---------

Co-authored-by: Michael Xu <michaelx@xmtp.com>
Co-authored-by: Michael Xu <michaeljxu11@gmail.com>
Co-authored-by: Nicholas Molnar <nicholas@xmtp.com>
Co-authored-by: Nicholas Molnar <65710+neekolas@users.noreply.github.com>
2023-05-19 12:16:17 -07:00
Elise Alix a18da1eba5
fix: use exact 0.10 for secp library (#96) 2023-04-24 09:57:46 -04:00
Elise Alix c2c8ae2183
fix: use version 0.10 for secp library (#95) 2023-04-21 14:12:13 -07:00
Jennifer Hasegawa 5514cf65a7
docs: update README (#92) 2023-04-20 14:47:14 -07:00
Pat Nakajima cc22d69774
Fix example app (#90)
- Import UIKit to fix UIApplication not found
- Bring back XMTPiOSExample scheme
2023-04-17 10:30:58 -07:00
Jennifer Hasegawa dac55b2dc8
Prepare README for GA (#82)
* first pass

* Remote capabilities that haven't been added yet

* Port examples to swift, remove some comments

* Fix typo

* add a couple of links

* prep for ref doc url

* add ref doc link, refinements

---------

Co-authored-by: Pat Nakajima <patnakajima@gmail.com>
2023-04-05 12:20:23 -07:00
Pat Nakajima 7a669c1d36
Try building docs (#88)
* Try building docs

* Fix typo

* Updates

* One job

* fix

* Try another fix

* Separate steps

* Check out the code first

* Update hosting path

* --transform-for-static-hosting
2023-04-04 15:33:09 -07:00
Pat Nakajima be5c90c696
try swifttools 5.6 (#85) 2023-03-29 09:46:39 -07:00
Pat Nakajima 911721bb10
Update README.md (#84)
Just to try to get SPI to build docs
2023-03-28 10:05:21 -07:00
Pat Nakajima b4cf49660b
Add .spi.yml (#83)
* Add .spi.yml

* Add docc dep
2023-03-22 17:20:30 +00:00
Pat Nakajima d9463d79b3
Introduce Conversation.prepareMessage (#80)
This gives back a PreparedMessage that has a messageID on it. Clients
can use this for optimistic sending purposes.
2023-03-14 19:25:34 +00:00
Pat Nakajima 8e96ec3a43
Remove multiple topic queries (#81) 2023-03-14 12:20:08 -07:00
Jazz Turner-Baggs de76b3a2a1
standardize clientVersion string (#79) 2023-03-09 08:05:43 -08:00
Pat Nakajima 167aa5b0ef
Add client.canMessage (#78) 2023-03-08 16:02:59 +00:00
100 changed files with 8470 additions and 511 deletions

47
.github/workflows/build-docs.yml vendored Normal file
View File

@ -0,0 +1,47 @@
# Simple workflow for deploying static content to GitHub Pages
name: Deploy docs content to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["main", "docs"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: macos-12
steps:
- uses: actions/checkout@v3
- name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: "Build docs"
run: swift package --allow-writing-to-directory ./docs generate-documentation --target XMTP --disable-indexing --output-path ./docs --hosting-base-path xmtp-ios --transform-for-static-hosting
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# Upload entire repository
path: './docs'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2

5
.gitignore vendored
View File

@ -1,3 +1,6 @@
XMTPiOSExample/Pods/
XMTPiOSExample/build
.DS_Store
/.build
/Packages
@ -8,5 +11,5 @@ DerivedData/
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
Package.resolved
.vscode
XMTPiOSExample/Pods

5
.spi.yml Normal file
View File

@ -0,0 +1,5 @@
version: 1
builder:
configs:
- platform: ios
documentation_targets: [XMTP]

View File

@ -1,3 +1,6 @@
excluded:
- Sources/XMTP/Proto
disabled_rules: # rule identifiers turned on by default to exclude from running
- type_name
- identifier_name

View File

@ -70,14 +70,24 @@
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A628198E292DC825004B9117"
BuildableName = "XMTPiOSExample.app"
BlueprintName = "XMTPiOSExample"
ReferencedContainer = "container:XMTPiOSExample/XMTPiOSExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

158
Package.resolved Normal file
View File

@ -0,0 +1,158 @@
{
"pins" : [
{
"identity" : "bigint",
"kind" : "remoteSourceControl",
"location" : "https://github.com/attaswift/BigInt",
"state" : {
"revision" : "0ed110f7555c34ff468e72e1686e59721f2b0da6",
"version" : "5.3.0"
}
},
{
"identity" : "connect-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/bufbuild/connect-swift",
"state" : {
"revision" : "6f5afc57f44a3ed15b9a01381ce73f84d15e43db",
"version" : "0.3.0"
}
},
{
"identity" : "generic-json-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/zoul/generic-json-swift",
"state" : {
"revision" : "0a06575f4038b504e78ac330913d920f1630f510",
"version" : "2.0.2"
}
},
{
"identity" : "gzipswift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/1024jp/GzipSwift",
"state" : {
"revision" : "7a7f17761c76a932662ab77028a4329f67d645a4",
"version" : "5.2.0"
}
},
{
"identity" : "secp256k1.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/GigaBitcoin/secp256k1.swift.git",
"state" : {
"revision" : "48fb20fce4ca3aad89180448a127d5bc16f0e44c",
"version" : "0.10.0"
}
},
{
"identity" : "swift-atomics",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-atomics.git",
"state" : {
"revision" : "919eb1d83e02121cdb434c7bfc1f0c66ef17febe",
"version" : "1.0.2"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections.git",
"state" : {
"revision" : "f504716c27d2e5d4144fa4794b12129301d17729",
"version" : "1.0.3"
}
},
{
"identity" : "swift-docc-plugin",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-docc-plugin.git",
"state" : {
"revision" : "9b1258905c21fc1b97bf03d1b4ca12c4ec4e5fda",
"version" : "1.2.0"
}
},
{
"identity" : "swift-docc-symbolkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-docc-symbolkit",
"state" : {
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
"version" : "1.0.0"
}
},
{
"identity" : "swift-log",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-log.git",
"state" : {
"revision" : "6fe203dc33195667ce1759bf0182975e4653ba1c",
"version" : "1.4.4"
}
},
{
"identity" : "swift-nio",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio.git",
"state" : {
"revision" : "edfceecba13d68c1c993382806e72f7e96feaa86",
"version" : "2.44.0"
}
},
{
"identity" : "swift-nio-ssl",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-ssl.git",
"state" : {
"revision" : "4fb7ead803e38949eb1d6fabb849206a72c580f3",
"version" : "2.23.0"
}
},
{
"identity" : "swift-nio-transport-services",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-transport-services.git",
"state" : {
"revision" : "c0d9a144cfaec8d3d596aadde3039286a266c15c",
"version" : "1.15.0"
}
},
{
"identity" : "swift-protobuf",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-protobuf.git",
"state" : {
"revision" : "ab3a58b7209a17d781c0d1dbb3e1ff3da306bae8",
"version" : "1.20.3"
}
},
{
"identity" : "web3.swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/argentlabs/web3.swift",
"state" : {
"revision" : "9da09d639d4e5d06eb59518e636b3ae957e8e9cd",
"version" : "1.3.0"
}
},
{
"identity" : "websocket-kit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/vapor/websocket-kit.git",
"state" : {
"revision" : "2d9d2188a08eef4a869d368daab21b3c08510991",
"version" : "2.6.1"
}
},
{
"identity" : "xmtp-rust-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/xmtp/xmtp-rust-swift",
"state" : {
"revision" : "41a1161cf06a86bab0aa886e450584a1191429b1",
"version" : "0.3.0-beta0"
}
}
],
"version" : 2
}

View File

@ -1,4 +1,4 @@
// swift-tools-version:5.7
// swift-tools-version: 5.6
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
@ -21,11 +21,12 @@ let package = Package(
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(url: "https://github.com/xmtp/proto", branch: "main"),
.package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", branch: "main"),
.package(url: "https://github.com/GigaBitcoin/secp256k1.swift.git", exact: "0.10.0"),
.package(url: "https://github.com/argentlabs/web3.swift", from: "1.1.0"),
.package(url: "https://github.com/1024jp/GzipSwift", from: "5.2.0"),
.package(url: "https://github.com/bufbuild/connect-swift", from: "0.3.0"),
.package(url: "https://github.com/apple/swift-docc-plugin.git", from: "1.0.0"),
.package(url: "https://github.com/xmtp/xmtp-rust-swift", from: "0.3.0-beta0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
@ -33,11 +34,11 @@ let package = Package(
.target(
name: "XMTP",
dependencies: [
.product(name: "XMTPProto", package: "proto"),
.product(name: "secp256k1", package: "secp256k1.swift"),
"web3.swift",
.product(name: "Gzip", package: "GzipSwift"),
.product(name: "Connect", package: "connect-swift"),
.product(name: "XMTPRust", package: "xmtp-rust-swift"),
]
),
.target(

205
README.md
View File

@ -1,20 +1,14 @@
# XMTP-iOS
![Lint](https://github.com/xmtp/xmtp-ios/actions/workflows/lint.yml/badge.svg) ![Status](https://img.shields.io/badge/Project_Status-Developer_Preview-yellow)
![Lint](https://github.com/xmtp/xmtp-ios/actions/workflows/lint.yml/badge.svg) ![Status](https://img.shields.io/badge/Project_Status-General_Availability-31CA54)
`xmtp-ios` provides a Swift implementation of an XMTP message API client for use with iOS apps.
Use `xmtp-ios` to build with XMTP to send messages between blockchain accounts, including DMs, notifications, announcements, and more.
This SDK is in **Developer Preview** status and ready for you to start building.
This SDK is in **General Availability** status and ready for use in production.
However, we do **not** recommend using Developer Preview software in production apps. Software in this status may change based on feedback.
Specifically, this SDK is missing this functionality:
- Specifying `apiUrl`, `keyStoreType`, `codecs`, `maxContentSize`, and `appVersion` when creating a `Client`
Follow along in the [tracking issue](https://github.com/xmtp/xmtp-ios/issues/7) for updates.
To keep up with the latest SDK developments, see the [Issues tab](https://github.com/xmtp/xmtp-ios/issues) in this repo.
To learn more about XMTP and get answers to frequently asked questions, see [FAQ about XMTP](https://xmtp.org/docs/dev-concepts/faq).
@ -24,6 +18,10 @@ To learn more about XMTP and get answers to frequently asked questions, see [FAQ
For a basic demonstration of the core concepts and capabilities of the `xmtp-ios` client SDK, see the [Example app project](https://github.com/xmtp/xmtp-ios/tree/main/XMTPiOSExample/XMTPiOSExample).
## Reference docs
> **View the reference**
> Access the [Swift client SDK reference documentation](https://xmtp.github.io/xmtp-ios/documentation/xmtp).
## Install with Swift Package Manager
@ -67,7 +65,8 @@ A client is created with `Client.create(account: SigningKey) async throws -> Cli
1. To sign the newly generated key bundle. This happens only the very first time when a key bundle is not found in storage.
2. To sign a random salt used to encrypt the key bundle in storage. This happens every time the client is started, including the very first time).
**Important:** The client connects to the XMTP `dev` environment by default. [Use `ClientOptions`](#configuring-the-client) to change this and other parameters of the network connection.
> **Important:**
> The client connects to the XMTP `dev` environment by default. [Use `ClientOptions`](#configuring-the-client) to change this and other parameters of the network connection.
```swift
import XMTP
@ -102,9 +101,11 @@ let client = try Client.from(bundle: keys, options: .init(api: .init(env: .produ
You can configure the client's network connection and key storage method with these optional parameters of `Client.create`:
| Parameter | Default | Description |
| Parameter | Default | Description |
| --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| env | `dev` | Connect to the specified XMTP network environment. Valid values include `.dev`, `.production`, or `.local`. For important details about working with these environments, see [XMTP `production` and `dev` network environments](#xmtp-production-and-dev-network-environments). |
| env | `dev` | Connect to the specified XMTP network environment. Valid values include `.dev`, `.production`, or `.local`. For important details about working with these environments, see [XMTP `production` and `dev` network environments](#xmtp-production-and-dev-network-environments). |
#### Configure `env`
```swift
// Configure the client to use the `production` network
@ -112,7 +113,16 @@ let clientOptions = ClientOptions(api: .init(env: .production))
let client = try await Client.create(account: account, options: clientOptions)
```
**Note: The `apiUrl`, `keyStoreType`, `codecs`, `maxContentSize` and `appVersion` parameters from the XMTP client SDK for JavaScript (xmtp-js) are not yet supported.**
## Configure content types
You can use custom content types by calling `Client.register`. The SDK comes with two commonly used content type codecs, `AttachmentCodec` and `RemoteAttachmentCodec`:
```swift
Client.register(AttachmentCodec())
Client.register(RemoteAttachmentCodec())
```
To learn more about using `AttachmentCodec` and `RemoteAttachmentCodec`, see [Handle different content types](#handle-different-content-types).
## Handle conversations
@ -127,7 +137,7 @@ let conversations = try await client.conversations.list()
### List existing conversations
You can get a list of all conversations that have had one or more messages exchanged in the last 30 days.
You can get a list of all conversations that have one or more messages.
```swift
let allConversations = try await client.conversations.list()
@ -140,13 +150,14 @@ for conversation in allConversations {
These conversations include all conversations for a user **regardless of which app created the conversation.** This functionality provides the concept of an [interoperable inbox](https://xmtp.org/docs/dev-concepts/interoperable-inbox), which enables a user to access all of their conversations in any app built with XMTP.
You might choose to provide an additional filtered view of conversations. To learn more, see [Handling multiple conversations with the same blockchain address](#handling-multiple-conversations-with-the-same-blockchain-address) and [Filter conversations using conversation IDs and metadata](https://xmtp.org/docs/client-sdk/javascript/tutorials/filter-conversations).
You might choose to provide an additional filtered view of conversations. To learn more, see [Handle multiple conversations with the same blockchain address](#handle-multiple-conversations-with-the-same-blockchain-address) and [Filter conversations using conversation IDs and metadata](https://xmtp.org/docs/client-sdk/javascript/tutorials/filter-conversations).
### Listen for new conversations
You can also listen for new conversations being started in real-time. This will allow apps to display incoming messages from new contacts.
**Warning: This stream will continue infinitely. To end the stream, break from the loop.**
> **Warning:**
> This stream will continue infinitely. To end the stream, break from the loop.
```swift
for try await conversation in client.conversations.stream() {
@ -170,9 +181,9 @@ let newConversation = try await client.conversations.newConversation(with: "0x3F
### Send messages
To be able to send a message, the recipient must have already created a client at least once and consequently advertised their key bundle on the network. Messages are addressed using account addresses. The message payload must be a plain string.
To be able to send a message, the recipient must have already created a client at least once and consequently advertised their key bundle on the network. Messages are addressed using account addresses. By default, the message payload supports plain strings.
**Note: Other types of content are currently not supported.**
To learn about support for other content types, see [Handle different content types](#handle-different-content-types).
```swift
let conversation = try await client.conversations.newConversation(with: "0x3F11b27F323b62B159D2642964fa27C46C841897")
@ -221,7 +232,7 @@ for try await message in conversation.streamMessages() {
}
```
### Handling multiple conversations with the same blockchain address
### Handle multiple conversations with the same blockchain address
With XMTP, you can have multiple ongoing conversations with the same blockchain address. For example, you might want to have a conversation scoped to your particular app, or even a conversation scoped to a particular item in your app.
@ -253,7 +264,7 @@ let myAppConversations = conversations.filter {
}
```
### Decoding a single message
### Decode a single message
You can decode a single `Envelope` from XMTP using the `decode` method:
@ -290,21 +301,152 @@ let decodedConversation = containerAgain.decode(with: client)
try await decodedConversation.send(text: "hi")
```
### Different types of content
## Handle different content types
All the send functions support SendOptions as an optional parameter. The contentType option allows specifying different types of content than the default simple string, which is identified with content type identifier ContentTypeText. Support for other types of content can be added by registering additional ContentCodecs with the Client. Every codec is associated with a content type identifier, ContentTypeId, which is used to signal to the Client which codec should be used to process the content that is being sent or received. See XIP-5 for more details on codecs and content types.
All of the send functions support `SendOptions` as an optional parameter. The `contentType` option allows specifying different types of content other than the default simple string standard content type, which is identified with content type identifier `ContentTypeText`.
Codecs and content types may be proposed as interoperable standards through XRCs. If there is a concern that the recipient may not be able to handle a non-standard content type, the sender can use the contentFallback option to provide a string that describes the content being sent. If the recipient fails to decode the original content, the fallback will replace it and can be used to inform the recipient what the original content was.
To learn more about content types, see [Content types with XMTP](https://xmtp.org/docs/dev-concepts/content-types).
Support for other content types can be added by registering additional `ContentCodec`s with the client. Every codec is associated with a content type identifier, `ContentTypeID`, which is used to signal to the client which codec should be used to process the content that is being sent or received.
For example, see the [Codecs](https://github.com/xmtp/xmtp-ios/tree/main/Sources/XMTP/Codecs) available in `xmtp-ios`.
### Send a remote attachment
Use the [RemoteAttachmentCodec](https://github.com/xmtp/xmtp-ios/blob/main/Sources/XMTP/Codecs/RemoteAttachmentCodec.swift) package to enable your app to send and receive message attachments.
Message attachments are files. More specifically, attachments are objects that have:
- `filename` Most files have names, at least the most common file types.
- `mimeType` What kind of file is it? You can often assume this from the file extension, but it's nice to have a specific field for it. [Here's a list of common mime types.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types)
- `data` What is this file's data? Most files have data. If the file doesn't have data then it's probably not the most interesting thing to send.
Because XMTP messages can only be up to 1MB in size, we need to store the attachment somewhere other than the XMTP network. In other words, we need to store it in a remote location.
End-to-end encryption must apply not only to XMTP messages, but to message attachments as well. For this reason, we need to encrypt the attachment before we store it.
#### Create an attachment object
```swift
// Assuming we've loaded a fictional NumberCodec that can be used to encode numbers,
// and is identified with ContentTypeNumber, we can use it as follows.
Client.register(codec: NumberCodec())
try await aliceConversation.send(content: 3.14, options: .init(contentType: ContentTypeNumber, contentFallback: "sending you a pie"))
let attachment = Attachment(
filename: "screenshot.png",
mimeType: "image/png",
data: Data(somePNGData)
)
```
### Compression
#### Encrypt the attachment
Use the `RemoteAttachmentCodec.encodeEncrypted` to encrypt the attachment:
```swift
// Encode the attachment and encrypt that encoded content
const encryptedAttachment = try RemoteAttachment.encodeEncrypted(
content: attachment,
codec: AttachmentCodec()
)
```
#### Upload the encrypted attachment
Upload the encrypted attachment anywhere where it will be accessible via an HTTPS GET request. For example, you can use web3.storage:
```swift
func upload(data: Data, token: String): String {
let url = URL(string: "https://api.web3.storage/upload")!
var request = URLRequest(url: url)
request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.addValue("XMTP", forHTTPHeaderField: "X-NAME")
request.httpMethod = "POST"
let responseData = try await URLSession.shared.upload(for: request, from: data).0
let response = try JSONDecoder().decode(Web3Storage.Response.self, from: responseData)
return "https://\(response.cid).ipfs.w3s.link"
}
let url = upload(data: encryptedAttachment.payload, token: YOUR_WEB3_STORAGE_TOKEN)
```
#### Create a remote attachment
Now that you have a `url`, you can create a `RemoteAttachment`.
```swift
let remoteAttachment = try RemoteAttachment(
url: url,
encryptedEncodedContent: encryptedEncodedContent
)
```
#### Send a remote attachment
Now that you have a remote attachment, you can send it:
```swift
try await conversation.send(
content: remoteAttachment,
options: .init(
contentType: ContentTypeRemoteAttachment,
contentFallback: "a description of the image"
)
)
```
Note that were using `contentFallback` to enable clients that don't support these content types to still display something. For cases where clients *do* support these types, they can use the content fallback as alt text for accessibility purposes.
#### Receive a remote attachment
Now that you can send a remote attachment, you need a way to receive a remote attachment. For example:
```swift
let messages = try await conversation.messages()
let message = messages[0]
guard message.encodedContent.contentType == ContentTypeRemoteAttachment else {
return
}
const remoteAttachment: RemoteAttachment = try message.content()
```
#### Download, decrypt, and decode the attachment
Now that you can receive a remote attachment, you need to download, decrypt, and decode it so your app can display it. For example:
```swift
let attachment: Attachment = try await remoteAttachment.content()
```
You now have the original attachment:
```swift
attachment.filename // => "screenshot.png"
attachment.mimeType // => "image/png",
attachment.data // => [the PNG data]
```
#### Display the attachment
Display the attachment in your app as you please. For example, you can display it as an image:
```swift
import UIKIt
import SwiftUI
struct ContentView: View {
var body: some View {
Image(uiImage: UIImage(data: attachment.data))
}
}
```
#### Handle custom content types
Beyond this, custom codecs and content types may be proposed as interoperable standards through XRCs. To learn more about the custom content type proposal process, see [XIP-5](https://github.com/xmtp/XIPs/blob/main/XIPs/xip-5-message-content-types.md).
## Compression
Message content can be optionally compressed using the compression option. The value of the option is the name of the compression algorithm to use. Currently supported are gzip and deflate. Compression is applied to the bytes produced by the content codec.
@ -330,7 +472,7 @@ Older versions of the SDK will eventually be deprecated, which means:
The following table provides the deprecation schedule.
| Announced | Effective | Minimum Version | Rationale |
| ---------- | ---------- | --------------- | ----------------------------------------------------------------------------------------------------------------- |
| ---------- | ---------- | --------------- | ---------------------------------------------------------------------------------------------------------------- |
| There are no deprecations scheduled for `xmtp-ios` at this time. | | | |
Bug reports, feature requests, and PRs are welcome in accordance with these [contribution guidelines](https://github.com/xmtp/xmtp-ios/blob/main/CONTRIBUTING.md).
@ -342,7 +484,8 @@ XMTP provides both `production` and `dev` network environments to support the de
The `production` and `dev` networks are completely separate and not interchangeable.
For example, for a given blockchain account, its XMTP identity on `dev` network is completely distinct from its XMTP identity on the `production` network, as are the messages associated with these identities. In addition, XMTP identities and messages created on the `dev` network can't be accessed from or moved to the `production` network, and vice versa.
**Important:** When you [create a client](#create-a-client), it connects to the XMTP `dev` environment by default. To learn how to use the `env` parameter to set your client's network environment, see [Configure the client](#configure-the-client).
> **Important:**
> When you [create a client](#create-a-client), it connects to the XMTP `dev` environment by default. To learn how to use the `env` parameter to set your client's network environment, see [Configure the client](#configure-the-client).
The `env` parameter accepts one of three valid values: `dev`, `production`, or `local`. Here are some best practices for when to use each environment:

View File

@ -5,24 +5,53 @@
// Created by Pat Nakajima on 11/17/22.
//
import GRPC
import XMTPProto
import Foundation
import XMTPRust
import XMTPRustSwift
typealias PublishRequest = Xmtp_MessageApi_V1_PublishRequest
typealias PublishResponse = Xmtp_MessageApi_V1_PublishResponse
typealias BatchQueryRequest = Xmtp_MessageApi_V1_BatchQueryRequest
typealias BatchQueryResponse = Xmtp_MessageApi_V1_BatchQueryResponse
typealias Cursor = Xmtp_MessageApi_V1_Cursor
typealias QueryRequest = Xmtp_MessageApi_V1_QueryRequest
typealias QueryResponse = Xmtp_MessageApi_V1_QueryResponse
typealias SubscribeRequest = Xmtp_MessageApi_V1_SubscribeRequest
protocol ApiClient {
var environment: XMTPEnvironment { get }
init(environment: XMTPEnvironment, secure: Bool) throws
init(environment: XMTPEnvironment, secure: Bool, rustClient: XMTPRust.RustClient) throws
func setAuthToken(_ token: String)
func query(topics: [String], pagination: Pagination?, cursor: Xmtp_MessageApi_V1_Cursor?) async throws -> QueryResponse
func query(topics: [Topic], pagination: Pagination?) async throws -> QueryResponse
func envelopes(topics: [String], pagination: Pagination?) async throws -> [Envelope]
func batchQuery(request: BatchQueryRequest) async throws -> BatchQueryResponse
func query(topic: String, pagination: Pagination?, cursor: Xmtp_MessageApi_V1_Cursor?) async throws -> QueryResponse
func query(topic: Topic, pagination: Pagination?) async throws -> QueryResponse
func query(request: QueryRequest) async throws -> QueryResponse
func envelopes(topic: String, pagination: Pagination?) async throws -> [Envelope]
func publish(envelopes: [Envelope]) async throws -> PublishResponse
func publish(request: PublishRequest) async throws -> PublishResponse
func subscribe(topics: [String]) -> AsyncThrowingStream<Envelope, Error>
}
func makeQueryRequest(topic: String, pagination: Pagination? = nil, cursor: Cursor? = nil) -> QueryRequest {
return QueryRequest.with {
$0.contentTopics = [topic]
if let pagination {
$0.pagingInfo = pagination.pagingInfo
}
if let startAt = pagination?.startTime {
$0.endTimeNs = UInt64(startAt.millisecondsSinceEpoch) * 1_000_000
$0.pagingInfo.direction = .descending
}
if let endAt = pagination?.endTime {
$0.startTimeNs = UInt64(endAt.millisecondsSinceEpoch) * 1_000_000
$0.pagingInfo.direction = .descending
}
if let cursor {
$0.pagingInfo.cursor = cursor
}
}
}
class GRPCApiClient: ApiClient {
let ClientVersionHeaderKey = "X-Client-Version"
let AppVersionHeaderKey = "X-App-Version"
@ -30,62 +59,52 @@ class GRPCApiClient: ApiClient {
var environment: XMTPEnvironment
var authToken = ""
private var client: Xmtp_MessageApi_V1_MessageApiAsyncClient!
var rustClient: XMTPRust.RustClient
required init(environment: XMTPEnvironment, secure: Bool = true) throws {
required init(environment: XMTPEnvironment, secure _: Bool = true, rustClient: XMTPRust.RustClient) throws {
self.environment = environment
let group = PlatformSupport.makeEventLoopGroup(loopCount: 1)
self.rustClient = rustClient
}
let config = GRPCTLSConfiguration.makeClientConfigurationBackedByNIOSSL()
let channel = try GRPCChannelPool.with(
target: .host(environment.rawValue, port: 5556),
transportSecurity: secure ? .tls(config) : .plaintext,
eventLoopGroup: group
)
client = Xmtp_MessageApi_V1_MessageApiAsyncClient(channel: channel)
static func envToUrl(env: XMTPEnvironment) -> String {
switch env {
case XMTPEnvironment.local: return "http://localhost:5556"
case XMTPEnvironment.dev: return "https://dev.xmtp.network:5556"
case XMTPEnvironment.production: return "https://production.xmtp.network:5556"
}
}
func setAuthToken(_ token: String) {
authToken = token
}
func query(topics: [String], pagination: Pagination? = nil, cursor: Xmtp_MessageApi_V1_Cursor? = nil) async throws -> QueryResponse {
var request = Xmtp_MessageApi_V1_QueryRequest()
request.contentTopics = topics
func batchQuery(request: BatchQueryRequest) async throws -> BatchQueryResponse {
let req = RustVec<UInt8>(try request.serializedData())
let res: RustVec<UInt8> = try await rustClient.batch_query(req)
return try BatchQueryResponse(serializedData: Data(res))
}
if let pagination {
request.pagingInfo = pagination.pagingInfo
}
func query(request: QueryRequest) async throws -> QueryResponse {
let req = RustVec<UInt8>(try request.serializedData())
let res: RustVec<UInt8> = try await rustClient.query(req)
return try QueryResponse(serializedData: Data(res))
}
if let startAt = pagination?.startTime {
request.endTimeNs = UInt64(startAt.millisecondsSinceEpoch) * 1_000_000
request.pagingInfo.direction = .descending
}
func query(topic: String, pagination: Pagination? = nil, cursor: Cursor? = nil) async throws -> QueryResponse {
return try await query(request: makeQueryRequest(topic: topic, pagination: pagination, cursor: cursor))
}
if let endAt = pagination?.endTime {
request.startTimeNs = UInt64(endAt.millisecondsSinceEpoch) * 1_000_000
request.pagingInfo.direction = .descending
}
func query(topic: Topic, pagination: Pagination? = nil) async throws -> QueryResponse {
return try await query(request: makeQueryRequest(topic: topic.description, pagination: pagination))
}
if let cursor {
request.pagingInfo.cursor = cursor
}
var options = CallOptions()
options.customMetadata.add(name: "authorization", value: "Bearer \(authToken)")
options.timeLimit = .timeout(.seconds(5))
return try await client.query(request, callOptions: options)
}
func envelopes(topics: [String], pagination: Pagination? = nil) async throws -> [Envelope] {
func envelopes(topic: String, pagination: Pagination? = nil) async throws -> [Envelope] {
var envelopes: [Envelope] = []
var hasNextPage = true
var cursor: Xmtp_MessageApi_V1_Cursor?
while hasNextPage {
let response = try await query(topics: topics, pagination: pagination, cursor: cursor)
let response = try await query(topic: topic, pagination: pagination, cursor: cursor)
envelopes.append(contentsOf: response.envelopes)
@ -96,33 +115,35 @@ class GRPCApiClient: ApiClient {
return envelopes
}
func query(topics: [Topic], pagination: Pagination? = nil) async throws -> Xmtp_MessageApi_V1_QueryResponse {
return try await query(topics: topics.map(\.description), pagination: pagination)
}
func subscribe(topics: [String]) -> AsyncThrowingStream<Envelope, Error> {
return AsyncThrowingStream { continuation in
Task {
var request = SubscribeRequest()
request.contentTopics = topics
for try await envelope in self.client.subscribe(request) {
continuation.yield(envelope)
let request = SubscribeRequest.with { $0.contentTopics = topics }
let req = RustVec<UInt8>(try request.serializedData())
let subscription = try await self.rustClient.subscribe(req)
// Run a continuous for loop polling and sleeping for a bit each loop.
while true {
let buf = try subscription.get_envelopes_as_query_response()
// Note: it uses QueryResponse as a convenient envelopes wrapper.
let res = try QueryResponse(serializedData: Data(buf))
for envelope in res.envelopes {
continuation.yield(envelope)
}
try await Task.sleep(nanoseconds: 50_000_000) // 50ms
}
}
}
}
func publish(request: PublishRequest) async throws -> PublishResponse {
let req = RustVec<UInt8>(try request.serializedData())
let res: RustVec<UInt8> = try await rustClient.publish(authToken.intoRustString(), req)
return try PublishResponse(serializedData: Data(res))
}
@discardableResult func publish(envelopes: [Envelope]) async throws -> PublishResponse {
var request = Xmtp_MessageApi_V1_PublishRequest()
request.envelopes = envelopes
var options = CallOptions()
options.customMetadata.add(name: "authorization", value: "Bearer \(authToken)")
options.customMetadata.add(name: ClientVersionHeaderKey, value: Constants.version)
options.customMetadata.add(name: AppVersionHeaderKey, value: Constants.version)
options.timeLimit = .timeout(.seconds(5))
return try await client.publish(request, callOptions: options)
return try await publish(request: PublishRequest.with {
$0.envelopes = envelopes
})
}
}

View File

@ -6,9 +6,8 @@
//
import Foundation
import GRPC
import web3
import XMTPProto
import XMTPRust
/// Specify configuration options for creating a ``Client``.
public struct ClientOptions {
@ -49,6 +48,8 @@ public class Client {
var privateKeyBundleV1: PrivateKeyBundleV1
var apiClient: ApiClient
public private(set) var isGroupChatEnabled = false
/// Access ``Conversations`` for this Client.
public lazy var conversations: Conversations = .init(client: self)
@ -74,9 +75,11 @@ public class Client {
public static func create(account: SigningKey, options: ClientOptions? = nil) async throws -> Client {
let options = options ?? ClientOptions()
let client = try await XMTPRust.create_client(GRPCApiClient.envToUrl(env: options.api.env), options.api.env != .local)
let apiClient = try GRPCApiClient(
environment: options.api.env,
secure: options.api.isSecure
secure: options.api.isSecure,
rustClient: client
)
return try await create(account: account, apiClient: apiClient)
@ -95,7 +98,7 @@ public class Client {
// swiftlint:disable no_optional_try
if let keys = try await loadPrivateKeys(for: account, apiClient: apiClient) {
// swiftlint:enable no_optional_try
print("loading existing private keys.")
#if DEBUG
print("Loaded existing private keys.")
#endif
@ -112,10 +115,8 @@ public class Client {
var authorizedIdentity = AuthorizedIdentity(privateKeyBundleV1: keys)
authorizedIdentity.address = account.address
let authToken = try await authorizedIdentity.createAuthToken()
let apiClient = apiClient
apiClient.setAuthToken(authToken)
_ = try await apiClient.publish(envelopes: [
Envelope(topic: .userPrivateStoreKeyBundle(account.address), timestamp: Date(), message: try encryptedKeys.serializedData()),
])
@ -125,31 +126,38 @@ public class Client {
}
static func loadPrivateKeys(for account: SigningKey, apiClient: ApiClient) async throws -> PrivateKeyBundleV1? {
let topics: [Topic] = [.userPrivateStoreKeyBundle(account.address)]
let res = try await apiClient.query(topics: topics, pagination: nil)
let res = try await apiClient.query(
topic: .userPrivateStoreKeyBundle(account.address),
pagination: nil
)
for envelope in res.envelopes {
let encryptedBundle = try EncryptedPrivateKeyBundle(serializedData: envelope.message)
let bundle = try await encryptedBundle.decrypted(with: account)
return bundle.v1
if case .v1 = bundle.version {
return bundle.v1
}
print("discarding unsupported stored key bundle")
}
return nil
}
public static func from(bundle: PrivateKeyBundle, options: ClientOptions? = nil) throws -> Client {
return try from(v1Bundle: bundle.v1, options: options)
public static func from(bundle: PrivateKeyBundle, options: ClientOptions? = nil) async throws -> Client {
return try await from(v1Bundle: bundle.v1, options: options)
}
/// Create a Client from saved v1 key bundle.
public static func from(v1Bundle: PrivateKeyBundleV1, options: ClientOptions? = nil) throws -> Client {
public static func from(v1Bundle: PrivateKeyBundleV1, options: ClientOptions? = nil) async throws -> Client {
let address = try v1Bundle.identityKey.publicKey.recoverWalletSignerPublicKey().walletAddress
let options = options ?? ClientOptions()
let client = try await XMTPRust.create_client(GRPCApiClient.envToUrl(env: options.api.env), options.api.env != .local)
let apiClient = try GRPCApiClient(
environment: options.api.env,
secure: options.api.isSecure
secure: options.api.isSecure,
rustClient: client
)
return try Client(address: address, privateKeyBundleV1: v1Bundle, apiClient: apiClient)
@ -161,6 +169,11 @@ public class Client {
self.apiClient = apiClient
}
public func enableGroupChat() {
self.isGroupChatEnabled = true
GroupChat.registerCodecs()
}
public var privateKeyBundle: PrivateKeyBundle {
PrivateKeyBundle(v1: privateKeyBundleV1)
}
@ -173,6 +186,10 @@ public class Client {
privateKeyBundleV1.toV2()
}
public func canMessage(_ peerAddress: String) async throws -> Bool {
return try await query(topic: .contact(peerAddress)).envelopes.count > 0
}
public func importConversation(from conversationData: Data) throws -> Conversation? {
let jsonDecoder = JSONDecoder()
@ -261,10 +278,17 @@ public class Client {
_ = try await publish(envelopes: envelopes)
}
func query(topics: [Topic], pagination: Pagination? = nil) async throws -> QueryResponse {
return try await apiClient.query(topics: topics, pagination: pagination)
func query(topic: Topic, pagination: Pagination? = nil) async throws -> QueryResponse {
return try await apiClient.query(
topic: topic,
pagination: pagination
)
}
func batchQuery(request: BatchQueryRequest) async throws -> BatchQueryResponse {
return try await apiClient.batchQuery(request: request)
}
@discardableResult func publish(envelopes: [Envelope]) async throws -> PublishResponse {
let authorized = AuthorizedIdentity(address: address, authorized: privateKeyBundleV1.identityKey.publicKey, identity: privateKeyBundleV1.identityKey)
let authToken = try await authorized.createAuthToken()

View File

@ -5,7 +5,6 @@
// Created by Pat on 2/14/23.
//
import Foundation
import XMTPProto
public let ContentTypeAttachment = ContentTypeID(authorityID: "xmtp.org", typeID: "attachment", versionMajor: 1, versionMinor: 0)

View File

@ -5,8 +5,6 @@
// Created by Pat Nakajima on 12/22/22.
//
import XMTPProto
typealias Composite = Xmtp_MessageContents_Composite
let ContentTypeComposite = ContentTypeID(authorityID: "xmtp.org", typeID: "composite", versionMajor: 1, versionMinor: 0)

View File

@ -6,7 +6,6 @@
//
import Foundation
import XMTPProto
enum CodecError: String, Error {
case invalidContent, codecNotFound

View File

@ -5,8 +5,6 @@
// Created by Pat Nakajima on 11/28/22.
//
import XMTPProto
public typealias ContentTypeID = Xmtp_MessageContents_ContentTypeId
public extension ContentTypeID {

View File

@ -0,0 +1,33 @@
//
// GroupChatMemberAddedCodec.swift
//
//
// Created by Pat Nakajima on 6/11/23.
//
import Foundation
public let ContentTypeGroupChatMemberAdded = ContentTypeID(authorityID: "xmtp.org", typeID: "groupChatMemberAdded", versionMajor: 1, versionMinor: 0)
public struct GroupChatMemberAdded: Codable {
// The address of the member being added
public var member: String
}
public struct GroupChatMemberAddedCodec: ContentCodec {
public var contentType = ContentTypeGroupChatMemberAdded
public func encode(content: GroupChatMemberAdded) throws -> EncodedContent {
var encodedContent = EncodedContent()
encodedContent.type = ContentTypeGroupChatMemberAdded
encodedContent.content = try JSONEncoder().encode(content)
return encodedContent
}
public func decode(content: EncodedContent) throws -> GroupChatMemberAdded {
let memberAdded = try JSONDecoder().decode(GroupChatMemberAdded.self, from: content.content)
return memberAdded
}
}

View File

@ -0,0 +1,33 @@
//
// GroupChatTitleChangedCodec.swift
//
//
// Created by Pat Nakajima on 6/11/23.
//
import Foundation
public let ContentTypeGroupTitleChangedAdded = ContentTypeID(authorityID: "xmtp.org", typeID: "groupChatTitleChanged", versionMajor: 1, versionMinor: 0)
public struct GroupChatTitleChanged: Codable {
// The new title
public var newTitle: String
}
public struct GroupChatTitleChangedCodec: ContentCodec {
public var contentType = ContentTypeGroupTitleChangedAdded
public func encode(content: GroupChatTitleChanged) throws -> EncodedContent {
var encodedContent = EncodedContent()
encodedContent.type = ContentTypeGroupTitleChangedAdded
encodedContent.content = try JSONEncoder().encode(content)
return encodedContent
}
public func decode(content: EncodedContent) throws -> GroupChatTitleChanged {
let titleChanged = try JSONDecoder().decode(GroupChatTitleChanged.self, from: content.content)
return titleChanged
}
}

View File

@ -8,7 +8,6 @@
import CryptoKit
import Foundation
import web3
import XMTPProto
public let ContentTypeRemoteAttachment = ContentTypeID(authorityID: "xmtp.org", typeID: "remoteStaticAttachment", versionMajor: 1, versionMinor: 0)

View File

@ -6,7 +6,6 @@
//
import Foundation
import XMTPProto
public let ContentTypeText = ContentTypeID(authorityID: "xmtp.org", typeID: "text", versionMajor: 1, versionMinor: 0)

View File

@ -8,5 +8,5 @@
import Foundation
struct Constants {
static let version = "0.0.0-development"
static let version = "xmtp-ios/0.0.0-development"
}

View File

@ -30,7 +30,7 @@ public struct Contacts {
return knownBundle
}
let response = try await client.query(topics: [.contact(peerAddress)])
let response = try await client.query(topic: .contact(peerAddress))
for envelope in response.envelopes {
// swiftlint:disable no_optional_try

View File

@ -6,7 +6,6 @@
//
import Foundation
import XMTPProto
public enum ConversationContainer: Codable {
case v1(ConversationV1Container), v2(ConversationV2Container)
@ -22,7 +21,7 @@ public enum ConversationContainer: Codable {
}
/// Wrapper that provides a common interface between ``ConversationV1`` and ``ConversationV2`` objects.
public enum Conversation {
public enum Conversation: Sendable {
// TODO: It'd be nice to not have to expose these types as public, maybe we make this a struct with an enum prop instead of just an enum
case v1(ConversationV1), v2(ConversationV2)
@ -30,11 +29,20 @@ public enum Conversation {
case v1, v2
}
public var isGroup: Bool {
switch self {
case .v1:
return false
case let .v2(conversationV2):
return conversationV2.isGroup
}
}
public var version: Version {
switch self {
case let .v1:
case .v1:
return .v1
case let .v2:
case .v2:
return .v2
}
}
@ -97,6 +105,15 @@ public enum Conversation {
}
}
public func prepareMessage<T>(content: T, options: SendOptions? = nil) async throws -> PreparedMessage {
switch self {
case let .v1(conversationV1):
return try await conversationV1.prepareMessage(content: content, options: options ?? .init())
case let .v2(conversationV2):
return try await conversationV2.prepareMessage(content: content, options: options ?? .init())
}
}
@discardableResult public func send<T>(content: T, options: SendOptions? = nil, fallback _: String? = nil) async throws -> String {
switch self {
case let .v1(conversationV1):

View File

@ -5,8 +5,6 @@
// Created by Pat Nakajima on 2/1/23.
//
import XMTPProto
enum ConversationImportError: Error {
case invalidData
}

View File

@ -38,18 +38,11 @@ public struct ConversationV1 {
Topic.directMessageV1(client.address, peerAddress)
}
@discardableResult func send(content: String, options: SendOptions? = nil) async throws -> String {
return try await send(content: content, options: options, sentAt: nil)
}
func prepareMessage<T>(content: T, options: SendOptions?) async throws -> PreparedMessage {
guard let contact = try await client.contacts.find(peerAddress) else {
throw ContactBundleError.notFound
}
@discardableResult internal func send(content: String, options: SendOptions? = nil, sentAt: Date? = nil) async throws -> String {
let encoder = TextCodec()
let encodedContent = try encoder.encode(content: content)
return try await send(content: encodedContent, options: options, sentAt: sentAt)
}
func send<T>(content: T, options: SendOptions? = nil) async throws -> String {
let codec = Client.codecRegistry.find(for: options?.contentType)
func encode<Codec: ContentCodec>(codec: Codec, content: Any) throws -> EncodedContent {
@ -63,18 +56,9 @@ public struct ConversationV1 {
let content = content as T
var encoded = try encode(codec: codec, content: content)
encoded.fallback = options?.contentFallback ?? ""
return try await send(content: encoded, options: options)
}
internal func send(content encodedContent: EncodedContent, options: SendOptions? = nil, sentAt: Date? = nil) async throws -> String {
guard let contact = try await client.contacts.find(peerAddress) else {
throw ContactBundleError.notFound
}
var encodedContent = encodedContent
if let compression = options?.compression {
encodedContent = try encodedContent.compress(compression)
encoded = try encoded.compress(compression)
}
let recipient = try contact.toPublicKeyBundle()
@ -83,12 +67,12 @@ public struct ConversationV1 {
fatalError("no signature for id key")
}
let date = sentAt ?? Date()
let date = sentAt
let message = try MessageV1.encode(
sender: client.privateKeyBundleV1,
recipient: recipient,
message: try encodedContent.serializedData(),
message: try encoded.serializedData(),
timestamp: date
)
@ -98,28 +82,44 @@ public struct ConversationV1 {
message: try Message(v1: message).serializedData()
)
var envelopes = [messageEnvelope]
return PreparedMessage(messageEnvelope: messageEnvelope, conversation: .v1(self)) {
var envelopes = [messageEnvelope]
if client.contacts.needsIntroduction(peerAddress) {
envelopes.append(contentsOf: [
Envelope(
topic: .userIntro(peerAddress),
timestamp: date,
message: try Message(v1: message).serializedData()
),
Envelope(
topic: .userIntro(client.address),
timestamp: date,
message: try Message(v1: message).serializedData()
),
])
if client.contacts.needsIntroduction(peerAddress) {
envelopes.append(contentsOf: [
Envelope(
topic: .userIntro(peerAddress),
timestamp: date,
message: try Message(v1: message).serializedData()
),
Envelope(
topic: .userIntro(client.address),
timestamp: date,
message: try Message(v1: message).serializedData()
),
])
client.contacts.hasIntroduced[peerAddress] = true
client.contacts.hasIntroduced[peerAddress] = true
}
try await client.publish(envelopes: envelopes)
}
}
try await client.publish(envelopes: envelopes)
@discardableResult func send(content: String, options: SendOptions? = nil) async throws -> String {
return try await send(content: content, options: options, sentAt: nil)
}
return generateID(from: messageEnvelope)
@discardableResult internal func send(content: String, options: SendOptions? = nil, sentAt _: Date? = nil) async throws -> String {
let preparedMessage = try await prepareMessage(content: content, options: options)
try await preparedMessage.send()
return preparedMessage.messageID
}
func send<T>(content: T, options: SendOptions? = nil) async throws -> String {
let preparedMessage = try await prepareMessage(content: content, options: options)
try await preparedMessage.send()
return preparedMessage.messageID
}
public func streamMessages() -> AsyncThrowingStream<DecodedMessage, Error> {
@ -136,9 +136,10 @@ public struct ConversationV1 {
func messages(limit: Int? = nil, before: Date? = nil, after: Date? = nil) async throws -> [DecodedMessage] {
let pagination = Pagination(limit: limit, startTime: before, endTime: after)
let envelopes = try await client.apiClient.query(topics: [
.directMessageV1(client.address, peerAddress),
], pagination: pagination).envelopes
let envelopes = try await client.apiClient.query(
topic: Topic.directMessageV1(client.address, peerAddress),
pagination: pagination
).envelopes
return envelopes.compactMap { envelope in
do {

View File

@ -7,7 +7,6 @@
import CryptoKit
import Foundation
import XMTPProto
// Save the non-client parts for a v2 conversation
public struct ConversationV2Container: Codable {
@ -31,15 +30,16 @@ public struct ConversationV2 {
public var context: InvitationV1.Context
public var peerAddress: String
public var client: Client
public var isGroup = false
private var header: SealedInvitationHeaderV1
static func create(client: Client, invitation: InvitationV1, header: SealedInvitationHeaderV1) throws -> ConversationV2 {
static func create(client: Client, invitation: InvitationV1, header: SealedInvitationHeaderV1, isGroup: Bool = false) throws -> ConversationV2 {
let myKeys = client.keys.getPublicKeyBundle()
let peer = try myKeys.walletAddress == (try header.sender.walletAddress) ? header.recipient : header.sender
let peerAddress = try peer.walletAddress
let keyMaterial = Data(invitation.aes256GcmHkdfSha256.keyMaterial.bytes)
let keyMaterial = Data(invitation.aes256GcmHkdfSha256.keyMaterial)
return ConversationV2(
topic: invitation.topic,
@ -47,7 +47,8 @@ public struct ConversationV2 {
context: invitation.context,
peerAddress: peerAddress,
client: client,
header: header
header: header,
isGroup: isGroup
)
}
@ -60,23 +61,55 @@ public struct ConversationV2 {
header = SealedInvitationHeaderV1()
}
public init(topic: String, keyMaterial: Data, context: InvitationV1.Context, peerAddress: String, client: Client, header: SealedInvitationHeaderV1) {
public init(topic: String, keyMaterial: Data, context: InvitationV1.Context, peerAddress: String, client: Client, header: SealedInvitationHeaderV1, isGroup: Bool = false) {
self.topic = topic
self.keyMaterial = keyMaterial
self.context = context
self.peerAddress = peerAddress
self.client = client
self.header = header
self.isGroup = isGroup
}
public var encodedContainer: ConversationV2Container {
ConversationV2Container(topic: topic, keyMaterial: keyMaterial, conversationID: context.conversationID, metadata: context.metadata, peerAddress: peerAddress, header: header)
}
func prepareMessage<T>(content: T, options: SendOptions?) async throws -> PreparedMessage {
let codec = Client.codecRegistry.find(for: options?.contentType)
func encode<Codec: ContentCodec>(codec: Codec, content: Any) throws -> EncodedContent {
if let content = content as? Codec.T {
return try codec.encode(content: content)
} else {
throw CodecError.invalidContent
}
}
var encoded = try encode(codec: codec, content: content)
encoded.fallback = options?.contentFallback ?? ""
if let compression = options?.compression {
encoded = try encoded.compress(compression)
}
let message = try await MessageV2.encode(
client: client,
content: encoded,
topic: topic,
keyMaterial: keyMaterial
)
let envelope = Envelope(topic: topic, timestamp: Date(), message: try Message(v2: message).serializedData())
return PreparedMessage(messageEnvelope: envelope, conversation: .v2(self)) {
try await client.publish(envelopes: [envelope])
}
}
func messages(limit: Int? = nil, before: Date? = nil, after: Date? = nil) async throws -> [DecodedMessage] {
let pagination = Pagination(limit: limit, startTime: before, endTime: after)
let envelopes = try await client.apiClient.query(topics: [topic], pagination: pagination, cursor: nil).envelopes
let envelopes = try await client.apiClient.query(topic: topic, pagination: pagination, cursor: nil).envelopes
return envelopes.compactMap { envelope in
do {
@ -118,25 +151,15 @@ public struct ConversationV2 {
}
@discardableResult func send<T>(content: T, options: SendOptions? = nil) async throws -> String {
let codec = Client.codecRegistry.find(for: options?.contentType)
func encode<Codec: ContentCodec>(codec: Codec, content: Any) throws -> EncodedContent {
if let content = content as? Codec.T {
return try codec.encode(content: content)
} else {
throw CodecError.invalidContent
}
}
var encoded = try encode(codec: codec, content: content)
encoded.fallback = options?.contentFallback ?? ""
return try await send(content: encoded, options: options, sentAt: Date())
let preparedMessage = try await prepareMessage(content: content, options: options)
try await preparedMessage.send()
return preparedMessage.messageID
}
@discardableResult func send(content: String, options: SendOptions? = nil, sentAt: Date) async throws -> String {
let encoder = TextCodec()
let encodedContent = try encoder.encode(content: content)
return try await send(content: encodedContent, options: options, sentAt: sentAt)
@discardableResult func send(content: String, options: SendOptions? = nil, sentAt _: Date) async throws -> String {
let preparedMessage = try await prepareMessage(content: content, options: options)
try await preparedMessage.send()
return preparedMessage.messageID
}
public func encode<Codec: ContentCodec, T>(codec: Codec, content: T) async throws -> Data where Codec.T == T {
@ -158,31 +181,6 @@ public struct ConversationV2 {
return try envelope.serializedData()
}
internal func send(content: EncodedContent, options: SendOptions? = nil, sentAt: Date) async throws -> String {
guard try await client.getUserContact(peerAddress: peerAddress) != nil else {
throw ContactBundleError.notFound
}
var content = content
if let compression = options?.compression {
content = try content.compress(compression)
}
let message = try await MessageV2.encode(
client: client,
content: content,
topic: topic,
keyMaterial: keyMaterial
)
let envelope = Envelope(topic: topic, timestamp: sentAt, message: try Message(v2: message).serializedData())
try await client.publish(envelopes: [envelope])
return generateID(from: envelope)
}
@discardableResult func send(content: String, options: SendOptions? = nil) async throws -> String {
return try await send(content: content, options: options, sentAt: Date())
}

View File

@ -6,10 +6,9 @@
//
import Foundation
import XMTPProto
public enum ConversationError: Error {
case recipientNotOnNetwork, recipientIsSender
case recipientNotOnNetwork, recipientIsSender, v1NotSupported(String)
}
/// Handles listing and creating Conversations.
@ -21,6 +20,39 @@ public class Conversations {
self.client = client
}
public func listBatchMessages(topics: [String], limit: Int? = nil, before: Date? = nil, after: Date? = nil) async throws -> [DecodedMessage] {
let pagination = Pagination(limit: limit, startTime: before, endTime: after)
let requests = topics.map { (topic) in
makeQueryRequest(topic: topic, pagination: pagination)
}
/// The maximum number of requests permitted in a single batch call.
let maxQueryRequestsPerBatch = 50
let batches = requests.chunks(maxQueryRequestsPerBatch)
.map { (requests) in BatchQueryRequest.with { $0.requests = requests } }
var messages: [DecodedMessage] = []
// TODO: consider using a task group here for parallel batch calls
for batch in batches {
messages += try await client.apiClient.batchQuery(request: batch)
.responses.flatMap { (res) in
try res.envelopes.compactMap { (envelope) in
let conversation = conversations
.first(where: { $0.topic == envelope.contentTopic })
if conversation == nil {
print("discarding message, unknown conversation \(envelope)")
return nil
}
let msg = try conversation?.decode(envelope)
if msg == nil {
print("discarding message, unable to decode \(envelope)")
return nil
}
return msg
}
}
}
return messages
}
public func streamAllMessages() async throws -> AsyncThrowingStream<DecodedMessage, Error> {
return AsyncThrowingStream { continuation in
Task {
@ -195,15 +227,20 @@ public class Conversations {
print("Error loading introduction peers: \(error)")
}
let invitations = try await listInvitations()
for sealedInvitation in invitations {
for sealedInvitation in try await listInvitations() {
do {
let unsealed = try sealedInvitation.v1.getInvitation(viewer: client.keys)
let conversation = try ConversationV2.create(client: client, invitation: unsealed, header: sealedInvitation.v1.header)
conversations.append(
Conversation.v2(conversation)
Conversation.v2(try conversation(from: sealedInvitation))
)
} catch {
print("Error loading invitations: \(error)")
}
}
for sealedInvitation in try await listGroupInvitations() {
do {
conversations.append(
Conversation.v2(try conversation(from: sealedInvitation, isGroup: true))
)
} catch {
print("Error loading invitations: \(error)")
@ -215,10 +252,18 @@ public class Conversations {
return self.conversations
}
func conversation(from sealedInvitation: SealedInvitation, isGroup: Bool = false) throws -> ConversationV2 {
let unsealed = try sealedInvitation.v1.getInvitation(viewer: client.keys)
let conversation = try ConversationV2.create(client: client, invitation: unsealed, header: sealedInvitation.v1.header, isGroup: isGroup)
return conversation
}
func listIntroductionPeers() async throws -> [String: Date] {
let envelopes = try await client.apiClient.query(topics: [
.userIntro(client.address),
], pagination: nil).envelopes
let envelopes = try await client.apiClient.query(
topic: .userIntro(client.address),
pagination: nil
).envelopes
let messages = envelopes.compactMap { envelope in
do {
@ -257,9 +302,26 @@ public class Conversations {
return seenPeers
}
func listInvitations() async throws -> [SealedInvitation] {
func listGroupInvitations() async throws -> [SealedInvitation] {
if !client.isGroupChatEnabled {
return []
}
let envelopes = try await client.apiClient.envelopes(
topics: [Topic.userInvite(client.address).description],
topic: Topic.groupInvite(client.address).description,
pagination: nil
)
return envelopes.compactMap { envelope in
// swiftlint:disable no_optional_try
try? SealedInvitation(serializedData: envelope.message)
// swiftlint:enable no_optional_try
}
}
func listInvitations() async throws -> [SealedInvitation] {
var envelopes = try await client.apiClient.envelopes(
topic: Topic.userInvite(client.address).description,
pagination: nil
)

View File

@ -7,7 +7,6 @@
import CryptoKit
import Foundation
import XMTPProto
public typealias CipherText = Xmtp_MessageContents_Ciphertext
@ -36,8 +35,14 @@ enum Crypto {
}
var ciphertext = CipherText()
ciphertext.aes256GcmHkdfSha256.payload = payload.ciphertext + payload.tag
// Copy the ciphertext data out, otherwise it's a region sliced from a combined Data (nonce, ciphertext, tag)
// with offsets like lowerBound=12, upperBound=224. Without copying, trying to index like payload[0] crashes
// up until payload[12]. This is mostly a problem for unit tests where we decrypt what we encrypt in memory, as
// serialization/deserialization acts as copying and avoids this issue.
var payloadData = Data(payload.ciphertext.subdata(in: 12 ..< payload.ciphertext.count+12))
let startTag = 12 + payload.ciphertext.count
payloadData.append(payload.tag.subdata(in: startTag ..< startTag + payload.tag.count))
ciphertext.aes256GcmHkdfSha256.payload = payloadData
ciphertext.aes256GcmHkdfSha256.hkdfSalt = salt
ciphertext.aes256GcmHkdfSha256.gcmNonce = nonceData
@ -48,11 +53,11 @@ enum Crypto {
let salt = ciphertext.aes256GcmHkdfSha256.hkdfSalt
let nonceData = ciphertext.aes256GcmHkdfSha256.gcmNonce
let nonce = try AES.GCM.Nonce(data: nonceData)
let payload = ciphertext.aes256GcmHkdfSha256.payload.bytes
let payload = ciphertext.aes256GcmHkdfSha256.payload
let ciphertext = payload[0 ..< payload.count - 16]
let ciphertextBytes = payload[0 ..< payload.count - 16]
let tag = payload[payload.count - 16 ..< payload.count]
let box = try AES.GCM.SealedBox(nonce: nonce, ciphertext: ciphertext, tag: tag)
let box = try AES.GCM.SealedBox(nonce: nonce, ciphertext: ciphertextBytes, tag: tag)
let resultKey = HKDF<SHA256>.deriveKey(
inputKeyMaterial: SymmetricKey(data: secret),

View File

@ -8,7 +8,7 @@
import Foundation
/// Decrypted messages from a conversation.
public struct DecodedMessage {
public struct DecodedMessage: Sendable {
public var id: String = ""
public var encodedContent: EncodedContent

View File

@ -6,12 +6,17 @@
//
import Foundation
import XMTPRust
extension Data {
init?(base64String: String) {
self.init(base64Encoded: Data(base64String.utf8))
}
init(_ rustVec: RustVec<UInt8>) {
self.init(rustVec.map { $0 })
}
var toHex: String {
return reduce("") { $0 + String(format: "%02x", $1) }
}

View File

@ -0,0 +1,19 @@
//
// File.swift
//
//
// Created by Pat Nakajima on 4/24/23.
//
import Foundation
import XMTPRust
extension RustVec where T == UInt8 {
convenience init(_ data: Data) {
self.init()
for byte in data {
push(value: byte)
}
}
}

View File

@ -0,0 +1,15 @@
//
// GroupChat.swift
//
//
// Created by Pat Nakajima on 6/11/23.
//
import Foundation
public struct GroupChat {
public static func registerCodecs() {
Client.register(codec: GroupChatMemberAddedCodec())
Client.register(codec: GroupChatTitleChangedCodec())
}
}

View File

@ -6,6 +6,7 @@ import Foundation
import Logging
import secp256k1
import web3
import XMTPRust
enum KeyUtilError: Error {
case invalidContext
@ -18,19 +19,24 @@ enum KeyUtilError: Error {
}
// Copied from web3.swift since its version is `internal`
enum KeyUtil {
private static var logger: Logger {
Logger(label: "web3.swift.key-util")
enum KeyUtilx {
static func generatePublicKey(from data: Data) throws -> Data {
let vec = try XMTPRust.public_key_from_private_key_k256(RustVec<UInt8>(data))
return Data(vec)
}
static func generatePublicKey(from privateKeyData: Data) throws -> Data {
let privateKey = try secp256k1.Signing.PrivateKey(rawRepresentation: privateKeyData, format: .uncompressed)
return privateKey.publicKey.rawRepresentation
static func recoverPublicKeySHA256(from data: Data, message: Data) throws -> Data {
let vec = try XMTPRust.recover_public_key_k256_sha256(RustVec<UInt8>(message), RustVec<UInt8>(data))
return Data(vec)
}
static func recoverPublicKeyKeccak256(from data: Data, message: Data) throws -> Data {
let vec = try XMTPRust.recover_public_key_k256_keccak256(RustVec<UInt8>(message), RustVec<UInt8>(data))
return Data(vec)
}
static func sign(message: Data, with privateKey: Data, hashing: Bool) throws -> Data {
guard let ctx = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)) else {
logger.warning("Failed to sign message: invalid context.")
throw KeyUtilError.invalidContext
}
@ -46,7 +52,6 @@ enum KeyUtil {
signaturePtr.deallocate()
}
guard secp256k1_ecdsa_sign_recoverable(ctx, signaturePtr, msg, privateKeyPtr, nil, nil) == 1 else {
logger.warning("Failed to sign message: recoverable ECDSA signature creation failed.")
throw KeyUtilError.signatureFailure
}
@ -79,7 +84,6 @@ enum KeyUtil {
static func recoverPublicKey(message: Data, signature: Data) throws -> Data {
guard let ctx = secp256k1_context_create(UInt32(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)) else {
logger.warning("Failed to sign message: invalid context.")
throw KeyUtilError.invalidContext
}
defer { secp256k1_context_destroy(ctx) }
@ -101,7 +105,6 @@ enum KeyUtil {
// swiftlint:disable force_unwrapping
try serializedSignature.withUnsafeBytes {
guard secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, signaturePtr, $0.bindMemory(to: UInt8.self).baseAddress!, v) == 1 else {
logger.warning("Failed to parse signature: recoverable ECDSA signature parse failed.")
throw KeyUtilError.signatureParseFailure
}
}

View File

@ -6,7 +6,6 @@
//
import Foundation
import XMTPProto
typealias AuthData = Xmtp_MessageApi_V1_AuthData

View File

@ -5,7 +5,8 @@
// Created by Pat Nakajima on 11/23/22.
//
import XMTPProto
import web3
import XMTPRust
typealias ContactBundle = Xmtp_MessageContents_ContactBundle
typealias ContactBundleV1 = Xmtp_MessageContents_ContactBundleV1
@ -62,13 +63,13 @@ extension ContactBundle {
switch version {
case .v1:
if let key = try? v1.keyBundle.identityKey.recoverWalletSignerPublicKey() {
return KeyUtil.generateAddress(from: key.secp256K1Uncompressed.bytes).toChecksumAddress()
return KeyUtilx.generateAddress(from: key.secp256K1Uncompressed.bytes).toChecksumAddress()
}
return nil
case .v2:
if let key = try? v2.keyBundle.identityKey.recoverWalletSignerPublicKey() {
return KeyUtil.generateAddress(from: key.secp256K1Uncompressed.bytes).toChecksumAddress()
return KeyUtilx.generateAddress(from: key.secp256K1Uncompressed.bytes).toChecksumAddress()
}
return nil

View File

@ -5,8 +5,6 @@
// Created by Pat Nakajima on 11/17/22.
//
import XMTPProto
typealias EncryptedPrivateKeyBundle = Xmtp_MessageContents_EncryptedPrivateKeyBundle
extension EncryptedPrivateKeyBundle {

View File

@ -6,7 +6,6 @@
//
import Foundation
import XMTPProto
public typealias Envelope = Xmtp_MessageApi_V1_Envelope

View File

@ -6,7 +6,6 @@
//
import Foundation
import XMTPProto
/// Handles topic generation for conversations.
public typealias InvitationV1 = Xmtp_MessageContents_InvitationV1

View File

@ -5,8 +5,6 @@
// Created by Pat Nakajima on 11/27/22.
//
import XMTPProto
/// Handles encryption/decryption for communicating data in conversations
public typealias Message = Xmtp_MessageContents_Message

View File

@ -6,7 +6,6 @@
//
import Foundation
import XMTPProto
typealias MessageHeaderV1 = Xmtp_MessageContents_MessageHeaderV1

View File

@ -6,7 +6,6 @@
//
import Foundation
import XMTPProto
typealias MessageHeaderV2 = Xmtp_MessageContents_MessageHeaderV2

View File

@ -6,7 +6,6 @@
//
import Foundation
import XMTPProto
typealias MessageV1 = Xmtp_MessageContents_MessageV1

View File

@ -7,7 +7,7 @@
import CryptoKit
import Foundation
import XMTPProto
import XMTPRust
typealias MessageV2 = Xmtp_MessageContents_MessageV2
@ -41,10 +41,8 @@ extension MessageV2 {
}
// Verify content signature
let digest = SHA256.hash(data: message.headerBytes + signed.payload)
let key = try PublicKey.with { key in
key.secp256K1Uncompressed.bytes = try KeyUtil.recoverPublicKey(message: Data(digest.bytes), signature: signed.signature.rawData)
key.secp256K1Uncompressed.bytes = try KeyUtilx.recoverPublicKeySHA256(from: signed.signature.rawData, message: Data(message.headerBytes + signed.payload))
}
if key.walletAddress != (try PublicKey(signed.sender.preKey).walletAddress) {

View File

@ -6,13 +6,12 @@
//
import Foundation
import XMTPProto
typealias PagingInfo = Xmtp_MessageApi_V1_PagingInfo
typealias PagingInfoCursor = Xmtp_MessageApi_V1_Cursor
typealias PagingInfoSortDirection = Xmtp_MessageApi_V1_SortDirection
struct Pagination {
public struct Pagination {
var limit: Int?
var direction: PagingInfoSortDirection?
var startTime: Date?

View File

@ -6,8 +6,8 @@
//
import Foundation
import secp256k1
import XMTPProto
import XMTPRust
import CryptoKit
/// Represents a secp256k1 private key. ``PrivateKey`` conforms to ``SigningKey`` so you can use it
/// to create a ``Client``.
@ -31,7 +31,7 @@ extension PrivateKey: SigningKey {
}
public func sign(_ data: Data) async throws -> Signature {
let signatureData = try KeyUtil.sign(message: data, with: secp256K1.bytes, hashing: false)
let signatureData = try KeyUtilx.sign(message: data, with: secp256K1.bytes, hashing: false)
var signature = Signature()
signature.ecdsaCompact.bytes = signatureData[0 ..< 64]
@ -54,7 +54,7 @@ public extension PrivateKey {
timestamp = UInt64(Date().millisecondsSinceEpoch)
secp256K1.bytes = privateKeyData
let publicData = try KeyUtil.generatePublicKey(from: privateKeyData)
let publicData = try KeyUtilx.generatePublicKey(from: privateKeyData)
publicKey.secp256K1Uncompressed.bytes = publicData
publicKey.timestamp = timestamp
}
@ -78,7 +78,7 @@ public extension PrivateKey {
internal func sign(key: UnsignedPublicKey) async throws -> SignedPublicKey {
let bytes = try key.serializedData()
let digest = SHA256.hash(data: bytes)
let signature = try await sign(Data(digest.bytes))
let signature = try await sign(Data(digest))
var signedPublicKey = SignedPublicKey()
signedPublicKey.signature = signature

View File

@ -6,7 +6,7 @@
//
import Foundation
import XMTPProto
public typealias PrivateKeyBundle = Xmtp_MessageContents_PrivateKeyBundle

View File

@ -7,7 +7,8 @@
import CryptoKit
import Foundation
import XMTPProto
import XMTPRust
public typealias PrivateKeyBundleV1 = Xmtp_MessageContents_PrivateKeyBundleV1

View File

@ -6,8 +6,7 @@
//
import Foundation
import secp256k1
import XMTPProto
import XMTPRust
public typealias PrivateKeyBundleV2 = Xmtp_MessageContents_PrivateKeyBundleV2
@ -35,11 +34,7 @@ extension PrivateKeyBundleV2 {
}
func sharedSecret(private privateData: Data, public publicData: Data) throws -> Data {
let publicKey = try secp256k1.Signing.PublicKey(rawRepresentation: publicData, format: .uncompressed)
let sharedSecret = try publicKey.multiply(privateData.bytes, format: .uncompressed)
return sharedSecret.rawRepresentation
return Data(try XMTPRust.diffie_hellman_k256(RustVec<UInt8>(privateData), RustVec<UInt8>(publicData)))
}
func findPreKey(_ myPreKey: SignedPublicKey) throws -> SignedPrivateKey {

View File

@ -6,13 +6,15 @@
//
import Foundation
import secp256k1
import XMTPProto
import XMTPRust
import web3
import CryptoKit
typealias PublicKey = Xmtp_MessageContents_PublicKey
enum PublicKeyError: String, Error {
case noSignature, invalidPreKey, addressNotFound
case noSignature, invalidPreKey, addressNotFound, invalidKeyString
}
extension PublicKey {
@ -46,6 +48,16 @@ extension PublicKey {
secp256K1Uncompressed.bytes = data
}
init(_ string: String) throws {
self.init()
guard let bytes = string.web3.bytesFromHex else {
throw PublicKeyError.invalidKeyString
}
try self.init(Data(bytes))
}
func recoverWalletSignerPublicKey() throws -> PublicKey {
if !hasSignature {
throw PublicKeyError.noSignature
@ -56,9 +68,9 @@ extension PublicKey {
slimKey.secp256K1Uncompressed.bytes = secp256K1Uncompressed.bytes
let sigText = Signature.createIdentityText(key: try slimKey.serializedData())
let sigHash = try Signature.ethHash(sigText)
let message = try Signature.ethPersonalMessage(sigText)
let pubKeyData = try KeyUtil.recoverPublicKey(message: sigHash, signature: signature.rawData)
let pubKeyData = try KeyUtilx.recoverPublicKeyKeccak256(from: signature.rawData, message: message)
return try PublicKey(pubKeyData)
}
@ -73,11 +85,11 @@ extension PublicKey {
slimKey.timestamp = timestamp
let bytesToSign = try slimKey.serializedData()
let pubKeyData = try KeyUtil.recoverPublicKey(message: Data(SHA256.hash(data: bytesToSign)), signature: signature.rawData)
let pubKeyData = try KeyUtilx.recoverPublicKeySHA256(from: signature.rawData, message: bytesToSign)
return try PublicKey(pubKeyData)
}
var walletAddress: String {
KeyUtil.generateAddress(from: secp256K1Uncompressed.bytes).toChecksumAddress()
KeyUtilx.generateAddress(from: secp256K1Uncompressed.bytes).toChecksumAddress()
}
}

View File

@ -5,7 +5,7 @@
// Created by Pat Nakajima on 11/23/22.
//
import XMTPProto
typealias PublicKeyBundle = Xmtp_MessageContents_PublicKeyBundle

View File

@ -6,7 +6,7 @@
//
import Foundation
import XMTPProto
typealias SealedInvitation = Xmtp_MessageContents_SealedInvitation

View File

@ -6,7 +6,7 @@
//
import Foundation
import XMTPProto
public typealias SealedInvitationHeaderV1 = Xmtp_MessageContents_SealedInvitationHeaderV1

View File

@ -6,7 +6,7 @@
//
import Foundation
import XMTPProto
typealias SealedInvitationV1 = Xmtp_MessageContents_SealedInvitationV1

View File

@ -6,8 +6,7 @@
//
import Foundation
import secp256k1
import XMTPProto
import XMTPRust
/// Represents a secp256k1 compact recoverable signature.
public typealias Signature = Xmtp_MessageContents_Signature
@ -103,19 +102,12 @@ extension Signature {
}
func verify(signedBy: PublicKey, digest: Data) throws -> Bool {
let recoverySignature = try secp256k1.Recovery.ECDSASignature(compactRepresentation: ecdsaCompact.bytes, recoveryId: Int32(ecdsaCompact.recovery))
let ecdsaSignature = try recoverySignature.normalize
let signingKey = try secp256k1.Signing.PublicKey(rawRepresentation: signedBy.secp256K1Uncompressed.bytes, format: .uncompressed)
return signingKey.ecdsa.isValidSignature(ecdsaSignature, for: digest)
}
func verify(signedBy: PublicKey, digest: any Digest) throws -> Bool {
let recoverySignature = try secp256k1.Recovery.ECDSASignature(compactRepresentation: ecdsaCompact.bytes, recoveryId: Int32(ecdsaCompact.recovery))
let ecdsaSignature = try recoverySignature.normalize
let signingKey = try secp256k1.Signing.PublicKey(rawRepresentation: signedBy.secp256K1Uncompressed.bytes, format: .uncompressed)
return signingKey.ecdsa.isValidSignature(ecdsaSignature, for: digest)
do {
let _ = try XMTPRust.verify_k256_sha256(RustVec<UInt8>(signedBy.secp256K1Uncompressed.bytes), RustVec<UInt8>(digest), RustVec<UInt8>(ecdsaCompact.bytes), UInt8(ecdsaCompact.recovery))
} catch {
return false
}
return true
}
}

View File

@ -6,7 +6,7 @@
//
import Foundation
import XMTPProto
typealias SignedContent = Xmtp_MessageContents_SignedContent

View File

@ -6,8 +6,7 @@
//
import Foundation
import secp256k1
import XMTPProto
public typealias SignedPrivateKey = Xmtp_MessageContents_SignedPrivateKey

View File

@ -7,8 +7,9 @@
import CryptoKit
import Foundation
import secp256k1
import XMTPProto
import XMTPRust
import web3
typealias SignedPublicKey = Xmtp_MessageContents_SignedPublicKey
@ -63,15 +64,15 @@ extension SignedPublicKey {
slimKey.timestamp = publicKey.timestamp
let bytesToSign = try slimKey.serializedData()
let pubKeyData = try KeyUtil.recoverPublicKey(message: Data(SHA256.hash(data: bytesToSign)), signature: publicKey.signature.rawData)
let pubKeyData = try KeyUtilx.recoverPublicKeySHA256(from: publicKey.signature.rawData, message: bytesToSign)
return try PublicKey(pubKeyData)
}
func recoverWalletSignerPublicKey() throws -> PublicKey {
let sigText = Signature.createIdentityText(key: keyBytes)
let sigHash = try Signature.ethHash(sigText)
let message = try Signature.ethPersonalMessage(sigText)
let pubKeyData = try KeyUtil.recoverPublicKey(message: sigHash, signature: signature.rawData)
let pubKeyData = try KeyUtilx.recoverPublicKeyKeccak256(from: signature.rawData, message: message)
return try PublicKey(pubKeyData)
}

View File

@ -5,7 +5,7 @@
// Created by Pat Nakajima on 11/23/22.
//
import XMTPProto
typealias SignedPublicKeyBundle = Xmtp_MessageContents_SignedPublicKeyBundle

View File

@ -6,6 +6,6 @@
//
import Foundation
import XMTPProto
typealias Token = Xmtp_MessageApi_V1_Token

View File

@ -5,13 +5,14 @@
// Created by Pat Nakajima on 11/17/22.
//
import XMTPProto
enum Topic {
public enum Topic {
case userPrivateStoreKeyBundle(String),
contact(String),
userIntro(String),
userInvite(String),
groupInvite(String),
directMessageV1(String, String),
directMessageV2(String)
@ -25,6 +26,8 @@ enum Topic {
return wrap("intro-\(address)")
case let .userInvite(address):
return wrap("invite-\(address)")
case let .groupInvite(address):
return wrap("groupInvite-\(address)")
case let .directMessageV1(address1, address2):
let addresses = [address1, address2].sorted().joined(separator: "-")
return wrap("dm-\(addresses)")

View File

@ -6,7 +6,7 @@
//
import Foundation
import XMTPProto
typealias UnsignedPublicKey = Xmtp_MessageContents_UnsignedPublicKey

View File

@ -0,0 +1,27 @@
//
// PreparedMessage.swift
//
//
// Created by Pat Nakajima on 3/9/23.
//
import CryptoKit
import Foundation
public struct PreparedMessage {
var messageEnvelope: Envelope
var conversation: Conversation
var onSend: () async throws -> Void
public func decodedMessage() throws -> DecodedMessage {
return try conversation.decode(messageEnvelope)
}
public func send() async throws {
try await onSend()
}
var messageID: String {
Data(SHA256.hash(data: messageEnvelope.message)).toHex
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_api/v1/authn.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Client authentication protocol
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// Token is used by clients to prove to the nodes
/// that they are serving a specific wallet.
public struct Xmtp_MessageApi_V1_Token {
// 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.
/// identity key signed by a wallet
public var identityKey: Xmtp_MessageContents_PublicKey {
get {return _identityKey ?? Xmtp_MessageContents_PublicKey()}
set {_identityKey = newValue}
}
/// Returns true if `identityKey` has been explicitly set.
public var hasIdentityKey: Bool {return self._identityKey != nil}
/// Clears the value of `identityKey`. Subsequent reads from it will return its default value.
public mutating func clearIdentityKey() {self._identityKey = nil}
/// encoded bytes of AuthData
public var authDataBytes: Data = Data()
/// identity key signature of AuthData bytes
public var authDataSignature: Xmtp_MessageContents_Signature {
get {return _authDataSignature ?? Xmtp_MessageContents_Signature()}
set {_authDataSignature = newValue}
}
/// Returns true if `authDataSignature` has been explicitly set.
public var hasAuthDataSignature: Bool {return self._authDataSignature != nil}
/// Clears the value of `authDataSignature`. Subsequent reads from it will return its default value.
public mutating func clearAuthDataSignature() {self._authDataSignature = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _identityKey: Xmtp_MessageContents_PublicKey? = nil
fileprivate var _authDataSignature: Xmtp_MessageContents_Signature? = nil
}
/// AuthData carries token parameters that are authenticated
/// by the identity key signature.
/// It is embedded in the Token structure as bytes
/// so that the bytes don't need to be reconstructed
/// to verify the token signature.
public struct Xmtp_MessageApi_V1_AuthData {
// 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.
/// address of the wallet
public var walletAddr: String = String()
/// time when the token was generated/signed
public var createdNs: UInt64 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageApi_V1_Token: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_AuthData: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_api.v1"
extension Xmtp_MessageApi_V1_Token: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Token"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "identity_key"),
2: .standard(proto: "auth_data_bytes"),
3: .standard(proto: "auth_data_signature"),
]
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._identityKey) }()
case 2: try { try decoder.decodeSingularBytesField(value: &self.authDataBytes) }()
case 3: try { try decoder.decodeSingularMessageField(value: &self._authDataSignature) }()
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._identityKey {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
if !self.authDataBytes.isEmpty {
try visitor.visitSingularBytesField(value: self.authDataBytes, fieldNumber: 2)
}
try { if let v = self._authDataSignature {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_Token, rhs: Xmtp_MessageApi_V1_Token) -> Bool {
if lhs._identityKey != rhs._identityKey {return false}
if lhs.authDataBytes != rhs.authDataBytes {return false}
if lhs._authDataSignature != rhs._authDataSignature {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_AuthData: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".AuthData"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "wallet_addr"),
2: .standard(proto: "created_ns"),
]
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.decodeSingularStringField(value: &self.walletAddr) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.createdNs) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.walletAddr.isEmpty {
try visitor.visitSingularStringField(value: self.walletAddr, fieldNumber: 1)
}
if self.createdNs != 0 {
try visitor.visitSingularUInt64Field(value: self.createdNs, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_AuthData, rhs: Xmtp_MessageApi_V1_AuthData) -> Bool {
if lhs.walletAddr != rhs.walletAddr {return false}
if lhs.createdNs != rhs.createdNs {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,776 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_api/v1/message_api.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Message API
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// Sort direction
public enum Xmtp_MessageApi_V1_SortDirection: SwiftProtobuf.Enum {
public typealias RawValue = Int
case unspecified // = 0
case ascending // = 1
case descending // = 2
case UNRECOGNIZED(Int)
public init() {
self = .unspecified
}
public init?(rawValue: Int) {
switch rawValue {
case 0: self = .unspecified
case 1: self = .ascending
case 2: self = .descending
default: self = .UNRECOGNIZED(rawValue)
}
}
public var rawValue: Int {
switch self {
case .unspecified: return 0
case .ascending: return 1
case .descending: return 2
case .UNRECOGNIZED(let i): return i
}
}
}
#if swift(>=4.2)
extension Xmtp_MessageApi_V1_SortDirection: CaseIterable {
// The compiler won't synthesize support with the UNRECOGNIZED case.
public static var allCases: [Xmtp_MessageApi_V1_SortDirection] = [
.unspecified,
.ascending,
.descending,
]
}
#endif // swift(>=4.2)
/// This is based off of the go-waku Index type, but with the
/// receiverTime and pubsubTopic removed for simplicity.
/// Both removed fields are optional
public struct Xmtp_MessageApi_V1_IndexCursor {
// 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 digest: Data = Data()
public var senderTimeNs: UInt64 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// Wrapper for potentially multiple types of cursor
public struct Xmtp_MessageApi_V1_Cursor {
// 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.
/// Making the cursor a one-of type, as I would like to change the way we
/// handle pagination to use a precomputed sort field.
/// This way we can handle both methods
public var cursor: Xmtp_MessageApi_V1_Cursor.OneOf_Cursor? = nil
public var index: Xmtp_MessageApi_V1_IndexCursor {
get {
if case .index(let v)? = cursor {return v}
return Xmtp_MessageApi_V1_IndexCursor()
}
set {cursor = .index(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
/// Making the cursor a one-of type, as I would like to change the way we
/// handle pagination to use a precomputed sort field.
/// This way we can handle both methods
public enum OneOf_Cursor: Equatable {
case index(Xmtp_MessageApi_V1_IndexCursor)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageApi_V1_Cursor.OneOf_Cursor, rhs: Xmtp_MessageApi_V1_Cursor.OneOf_Cursor) -> Bool {
// 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 (lhs, rhs) {
case (.index, .index): return {
guard case .index(let l) = lhs, case .index(let r) = rhs else { preconditionFailure() }
return l == r
}()
}
}
#endif
}
public init() {}
}
/// This is based off of the go-waku PagingInfo struct, but with the direction
/// changed to our SortDirection enum format
public struct Xmtp_MessageApi_V1_PagingInfo {
// 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.
/// Note: this is a uint32, while go-waku's pageSize is a uint64
public var limit: UInt32 = 0
public var cursor: Xmtp_MessageApi_V1_Cursor {
get {return _cursor ?? Xmtp_MessageApi_V1_Cursor()}
set {_cursor = newValue}
}
/// Returns true if `cursor` has been explicitly set.
public var hasCursor: Bool {return self._cursor != nil}
/// Clears the value of `cursor`. Subsequent reads from it will return its default value.
public mutating func clearCursor() {self._cursor = nil}
public var direction: Xmtp_MessageApi_V1_SortDirection = .unspecified
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _cursor: Xmtp_MessageApi_V1_Cursor? = nil
}
/// Envelope encapsulates a message while in transit.
public struct Xmtp_MessageApi_V1_Envelope {
// 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 topic the message belongs to,
/// If the message includes the topic as well
/// it MUST be the same as the topic in the envelope.
public var contentTopic: String = String()
/// Message creation timestamp
/// If the message includes the timestamp as well
/// it MUST be equivalent to the timestamp in the envelope.
public var timestampNs: UInt64 = 0
public var message: Data = Data()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// Publish
public struct Xmtp_MessageApi_V1_PublishRequest {
// 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 envelopes: [Xmtp_MessageApi_V1_Envelope] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// Empty message as a response for Publish
public struct Xmtp_MessageApi_V1_PublishResponse {
// 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 unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// Subscribe
public struct Xmtp_MessageApi_V1_SubscribeRequest {
// 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 contentTopics: [String] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// SubscribeAll
public struct Xmtp_MessageApi_V1_SubscribeAllRequest {
// 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 unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// Query
public struct Xmtp_MessageApi_V1_QueryRequest {
// 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 contentTopics: [String] = []
public var startTimeNs: UInt64 = 0
public var endTimeNs: UInt64 = 0
public var pagingInfo: Xmtp_MessageApi_V1_PagingInfo {
get {return _pagingInfo ?? Xmtp_MessageApi_V1_PagingInfo()}
set {_pagingInfo = newValue}
}
/// Returns true if `pagingInfo` has been explicitly set.
public var hasPagingInfo: Bool {return self._pagingInfo != nil}
/// Clears the value of `pagingInfo`. Subsequent reads from it will return its default value.
public mutating func clearPagingInfo() {self._pagingInfo = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _pagingInfo: Xmtp_MessageApi_V1_PagingInfo? = nil
}
/// The response, containing envelopes, for a query
public struct Xmtp_MessageApi_V1_QueryResponse {
// 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 envelopes: [Xmtp_MessageApi_V1_Envelope] = []
public var pagingInfo: Xmtp_MessageApi_V1_PagingInfo {
get {return _pagingInfo ?? Xmtp_MessageApi_V1_PagingInfo()}
set {_pagingInfo = newValue}
}
/// Returns true if `pagingInfo` has been explicitly set.
public var hasPagingInfo: Bool {return self._pagingInfo != nil}
/// Clears the value of `pagingInfo`. Subsequent reads from it will return its default value.
public mutating func clearPagingInfo() {self._pagingInfo = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _pagingInfo: Xmtp_MessageApi_V1_PagingInfo? = nil
}
/// BatchQuery
public struct Xmtp_MessageApi_V1_BatchQueryRequest {
// 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 requests: [Xmtp_MessageApi_V1_QueryRequest] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// Response containing a list of QueryResponse messages
public struct Xmtp_MessageApi_V1_BatchQueryResponse {
// 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 responses: [Xmtp_MessageApi_V1_QueryResponse] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageApi_V1_SortDirection: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_IndexCursor: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_Cursor: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_Cursor.OneOf_Cursor: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_PagingInfo: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_Envelope: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_PublishRequest: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_PublishResponse: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_SubscribeRequest: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_SubscribeAllRequest: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_QueryRequest: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_QueryResponse: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_BatchQueryRequest: @unchecked Sendable {}
extension Xmtp_MessageApi_V1_BatchQueryResponse: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_api.v1"
extension Xmtp_MessageApi_V1_SortDirection: SwiftProtobuf._ProtoNameProviding {
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "SORT_DIRECTION_UNSPECIFIED"),
1: .same(proto: "SORT_DIRECTION_ASCENDING"),
2: .same(proto: "SORT_DIRECTION_DESCENDING"),
]
}
extension Xmtp_MessageApi_V1_IndexCursor: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".IndexCursor"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "digest"),
2: .standard(proto: "sender_time_ns"),
]
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.decodeSingularBytesField(value: &self.digest) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.senderTimeNs) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.digest.isEmpty {
try visitor.visitSingularBytesField(value: self.digest, fieldNumber: 1)
}
if self.senderTimeNs != 0 {
try visitor.visitSingularUInt64Field(value: self.senderTimeNs, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_IndexCursor, rhs: Xmtp_MessageApi_V1_IndexCursor) -> Bool {
if lhs.digest != rhs.digest {return false}
if lhs.senderTimeNs != rhs.senderTimeNs {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_Cursor: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Cursor"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "index"),
]
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 {
var v: Xmtp_MessageApi_V1_IndexCursor?
var hadOneofValue = false
if let current = self.cursor {
hadOneofValue = true
if case .index(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.cursor = .index(v)
}
}()
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 case .index(let v)? = self.cursor {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_Cursor, rhs: Xmtp_MessageApi_V1_Cursor) -> Bool {
if lhs.cursor != rhs.cursor {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_PagingInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".PagingInfo"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "limit"),
2: .same(proto: "cursor"),
3: .same(proto: "direction"),
]
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.decodeSingularUInt32Field(value: &self.limit) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._cursor) }()
case 3: try { try decoder.decodeSingularEnumField(value: &self.direction) }()
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
if self.limit != 0 {
try visitor.visitSingularUInt32Field(value: self.limit, fieldNumber: 1)
}
try { if let v = self._cursor {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
if self.direction != .unspecified {
try visitor.visitSingularEnumField(value: self.direction, fieldNumber: 3)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_PagingInfo, rhs: Xmtp_MessageApi_V1_PagingInfo) -> Bool {
if lhs.limit != rhs.limit {return false}
if lhs._cursor != rhs._cursor {return false}
if lhs.direction != rhs.direction {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_Envelope: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Envelope"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "content_topic"),
2: .standard(proto: "timestamp_ns"),
3: .same(proto: "message"),
]
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.decodeSingularStringField(value: &self.contentTopic) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.timestampNs) }()
case 3: try { try decoder.decodeSingularBytesField(value: &self.message) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.contentTopic.isEmpty {
try visitor.visitSingularStringField(value: self.contentTopic, fieldNumber: 1)
}
if self.timestampNs != 0 {
try visitor.visitSingularUInt64Field(value: self.timestampNs, fieldNumber: 2)
}
if !self.message.isEmpty {
try visitor.visitSingularBytesField(value: self.message, fieldNumber: 3)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_Envelope, rhs: Xmtp_MessageApi_V1_Envelope) -> Bool {
if lhs.contentTopic != rhs.contentTopic {return false}
if lhs.timestampNs != rhs.timestampNs {return false}
if lhs.message != rhs.message {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_PublishRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".PublishRequest"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "envelopes"),
]
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.decodeRepeatedMessageField(value: &self.envelopes) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.envelopes.isEmpty {
try visitor.visitRepeatedMessageField(value: self.envelopes, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_PublishRequest, rhs: Xmtp_MessageApi_V1_PublishRequest) -> Bool {
if lhs.envelopes != rhs.envelopes {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_PublishResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".PublishResponse"
public static let _protobuf_nameMap = SwiftProtobuf._NameMap()
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let _ = try decoder.nextFieldNumber() {
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_PublishResponse, rhs: Xmtp_MessageApi_V1_PublishResponse) -> Bool {
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_SubscribeRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SubscribeRequest"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "content_topics"),
]
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.decodeRepeatedStringField(value: &self.contentTopics) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.contentTopics.isEmpty {
try visitor.visitRepeatedStringField(value: self.contentTopics, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_SubscribeRequest, rhs: Xmtp_MessageApi_V1_SubscribeRequest) -> Bool {
if lhs.contentTopics != rhs.contentTopics {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_SubscribeAllRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SubscribeAllRequest"
public static let _protobuf_nameMap = SwiftProtobuf._NameMap()
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let _ = try decoder.nextFieldNumber() {
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_SubscribeAllRequest, rhs: Xmtp_MessageApi_V1_SubscribeAllRequest) -> Bool {
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_QueryRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".QueryRequest"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "content_topics"),
2: .standard(proto: "start_time_ns"),
3: .standard(proto: "end_time_ns"),
4: .standard(proto: "paging_info"),
]
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.decodeRepeatedStringField(value: &self.contentTopics) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.startTimeNs) }()
case 3: try { try decoder.decodeSingularUInt64Field(value: &self.endTimeNs) }()
case 4: try { try decoder.decodeSingularMessageField(value: &self._pagingInfo) }()
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
if !self.contentTopics.isEmpty {
try visitor.visitRepeatedStringField(value: self.contentTopics, fieldNumber: 1)
}
if self.startTimeNs != 0 {
try visitor.visitSingularUInt64Field(value: self.startTimeNs, fieldNumber: 2)
}
if self.endTimeNs != 0 {
try visitor.visitSingularUInt64Field(value: self.endTimeNs, fieldNumber: 3)
}
try { if let v = self._pagingInfo {
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_QueryRequest, rhs: Xmtp_MessageApi_V1_QueryRequest) -> Bool {
if lhs.contentTopics != rhs.contentTopics {return false}
if lhs.startTimeNs != rhs.startTimeNs {return false}
if lhs.endTimeNs != rhs.endTimeNs {return false}
if lhs._pagingInfo != rhs._pagingInfo {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_QueryResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".QueryResponse"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "envelopes"),
2: .standard(proto: "paging_info"),
]
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.decodeRepeatedMessageField(value: &self.envelopes) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._pagingInfo) }()
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
if !self.envelopes.isEmpty {
try visitor.visitRepeatedMessageField(value: self.envelopes, fieldNumber: 1)
}
try { if let v = self._pagingInfo {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_QueryResponse, rhs: Xmtp_MessageApi_V1_QueryResponse) -> Bool {
if lhs.envelopes != rhs.envelopes {return false}
if lhs._pagingInfo != rhs._pagingInfo {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_BatchQueryRequest: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".BatchQueryRequest"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "requests"),
]
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.decodeRepeatedMessageField(value: &self.requests) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.requests.isEmpty {
try visitor.visitRepeatedMessageField(value: self.requests, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_BatchQueryRequest, rhs: Xmtp_MessageApi_V1_BatchQueryRequest) -> Bool {
if lhs.requests != rhs.requests {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageApi_V1_BatchQueryResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".BatchQueryResponse"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "responses"),
]
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.decodeRepeatedMessageField(value: &self.responses) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.responses.isEmpty {
try visitor.visitRepeatedMessageField(value: self.responses, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageApi_V1_BatchQueryResponse, rhs: Xmtp_MessageApi_V1_BatchQueryResponse) -> Bool {
if lhs.responses != rhs.responses {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,331 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_contents/ciphertext.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Ciphertext is a generic structure for encrypted payload.
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// Ciphertext represents encrypted payload.
/// It is definited as a union to support cryptographic algorithm agility.
/// The payload is accompanied by the cryptographic parameters
/// required by the chosen encryption scheme.
public struct Xmtp_MessageContents_Ciphertext {
// 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 union: Xmtp_MessageContents_Ciphertext.OneOf_Union? = nil
public var aes256GcmHkdfSha256: Xmtp_MessageContents_Ciphertext.Aes256gcmHkdfsha256 {
get {
if case .aes256GcmHkdfSha256(let v)? = union {return v}
return Xmtp_MessageContents_Ciphertext.Aes256gcmHkdfsha256()
}
set {union = .aes256GcmHkdfSha256(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public enum OneOf_Union: Equatable {
case aes256GcmHkdfSha256(Xmtp_MessageContents_Ciphertext.Aes256gcmHkdfsha256)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_Ciphertext.OneOf_Union, rhs: Xmtp_MessageContents_Ciphertext.OneOf_Union) -> Bool {
// 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 (lhs, rhs) {
case (.aes256GcmHkdfSha256, .aes256GcmHkdfSha256): return {
guard case .aes256GcmHkdfSha256(let l) = lhs, case .aes256GcmHkdfSha256(let r) = rhs else { preconditionFailure() }
return l == r
}()
}
}
#endif
}
/// Encryption: AES256-GCM
/// Key derivation function: HKDF-SHA256
public struct Aes256gcmHkdfsha256 {
// 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.
/// 32 bytes
public var hkdfSalt: Data = Data()
/// 12 bytes
public var gcmNonce: Data = Data()
/// encrypted payload
public var payload: Data = Data()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public init() {}
}
/// SignedEciesCiphertext represents an ECIES encrypted payload and a signature
public struct Xmtp_MessageContents_SignedEciesCiphertext {
// 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.
/// serialized Ecies message
public var eciesBytes: Data = Data()
/// signature of sha256(ecies_bytes) signed with the IdentityKey
public var signature: Xmtp_MessageContents_Signature {
get {return _signature ?? Xmtp_MessageContents_Signature()}
set {_signature = newValue}
}
/// Returns true if `signature` has been explicitly set.
public var hasSignature: Bool {return self._signature != nil}
/// Clears the value of `signature`. Subsequent reads from it will return its default value.
public mutating func clearSignature() {self._signature = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
/// Ecies is ciphertext encrypted using ECIES with a MAC
public struct Ecies {
// 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.
/// 65 bytes
public var ephemeralPublicKey: Data = Data()
/// 16 bytes
public var iv: Data = Data()
/// 32 bytes
public var mac: Data = Data()
/// encrypted payload with block size of 16
public var ciphertext: Data = Data()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public init() {}
fileprivate var _signature: Xmtp_MessageContents_Signature? = nil
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageContents_Ciphertext: @unchecked Sendable {}
extension Xmtp_MessageContents_Ciphertext.OneOf_Union: @unchecked Sendable {}
extension Xmtp_MessageContents_Ciphertext.Aes256gcmHkdfsha256: @unchecked Sendable {}
extension Xmtp_MessageContents_SignedEciesCiphertext: @unchecked Sendable {}
extension Xmtp_MessageContents_SignedEciesCiphertext.Ecies: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_contents"
extension Xmtp_MessageContents_Ciphertext: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Ciphertext"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "aes256_gcm_hkdf_sha256"),
]
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 {
var v: Xmtp_MessageContents_Ciphertext.Aes256gcmHkdfsha256?
var hadOneofValue = false
if let current = self.union {
hadOneofValue = true
if case .aes256GcmHkdfSha256(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.union = .aes256GcmHkdfSha256(v)
}
}()
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 case .aes256GcmHkdfSha256(let v)? = self.union {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_Ciphertext, rhs: Xmtp_MessageContents_Ciphertext) -> Bool {
if lhs.union != rhs.union {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_Ciphertext.Aes256gcmHkdfsha256: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_Ciphertext.protoMessageName + ".Aes256gcmHkdfsha256"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "hkdf_salt"),
2: .standard(proto: "gcm_nonce"),
3: .same(proto: "payload"),
]
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.decodeSingularBytesField(value: &self.hkdfSalt) }()
case 2: try { try decoder.decodeSingularBytesField(value: &self.gcmNonce) }()
case 3: try { try decoder.decodeSingularBytesField(value: &self.payload) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.hkdfSalt.isEmpty {
try visitor.visitSingularBytesField(value: self.hkdfSalt, fieldNumber: 1)
}
if !self.gcmNonce.isEmpty {
try visitor.visitSingularBytesField(value: self.gcmNonce, fieldNumber: 2)
}
if !self.payload.isEmpty {
try visitor.visitSingularBytesField(value: self.payload, fieldNumber: 3)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_Ciphertext.Aes256gcmHkdfsha256, rhs: Xmtp_MessageContents_Ciphertext.Aes256gcmHkdfsha256) -> Bool {
if lhs.hkdfSalt != rhs.hkdfSalt {return false}
if lhs.gcmNonce != rhs.gcmNonce {return false}
if lhs.payload != rhs.payload {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_SignedEciesCiphertext: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SignedEciesCiphertext"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "ecies_bytes"),
2: .same(proto: "signature"),
]
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.decodeSingularBytesField(value: &self.eciesBytes) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._signature) }()
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
if !self.eciesBytes.isEmpty {
try visitor.visitSingularBytesField(value: self.eciesBytes, fieldNumber: 1)
}
try { if let v = self._signature {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_SignedEciesCiphertext, rhs: Xmtp_MessageContents_SignedEciesCiphertext) -> Bool {
if lhs.eciesBytes != rhs.eciesBytes {return false}
if lhs._signature != rhs._signature {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_SignedEciesCiphertext.Ecies: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_SignedEciesCiphertext.protoMessageName + ".Ecies"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "ephemeral_public_key"),
2: .same(proto: "iv"),
3: .same(proto: "mac"),
4: .same(proto: "ciphertext"),
]
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.decodeSingularBytesField(value: &self.ephemeralPublicKey) }()
case 2: try { try decoder.decodeSingularBytesField(value: &self.iv) }()
case 3: try { try decoder.decodeSingularBytesField(value: &self.mac) }()
case 4: try { try decoder.decodeSingularBytesField(value: &self.ciphertext) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.ephemeralPublicKey.isEmpty {
try visitor.visitSingularBytesField(value: self.ephemeralPublicKey, fieldNumber: 1)
}
if !self.iv.isEmpty {
try visitor.visitSingularBytesField(value: self.iv, fieldNumber: 2)
}
if !self.mac.isEmpty {
try visitor.visitSingularBytesField(value: self.mac, fieldNumber: 3)
}
if !self.ciphertext.isEmpty {
try visitor.visitSingularBytesField(value: self.ciphertext, fieldNumber: 4)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_SignedEciesCiphertext.Ecies, rhs: Xmtp_MessageContents_SignedEciesCiphertext.Ecies) -> Bool {
if lhs.ephemeralPublicKey != rhs.ephemeralPublicKey {return false}
if lhs.iv != rhs.iv {return false}
if lhs.mac != rhs.mac {return false}
if lhs.ciphertext != rhs.ciphertext {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,201 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_contents/composite.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Composite ContentType
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// Composite is used to implement xmtp.org/composite content type
public struct Xmtp_MessageContents_Composite {
// 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 parts: [Xmtp_MessageContents_Composite.Part] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
/// Part represents one section of a composite message
public struct Part {
// 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 element: Xmtp_MessageContents_Composite.Part.OneOf_Element? = nil
public var part: Xmtp_MessageContents_EncodedContent {
get {
if case .part(let v)? = element {return v}
return Xmtp_MessageContents_EncodedContent()
}
set {element = .part(newValue)}
}
public var composite: Xmtp_MessageContents_Composite {
get {
if case .composite(let v)? = element {return v}
return Xmtp_MessageContents_Composite()
}
set {element = .composite(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public enum OneOf_Element: Equatable {
case part(Xmtp_MessageContents_EncodedContent)
case composite(Xmtp_MessageContents_Composite)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_Composite.Part.OneOf_Element, rhs: Xmtp_MessageContents_Composite.Part.OneOf_Element) -> Bool {
// 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 (lhs, rhs) {
case (.part, .part): return {
guard case .part(let l) = lhs, case .part(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.composite, .composite): return {
guard case .composite(let l) = lhs, case .composite(let r) = rhs else { preconditionFailure() }
return l == r
}()
default: return false
}
}
#endif
}
public init() {}
}
public init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageContents_Composite: @unchecked Sendable {}
extension Xmtp_MessageContents_Composite.Part: @unchecked Sendable {}
extension Xmtp_MessageContents_Composite.Part.OneOf_Element: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_contents"
extension Xmtp_MessageContents_Composite: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Composite"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "parts"),
]
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.decodeRepeatedMessageField(value: &self.parts) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.parts.isEmpty {
try visitor.visitRepeatedMessageField(value: self.parts, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_Composite, rhs: Xmtp_MessageContents_Composite) -> Bool {
if lhs.parts != rhs.parts {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_Composite.Part: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_Composite.protoMessageName + ".Part"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "part"),
2: .same(proto: "composite"),
]
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 {
var v: Xmtp_MessageContents_EncodedContent?
var hadOneofValue = false
if let current = self.element {
hadOneofValue = true
if case .part(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.element = .part(v)
}
}()
case 2: try {
var v: Xmtp_MessageContents_Composite?
var hadOneofValue = false
if let current = self.element {
hadOneofValue = true
if case .composite(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.element = .composite(v)
}
}()
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
switch self.element {
case .part?: try {
guard case .part(let v)? = self.element else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
}()
case .composite?: try {
guard case .composite(let v)? = self.element else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
}()
case nil: break
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_Composite.Part, rhs: Xmtp_MessageContents_Composite.Part) -> Bool {
if lhs.element != rhs.element {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,278 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_contents/contact.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Contact Bundles are used to advertise user's public keys on the network.
/// They are published in well known topics so that other participants
/// can find them when they wish to communicate with the user.
/// The public keys are used to sign messages and to derive encryption keys
/// for some meta-messages, e.g. invitations.
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// LEGACY: User key bundle V1 using PublicKeys.
/// The PublicKeys MUST be signed.
public struct Xmtp_MessageContents_ContactBundleV1 {
// 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 keyBundle: Xmtp_MessageContents_PublicKeyBundle {
get {return _keyBundle ?? Xmtp_MessageContents_PublicKeyBundle()}
set {_keyBundle = newValue}
}
/// Returns true if `keyBundle` has been explicitly set.
public var hasKeyBundle: Bool {return self._keyBundle != nil}
/// Clears the value of `keyBundle`. Subsequent reads from it will return its default value.
public mutating func clearKeyBundle() {self._keyBundle = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _keyBundle: Xmtp_MessageContents_PublicKeyBundle? = nil
}
/// User key bundle V2 using SignedPublicKeys.
public struct Xmtp_MessageContents_ContactBundleV2 {
// 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 keyBundle: Xmtp_MessageContents_SignedPublicKeyBundle {
get {return _keyBundle ?? Xmtp_MessageContents_SignedPublicKeyBundle()}
set {_keyBundle = newValue}
}
/// Returns true if `keyBundle` has been explicitly set.
public var hasKeyBundle: Bool {return self._keyBundle != nil}
/// Clears the value of `keyBundle`. Subsequent reads from it will return its default value.
public mutating func clearKeyBundle() {self._keyBundle = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _keyBundle: Xmtp_MessageContents_SignedPublicKeyBundle? = nil
}
/// Versioned ContactBundle
public struct Xmtp_MessageContents_ContactBundle {
// 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 version: Xmtp_MessageContents_ContactBundle.OneOf_Version? = nil
public var v1: Xmtp_MessageContents_ContactBundleV1 {
get {
if case .v1(let v)? = version {return v}
return Xmtp_MessageContents_ContactBundleV1()
}
set {version = .v1(newValue)}
}
public var v2: Xmtp_MessageContents_ContactBundleV2 {
get {
if case .v2(let v)? = version {return v}
return Xmtp_MessageContents_ContactBundleV2()
}
set {version = .v2(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public enum OneOf_Version: Equatable {
case v1(Xmtp_MessageContents_ContactBundleV1)
case v2(Xmtp_MessageContents_ContactBundleV2)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_ContactBundle.OneOf_Version, rhs: Xmtp_MessageContents_ContactBundle.OneOf_Version) -> Bool {
// 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 (lhs, rhs) {
case (.v1, .v1): return {
guard case .v1(let l) = lhs, case .v1(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.v2, .v2): return {
guard case .v2(let l) = lhs, case .v2(let r) = rhs else { preconditionFailure() }
return l == r
}()
default: return false
}
}
#endif
}
public init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageContents_ContactBundleV1: @unchecked Sendable {}
extension Xmtp_MessageContents_ContactBundleV2: @unchecked Sendable {}
extension Xmtp_MessageContents_ContactBundle: @unchecked Sendable {}
extension Xmtp_MessageContents_ContactBundle.OneOf_Version: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_contents"
extension Xmtp_MessageContents_ContactBundleV1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ContactBundleV1"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "key_bundle"),
]
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._keyBundle) }()
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._keyBundle {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_ContactBundleV1, rhs: Xmtp_MessageContents_ContactBundleV1) -> Bool {
if lhs._keyBundle != rhs._keyBundle {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_ContactBundleV2: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ContactBundleV2"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "key_bundle"),
]
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._keyBundle) }()
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._keyBundle {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_ContactBundleV2, rhs: Xmtp_MessageContents_ContactBundleV2) -> Bool {
if lhs._keyBundle != rhs._keyBundle {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_ContactBundle: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ContactBundle"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "v1"),
2: .same(proto: "v2"),
]
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 {
var v: Xmtp_MessageContents_ContactBundleV1?
var hadOneofValue = false
if let current = self.version {
hadOneofValue = true
if case .v1(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.version = .v1(v)
}
}()
case 2: try {
var v: Xmtp_MessageContents_ContactBundleV2?
var hadOneofValue = false
if let current = self.version {
hadOneofValue = true
if case .v2(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.version = .v2(v)
}
}()
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
switch self.version {
case .v1?: try {
guard case .v1(let v)? = self.version else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
}()
case .v2?: try {
guard case .v2(let v)? = self.version else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
}()
case nil: break
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_ContactBundle, rhs: Xmtp_MessageContents_ContactBundle) -> Bool {
if lhs.version != rhs.version {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,357 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_contents/content.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Message content encoding structures
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// Recognized compression algorithms
/// protolint:disable ENUM_FIELD_NAMES_ZERO_VALUE_END_WITH
public enum Xmtp_MessageContents_Compression: SwiftProtobuf.Enum {
public typealias RawValue = Int
case deflate // = 0
case gzip // = 1
case UNRECOGNIZED(Int)
public init() {
self = .deflate
}
public init?(rawValue: Int) {
switch rawValue {
case 0: self = .deflate
case 1: self = .gzip
default: self = .UNRECOGNIZED(rawValue)
}
}
public var rawValue: Int {
switch self {
case .deflate: return 0
case .gzip: return 1
case .UNRECOGNIZED(let i): return i
}
}
}
#if swift(>=4.2)
extension Xmtp_MessageContents_Compression: CaseIterable {
// The compiler won't synthesize support with the UNRECOGNIZED case.
public static var allCases: [Xmtp_MessageContents_Compression] = [
.deflate,
.gzip,
]
}
#endif // swift(>=4.2)
/// ContentTypeId is used to identify the type of content stored in a Message.
public struct Xmtp_MessageContents_ContentTypeId {
// 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.
/// authority governing this content type
public var authorityID: String = String()
/// type identifier
public var typeID: String = String()
/// major version of the type
public var versionMajor: UInt32 = 0
/// minor version of the type
public var versionMinor: UInt32 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// EncodedContent bundles the content with metadata identifying its type
/// and parameters required for correct decoding and presentation of the content.
public struct Xmtp_MessageContents_EncodedContent {
// 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.
/// content type identifier used to match the payload with
/// the correct decoding machinery
public var type: Xmtp_MessageContents_ContentTypeId {
get {return _type ?? Xmtp_MessageContents_ContentTypeId()}
set {_type = newValue}
}
/// Returns true if `type` has been explicitly set.
public var hasType: Bool {return self._type != nil}
/// Clears the value of `type`. Subsequent reads from it will return its default value.
public mutating func clearType() {self._type = nil}
/// optional encoding parameters required to correctly decode the content
public var parameters: Dictionary<String,String> = [:]
/// optional fallback description of the content that can be used in case
/// the client cannot decode or render the content
public var fallback: String {
get {return _fallback ?? String()}
set {_fallback = newValue}
}
/// Returns true if `fallback` has been explicitly set.
public var hasFallback: Bool {return self._fallback != nil}
/// Clears the value of `fallback`. Subsequent reads from it will return its default value.
public mutating func clearFallback() {self._fallback = nil}
/// optional compression; the value indicates algorithm used to
/// compress the encoded content bytes
public var compression: Xmtp_MessageContents_Compression {
get {return _compression ?? .deflate}
set {_compression = newValue}
}
/// Returns true if `compression` has been explicitly set.
public var hasCompression: Bool {return self._compression != nil}
/// Clears the value of `compression`. Subsequent reads from it will return its default value.
public mutating func clearCompression() {self._compression = nil}
/// encoded content itself
public var content: Data = Data()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _type: Xmtp_MessageContents_ContentTypeId? = nil
fileprivate var _fallback: String? = nil
fileprivate var _compression: Xmtp_MessageContents_Compression? = nil
}
/// SignedContent attaches a signature to EncodedContent.
public struct Xmtp_MessageContents_SignedContent {
// 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.
/// MUST contain EncodedContent
public var payload: Data = Data()
public var sender: Xmtp_MessageContents_SignedPublicKeyBundle {
get {return _sender ?? Xmtp_MessageContents_SignedPublicKeyBundle()}
set {_sender = newValue}
}
/// Returns true if `sender` has been explicitly set.
public var hasSender: Bool {return self._sender != nil}
/// Clears the value of `sender`. Subsequent reads from it will return its default value.
public mutating func clearSender() {self._sender = nil}
/// MUST be a signature of a concatenation of
/// the message header bytes and the payload bytes,
/// signed by the sender's pre-key.
public var signature: Xmtp_MessageContents_Signature {
get {return _signature ?? Xmtp_MessageContents_Signature()}
set {_signature = newValue}
}
/// Returns true if `signature` has been explicitly set.
public var hasSignature: Bool {return self._signature != nil}
/// Clears the value of `signature`. Subsequent reads from it will return its default value.
public mutating func clearSignature() {self._signature = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _sender: Xmtp_MessageContents_SignedPublicKeyBundle? = nil
fileprivate var _signature: Xmtp_MessageContents_Signature? = nil
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageContents_Compression: @unchecked Sendable {}
extension Xmtp_MessageContents_ContentTypeId: @unchecked Sendable {}
extension Xmtp_MessageContents_EncodedContent: @unchecked Sendable {}
extension Xmtp_MessageContents_SignedContent: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_contents"
extension Xmtp_MessageContents_Compression: SwiftProtobuf._ProtoNameProviding {
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "COMPRESSION_DEFLATE"),
1: .same(proto: "COMPRESSION_GZIP"),
]
}
extension Xmtp_MessageContents_ContentTypeId: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ContentTypeId"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "authority_id"),
2: .standard(proto: "type_id"),
3: .standard(proto: "version_major"),
4: .standard(proto: "version_minor"),
]
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.decodeSingularStringField(value: &self.authorityID) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.typeID) }()
case 3: try { try decoder.decodeSingularUInt32Field(value: &self.versionMajor) }()
case 4: try { try decoder.decodeSingularUInt32Field(value: &self.versionMinor) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.authorityID.isEmpty {
try visitor.visitSingularStringField(value: self.authorityID, fieldNumber: 1)
}
if !self.typeID.isEmpty {
try visitor.visitSingularStringField(value: self.typeID, fieldNumber: 2)
}
if self.versionMajor != 0 {
try visitor.visitSingularUInt32Field(value: self.versionMajor, fieldNumber: 3)
}
if self.versionMinor != 0 {
try visitor.visitSingularUInt32Field(value: self.versionMinor, fieldNumber: 4)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_ContentTypeId, rhs: Xmtp_MessageContents_ContentTypeId) -> Bool {
if lhs.authorityID != rhs.authorityID {return false}
if lhs.typeID != rhs.typeID {return false}
if lhs.versionMajor != rhs.versionMajor {return false}
if lhs.versionMinor != rhs.versionMinor {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_EncodedContent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".EncodedContent"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "type"),
2: .same(proto: "parameters"),
3: .same(proto: "fallback"),
5: .same(proto: "compression"),
4: .same(proto: "content"),
]
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._type) }()
case 2: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMap<SwiftProtobuf.ProtobufString,SwiftProtobuf.ProtobufString>.self, value: &self.parameters) }()
case 3: try { try decoder.decodeSingularStringField(value: &self._fallback) }()
case 4: try { try decoder.decodeSingularBytesField(value: &self.content) }()
case 5: try { try decoder.decodeSingularEnumField(value: &self._compression) }()
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._type {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
if !self.parameters.isEmpty {
try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMap<SwiftProtobuf.ProtobufString,SwiftProtobuf.ProtobufString>.self, value: self.parameters, fieldNumber: 2)
}
try { if let v = self._fallback {
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
} }()
if !self.content.isEmpty {
try visitor.visitSingularBytesField(value: self.content, fieldNumber: 4)
}
try { if let v = self._compression {
try visitor.visitSingularEnumField(value: v, fieldNumber: 5)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_EncodedContent, rhs: Xmtp_MessageContents_EncodedContent) -> Bool {
if lhs._type != rhs._type {return false}
if lhs.parameters != rhs.parameters {return false}
if lhs._fallback != rhs._fallback {return false}
if lhs._compression != rhs._compression {return false}
if lhs.content != rhs.content {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_SignedContent: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SignedContent"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "payload"),
2: .same(proto: "sender"),
3: .same(proto: "signature"),
]
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.decodeSingularBytesField(value: &self.payload) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._sender) }()
case 3: try { try decoder.decodeSingularMessageField(value: &self._signature) }()
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
if !self.payload.isEmpty {
try visitor.visitSingularBytesField(value: self.payload, fieldNumber: 1)
}
try { if let v = self._sender {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try { if let v = self._signature {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_SignedContent, rhs: Xmtp_MessageContents_SignedContent) -> Bool {
if lhs.payload != rhs.payload {return false}
if lhs._sender != rhs._sender {return false}
if lhs._signature != rhs._signature {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,113 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_contents/conversation_reference.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Holds the ConversationReference
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// A light pointer for a conversation that contains no decryption keys
public struct Xmtp_MessageContents_ConversationReference {
// 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 topic: String = String()
public var peerAddress: String = String()
public var createdNs: UInt64 = 0
public var context: Xmtp_MessageContents_InvitationV1.Context {
get {return _context ?? Xmtp_MessageContents_InvitationV1.Context()}
set {_context = newValue}
}
/// Returns true if `context` has been explicitly set.
public var hasContext: Bool {return self._context != nil}
/// Clears the value of `context`. Subsequent reads from it will return its default value.
public mutating func clearContext() {self._context = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _context: Xmtp_MessageContents_InvitationV1.Context? = nil
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageContents_ConversationReference: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_contents"
extension Xmtp_MessageContents_ConversationReference: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ConversationReference"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "topic"),
2: .standard(proto: "peer_address"),
3: .standard(proto: "created_ns"),
4: .same(proto: "context"),
]
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.decodeSingularStringField(value: &self.topic) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.peerAddress) }()
case 3: try { try decoder.decodeSingularUInt64Field(value: &self.createdNs) }()
case 4: try { try decoder.decodeSingularMessageField(value: &self._context) }()
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
if !self.topic.isEmpty {
try visitor.visitSingularStringField(value: self.topic, fieldNumber: 1)
}
if !self.peerAddress.isEmpty {
try visitor.visitSingularStringField(value: self.peerAddress, fieldNumber: 2)
}
if self.createdNs != 0 {
try visitor.visitSingularUInt64Field(value: self.createdNs, fieldNumber: 3)
}
try { if let v = self._context {
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_ConversationReference, rhs: Xmtp_MessageContents_ConversationReference) -> Bool {
if lhs.topic != rhs.topic {return false}
if lhs.peerAddress != rhs.peerAddress {return false}
if lhs.createdNs != rhs.createdNs {return false}
if lhs._context != rhs._context {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,506 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_contents/invitation.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Invitation is used by an initiator to invite participants
/// into a new conversation. Invitation carries the chosen topic name
/// and encryption scheme and key material to be used for message encryption.
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// Unsealed invitation V1
public struct Xmtp_MessageContents_InvitationV1 {
// 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.
/// topic name chosen for this conversation.
/// It MUST be randomly generated bytes (length >= 32),
/// then base64 encoded without padding
public var topic: String = String()
/// A context object defining metadata
public var context: Xmtp_MessageContents_InvitationV1.Context {
get {return _context ?? Xmtp_MessageContents_InvitationV1.Context()}
set {_context = newValue}
}
/// Returns true if `context` has been explicitly set.
public var hasContext: Bool {return self._context != nil}
/// Clears the value of `context`. Subsequent reads from it will return its default value.
public mutating func clearContext() {self._context = nil}
/// message encryption scheme and keys for this conversation.
public var encryption: Xmtp_MessageContents_InvitationV1.OneOf_Encryption? = nil
/// Specify the encryption method to process the key material properly.
public var aes256GcmHkdfSha256: Xmtp_MessageContents_InvitationV1.Aes256gcmHkdfsha256 {
get {
if case .aes256GcmHkdfSha256(let v)? = encryption {return v}
return Xmtp_MessageContents_InvitationV1.Aes256gcmHkdfsha256()
}
set {encryption = .aes256GcmHkdfSha256(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
/// message encryption scheme and keys for this conversation.
public enum OneOf_Encryption: Equatable {
/// Specify the encryption method to process the key material properly.
case aes256GcmHkdfSha256(Xmtp_MessageContents_InvitationV1.Aes256gcmHkdfsha256)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_InvitationV1.OneOf_Encryption, rhs: Xmtp_MessageContents_InvitationV1.OneOf_Encryption) -> Bool {
// 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 (lhs, rhs) {
case (.aes256GcmHkdfSha256, .aes256GcmHkdfSha256): return {
guard case .aes256GcmHkdfSha256(let l) = lhs, case .aes256GcmHkdfSha256(let r) = rhs else { preconditionFailure() }
return l == r
}()
}
}
#endif
}
/// Supported encryption schemes
/// AES256-GCM-HKDF-SHA256
public struct Aes256gcmHkdfsha256 {
// 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.
/// randomly generated key material (32 bytes)
public var keyMaterial: Data = Data()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// The context type
public struct Context {
// 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.
/// Expected to be a URI (ie xmtp.org/convo1)
public var conversationID: String = String()
/// Key value map of additional metadata that would be exposed to
/// application developers and could be used for filtering
public var metadata: Dictionary<String,String> = [:]
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public init() {}
fileprivate var _context: Xmtp_MessageContents_InvitationV1.Context? = nil
}
/// Sealed Invitation V1 Header
/// Header carries information that is unencrypted, thus readable by the network
/// it is however authenticated as associated data with the AEAD scheme used
/// to encrypt the invitation body, thus providing tamper evidence.
public struct Xmtp_MessageContents_SealedInvitationHeaderV1 {
// 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 sender: Xmtp_MessageContents_SignedPublicKeyBundle {
get {return _sender ?? Xmtp_MessageContents_SignedPublicKeyBundle()}
set {_sender = newValue}
}
/// Returns true if `sender` has been explicitly set.
public var hasSender: Bool {return self._sender != nil}
/// Clears the value of `sender`. Subsequent reads from it will return its default value.
public mutating func clearSender() {self._sender = nil}
public var recipient: Xmtp_MessageContents_SignedPublicKeyBundle {
get {return _recipient ?? Xmtp_MessageContents_SignedPublicKeyBundle()}
set {_recipient = newValue}
}
/// Returns true if `recipient` has been explicitly set.
public var hasRecipient: Bool {return self._recipient != nil}
/// Clears the value of `recipient`. Subsequent reads from it will return its default value.
public mutating func clearRecipient() {self._recipient = nil}
public var createdNs: UInt64 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _sender: Xmtp_MessageContents_SignedPublicKeyBundle? = nil
fileprivate var _recipient: Xmtp_MessageContents_SignedPublicKeyBundle? = nil
}
/// Sealed Invitation V1
/// Invitation encrypted with key material derived from the sender's and
/// recipient's public key bundles using simplified X3DH where
/// the sender's ephemeral key is replaced with sender's pre-key.
public struct Xmtp_MessageContents_SealedInvitationV1 {
// 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.
/// encoded SealedInvitationHeaderV1 used as associated data for Ciphertext
public var headerBytes: Data = Data()
/// Ciphertext.payload MUST contain encrypted InvitationV1.
public var ciphertext: Xmtp_MessageContents_Ciphertext {
get {return _ciphertext ?? Xmtp_MessageContents_Ciphertext()}
set {_ciphertext = newValue}
}
/// Returns true if `ciphertext` has been explicitly set.
public var hasCiphertext: Bool {return self._ciphertext != nil}
/// Clears the value of `ciphertext`. Subsequent reads from it will return its default value.
public mutating func clearCiphertext() {self._ciphertext = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _ciphertext: Xmtp_MessageContents_Ciphertext? = nil
}
/// Versioned Sealed Invitation
public struct Xmtp_MessageContents_SealedInvitation {
// 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 version: Xmtp_MessageContents_SealedInvitation.OneOf_Version? = nil
public var v1: Xmtp_MessageContents_SealedInvitationV1 {
get {
if case .v1(let v)? = version {return v}
return Xmtp_MessageContents_SealedInvitationV1()
}
set {version = .v1(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public enum OneOf_Version: Equatable {
case v1(Xmtp_MessageContents_SealedInvitationV1)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_SealedInvitation.OneOf_Version, rhs: Xmtp_MessageContents_SealedInvitation.OneOf_Version) -> Bool {
// 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 (lhs, rhs) {
case (.v1, .v1): return {
guard case .v1(let l) = lhs, case .v1(let r) = rhs else { preconditionFailure() }
return l == r
}()
}
}
#endif
}
public init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageContents_InvitationV1: @unchecked Sendable {}
extension Xmtp_MessageContents_InvitationV1.OneOf_Encryption: @unchecked Sendable {}
extension Xmtp_MessageContents_InvitationV1.Aes256gcmHkdfsha256: @unchecked Sendable {}
extension Xmtp_MessageContents_InvitationV1.Context: @unchecked Sendable {}
extension Xmtp_MessageContents_SealedInvitationHeaderV1: @unchecked Sendable {}
extension Xmtp_MessageContents_SealedInvitationV1: @unchecked Sendable {}
extension Xmtp_MessageContents_SealedInvitation: @unchecked Sendable {}
extension Xmtp_MessageContents_SealedInvitation.OneOf_Version: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_contents"
extension Xmtp_MessageContents_InvitationV1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".InvitationV1"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "topic"),
2: .same(proto: "context"),
3: .standard(proto: "aes256_gcm_hkdf_sha256"),
]
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.decodeSingularStringField(value: &self.topic) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._context) }()
case 3: try {
var v: Xmtp_MessageContents_InvitationV1.Aes256gcmHkdfsha256?
var hadOneofValue = false
if let current = self.encryption {
hadOneofValue = true
if case .aes256GcmHkdfSha256(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.encryption = .aes256GcmHkdfSha256(v)
}
}()
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
if !self.topic.isEmpty {
try visitor.visitSingularStringField(value: self.topic, fieldNumber: 1)
}
try { if let v = self._context {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try { if case .aes256GcmHkdfSha256(let v)? = self.encryption {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_InvitationV1, rhs: Xmtp_MessageContents_InvitationV1) -> Bool {
if lhs.topic != rhs.topic {return false}
if lhs._context != rhs._context {return false}
if lhs.encryption != rhs.encryption {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_InvitationV1.Aes256gcmHkdfsha256: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_InvitationV1.protoMessageName + ".Aes256gcmHkdfsha256"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "key_material"),
]
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.decodeSingularBytesField(value: &self.keyMaterial) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.keyMaterial.isEmpty {
try visitor.visitSingularBytesField(value: self.keyMaterial, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_InvitationV1.Aes256gcmHkdfsha256, rhs: Xmtp_MessageContents_InvitationV1.Aes256gcmHkdfsha256) -> Bool {
if lhs.keyMaterial != rhs.keyMaterial {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_InvitationV1.Context: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_InvitationV1.protoMessageName + ".Context"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "conversation_id"),
2: .same(proto: "metadata"),
]
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.decodeSingularStringField(value: &self.conversationID) }()
case 2: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMap<SwiftProtobuf.ProtobufString,SwiftProtobuf.ProtobufString>.self, value: &self.metadata) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.conversationID.isEmpty {
try visitor.visitSingularStringField(value: self.conversationID, fieldNumber: 1)
}
if !self.metadata.isEmpty {
try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMap<SwiftProtobuf.ProtobufString,SwiftProtobuf.ProtobufString>.self, value: self.metadata, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_InvitationV1.Context, rhs: Xmtp_MessageContents_InvitationV1.Context) -> Bool {
if lhs.conversationID != rhs.conversationID {return false}
if lhs.metadata != rhs.metadata {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_SealedInvitationHeaderV1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SealedInvitationHeaderV1"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "sender"),
2: .same(proto: "recipient"),
3: .standard(proto: "created_ns"),
]
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._sender) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._recipient) }()
case 3: try { try decoder.decodeSingularUInt64Field(value: &self.createdNs) }()
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._sender {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try { if let v = self._recipient {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
if self.createdNs != 0 {
try visitor.visitSingularUInt64Field(value: self.createdNs, fieldNumber: 3)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_SealedInvitationHeaderV1, rhs: Xmtp_MessageContents_SealedInvitationHeaderV1) -> Bool {
if lhs._sender != rhs._sender {return false}
if lhs._recipient != rhs._recipient {return false}
if lhs.createdNs != rhs.createdNs {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_SealedInvitationV1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SealedInvitationV1"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "header_bytes"),
2: .same(proto: "ciphertext"),
]
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.decodeSingularBytesField(value: &self.headerBytes) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._ciphertext) }()
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
if !self.headerBytes.isEmpty {
try visitor.visitSingularBytesField(value: self.headerBytes, fieldNumber: 1)
}
try { if let v = self._ciphertext {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_SealedInvitationV1, rhs: Xmtp_MessageContents_SealedInvitationV1) -> Bool {
if lhs.headerBytes != rhs.headerBytes {return false}
if lhs._ciphertext != rhs._ciphertext {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_SealedInvitation: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SealedInvitation"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "v1"),
]
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 {
var v: Xmtp_MessageContents_SealedInvitationV1?
var hadOneofValue = false
if let current = self.version {
hadOneofValue = true
if case .v1(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.version = .v1(v)
}
}()
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 case .v1(let v)? = self.version {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_SealedInvitation, rhs: Xmtp_MessageContents_SealedInvitation) -> Bool {
if lhs.version != rhs.version {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,600 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_contents/message.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Messages used for transport and storage of user conversations.
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// Message header is encoded separately as the bytes are also used
/// as associated data for authenticated encryption
public struct Xmtp_MessageContents_MessageHeaderV1 {
// 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 sender: Xmtp_MessageContents_PublicKeyBundle {
get {return _storage._sender ?? Xmtp_MessageContents_PublicKeyBundle()}
set {_uniqueStorage()._sender = newValue}
}
/// Returns true if `sender` has been explicitly set.
public var hasSender: Bool {return _storage._sender != nil}
/// Clears the value of `sender`. Subsequent reads from it will return its default value.
public mutating func clearSender() {_uniqueStorage()._sender = nil}
public var recipient: Xmtp_MessageContents_PublicKeyBundle {
get {return _storage._recipient ?? Xmtp_MessageContents_PublicKeyBundle()}
set {_uniqueStorage()._recipient = newValue}
}
/// Returns true if `recipient` has been explicitly set.
public var hasRecipient: Bool {return _storage._recipient != nil}
/// Clears the value of `recipient`. Subsequent reads from it will return its default value.
public mutating func clearRecipient() {_uniqueStorage()._recipient = nil}
public var timestamp: UInt64 {
get {return _storage._timestamp}
set {_uniqueStorage()._timestamp = newValue}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _storage = _StorageClass.defaultInstance
}
/// Message is the top level protocol element
public struct Xmtp_MessageContents_MessageV1 {
// 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.
/// encapsulates encoded MessageHeaderV1
public var headerBytes: Data = Data()
/// Ciphertext.payload MUST contain encrypted EncodedContent
public var ciphertext: Xmtp_MessageContents_Ciphertext {
get {return _ciphertext ?? Xmtp_MessageContents_Ciphertext()}
set {_ciphertext = newValue}
}
/// Returns true if `ciphertext` has been explicitly set.
public var hasCiphertext: Bool {return self._ciphertext != nil}
/// Clears the value of `ciphertext`. Subsequent reads from it will return its default value.
public mutating func clearCiphertext() {self._ciphertext = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _ciphertext: Xmtp_MessageContents_Ciphertext? = nil
}
/// Message header carries information that is not encrypted, and is therefore
/// observable by the network. It is however authenticated as associated data
/// of the AEAD encryption used to protect the message,
/// thus providing tamper evidence.
public struct Xmtp_MessageContents_MessageHeaderV2 {
// 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.
/// sender specified message creation time
public var createdNs: UInt64 = 0
/// the topic the message belongs to
public var topic: String = String()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// Message combines the encoded header with the encrypted payload.
public struct Xmtp_MessageContents_MessageV2 {
// 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.
/// encapsulates encoded MessageHeaderV2
public var headerBytes: Data = Data()
/// Ciphertext.payload MUST contain encrypted SignedContent
public var ciphertext: Xmtp_MessageContents_Ciphertext {
get {return _ciphertext ?? Xmtp_MessageContents_Ciphertext()}
set {_ciphertext = newValue}
}
/// Returns true if `ciphertext` has been explicitly set.
public var hasCiphertext: Bool {return self._ciphertext != nil}
/// Clears the value of `ciphertext`. Subsequent reads from it will return its default value.
public mutating func clearCiphertext() {self._ciphertext = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _ciphertext: Xmtp_MessageContents_Ciphertext? = nil
}
/// Versioned Message
public struct Xmtp_MessageContents_Message {
// 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 version: Xmtp_MessageContents_Message.OneOf_Version? = nil
public var v1: Xmtp_MessageContents_MessageV1 {
get {
if case .v1(let v)? = version {return v}
return Xmtp_MessageContents_MessageV1()
}
set {version = .v1(newValue)}
}
public var v2: Xmtp_MessageContents_MessageV2 {
get {
if case .v2(let v)? = version {return v}
return Xmtp_MessageContents_MessageV2()
}
set {version = .v2(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public enum OneOf_Version: Equatable {
case v1(Xmtp_MessageContents_MessageV1)
case v2(Xmtp_MessageContents_MessageV2)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_Message.OneOf_Version, rhs: Xmtp_MessageContents_Message.OneOf_Version) -> Bool {
// 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 (lhs, rhs) {
case (.v1, .v1): return {
guard case .v1(let l) = lhs, case .v1(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.v2, .v2): return {
guard case .v2(let l) = lhs, case .v2(let r) = rhs else { preconditionFailure() }
return l == r
}()
default: return false
}
}
#endif
}
public init() {}
}
/// DecodedMessage represents the decrypted message contents.
/// DecodedMessage instances are not stored on the network, but
/// may be serialized and stored by clients
public struct Xmtp_MessageContents_DecodedMessage {
// 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 id: String = String()
public var messageVersion: String = String()
public var senderAddress: String = String()
public var recipientAddress: String {
get {return _recipientAddress ?? String()}
set {_recipientAddress = newValue}
}
/// Returns true if `recipientAddress` has been explicitly set.
public var hasRecipientAddress: Bool {return self._recipientAddress != nil}
/// Clears the value of `recipientAddress`. Subsequent reads from it will return its default value.
public mutating func clearRecipientAddress() {self._recipientAddress = nil}
public var sentNs: UInt64 = 0
public var contentTopic: String = String()
public var conversation: Xmtp_MessageContents_ConversationReference {
get {return _conversation ?? Xmtp_MessageContents_ConversationReference()}
set {_conversation = newValue}
}
/// Returns true if `conversation` has been explicitly set.
public var hasConversation: Bool {return self._conversation != nil}
/// Clears the value of `conversation`. Subsequent reads from it will return its default value.
public mutating func clearConversation() {self._conversation = nil}
/// encapsulates EncodedContent
public var contentBytes: Data = Data()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _recipientAddress: String? = nil
fileprivate var _conversation: Xmtp_MessageContents_ConversationReference? = nil
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageContents_MessageHeaderV1: @unchecked Sendable {}
extension Xmtp_MessageContents_MessageV1: @unchecked Sendable {}
extension Xmtp_MessageContents_MessageHeaderV2: @unchecked Sendable {}
extension Xmtp_MessageContents_MessageV2: @unchecked Sendable {}
extension Xmtp_MessageContents_Message: @unchecked Sendable {}
extension Xmtp_MessageContents_Message.OneOf_Version: @unchecked Sendable {}
extension Xmtp_MessageContents_DecodedMessage: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_contents"
extension Xmtp_MessageContents_MessageHeaderV1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".MessageHeaderV1"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "sender"),
2: .same(proto: "recipient"),
3: .same(proto: "timestamp"),
]
fileprivate class _StorageClass {
var _sender: Xmtp_MessageContents_PublicKeyBundle? = nil
var _recipient: Xmtp_MessageContents_PublicKeyBundle? = nil
var _timestamp: UInt64 = 0
static let defaultInstance = _StorageClass()
private init() {}
init(copying source: _StorageClass) {
_sender = source._sender
_recipient = source._recipient
_timestamp = source._timestamp
}
}
fileprivate mutating func _uniqueStorage() -> _StorageClass {
if !isKnownUniquelyReferenced(&_storage) {
_storage = _StorageClass(copying: _storage)
}
return _storage
}
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
_ = _uniqueStorage()
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
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: &_storage._sender) }()
case 2: try { try decoder.decodeSingularMessageField(value: &_storage._recipient) }()
case 3: try { try decoder.decodeSingularUInt64Field(value: &_storage._timestamp) }()
default: break
}
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
// 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 = _storage._sender {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try { if let v = _storage._recipient {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
if _storage._timestamp != 0 {
try visitor.visitSingularUInt64Field(value: _storage._timestamp, fieldNumber: 3)
}
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_MessageHeaderV1, rhs: Xmtp_MessageContents_MessageHeaderV1) -> Bool {
if lhs._storage !== rhs._storage {
let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
let _storage = _args.0
let rhs_storage = _args.1
if _storage._sender != rhs_storage._sender {return false}
if _storage._recipient != rhs_storage._recipient {return false}
if _storage._timestamp != rhs_storage._timestamp {return false}
return true
}
if !storagesAreEqual {return false}
}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_MessageV1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".MessageV1"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "header_bytes"),
2: .same(proto: "ciphertext"),
]
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.decodeSingularBytesField(value: &self.headerBytes) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._ciphertext) }()
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
if !self.headerBytes.isEmpty {
try visitor.visitSingularBytesField(value: self.headerBytes, fieldNumber: 1)
}
try { if let v = self._ciphertext {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_MessageV1, rhs: Xmtp_MessageContents_MessageV1) -> Bool {
if lhs.headerBytes != rhs.headerBytes {return false}
if lhs._ciphertext != rhs._ciphertext {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_MessageHeaderV2: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".MessageHeaderV2"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "created_ns"),
2: .same(proto: "topic"),
]
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.decodeSingularUInt64Field(value: &self.createdNs) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.topic) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.createdNs != 0 {
try visitor.visitSingularUInt64Field(value: self.createdNs, fieldNumber: 1)
}
if !self.topic.isEmpty {
try visitor.visitSingularStringField(value: self.topic, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_MessageHeaderV2, rhs: Xmtp_MessageContents_MessageHeaderV2) -> Bool {
if lhs.createdNs != rhs.createdNs {return false}
if lhs.topic != rhs.topic {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_MessageV2: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".MessageV2"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "header_bytes"),
2: .same(proto: "ciphertext"),
]
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.decodeSingularBytesField(value: &self.headerBytes) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._ciphertext) }()
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
if !self.headerBytes.isEmpty {
try visitor.visitSingularBytesField(value: self.headerBytes, fieldNumber: 1)
}
try { if let v = self._ciphertext {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_MessageV2, rhs: Xmtp_MessageContents_MessageV2) -> Bool {
if lhs.headerBytes != rhs.headerBytes {return false}
if lhs._ciphertext != rhs._ciphertext {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_Message: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Message"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "v1"),
2: .same(proto: "v2"),
]
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 {
var v: Xmtp_MessageContents_MessageV1?
var hadOneofValue = false
if let current = self.version {
hadOneofValue = true
if case .v1(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.version = .v1(v)
}
}()
case 2: try {
var v: Xmtp_MessageContents_MessageV2?
var hadOneofValue = false
if let current = self.version {
hadOneofValue = true
if case .v2(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.version = .v2(v)
}
}()
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
switch self.version {
case .v1?: try {
guard case .v1(let v)? = self.version else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
}()
case .v2?: try {
guard case .v2(let v)? = self.version else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
}()
case nil: break
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_Message, rhs: Xmtp_MessageContents_Message) -> Bool {
if lhs.version != rhs.version {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_DecodedMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".DecodedMessage"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "id"),
2: .standard(proto: "message_version"),
3: .standard(proto: "sender_address"),
4: .standard(proto: "recipient_address"),
5: .standard(proto: "sent_ns"),
6: .standard(proto: "content_topic"),
7: .same(proto: "conversation"),
8: .standard(proto: "content_bytes"),
]
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.decodeSingularStringField(value: &self.id) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.messageVersion) }()
case 3: try { try decoder.decodeSingularStringField(value: &self.senderAddress) }()
case 4: try { try decoder.decodeSingularStringField(value: &self._recipientAddress) }()
case 5: try { try decoder.decodeSingularUInt64Field(value: &self.sentNs) }()
case 6: try { try decoder.decodeSingularStringField(value: &self.contentTopic) }()
case 7: try { try decoder.decodeSingularMessageField(value: &self._conversation) }()
case 8: try { try decoder.decodeSingularBytesField(value: &self.contentBytes) }()
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
if !self.id.isEmpty {
try visitor.visitSingularStringField(value: self.id, fieldNumber: 1)
}
if !self.messageVersion.isEmpty {
try visitor.visitSingularStringField(value: self.messageVersion, fieldNumber: 2)
}
if !self.senderAddress.isEmpty {
try visitor.visitSingularStringField(value: self.senderAddress, fieldNumber: 3)
}
try { if let v = self._recipientAddress {
try visitor.visitSingularStringField(value: v, fieldNumber: 4)
} }()
if self.sentNs != 0 {
try visitor.visitSingularUInt64Field(value: self.sentNs, fieldNumber: 5)
}
if !self.contentTopic.isEmpty {
try visitor.visitSingularStringField(value: self.contentTopic, fieldNumber: 6)
}
try { if let v = self._conversation {
try visitor.visitSingularMessageField(value: v, fieldNumber: 7)
} }()
if !self.contentBytes.isEmpty {
try visitor.visitSingularBytesField(value: self.contentBytes, fieldNumber: 8)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_DecodedMessage, rhs: Xmtp_MessageContents_DecodedMessage) -> Bool {
if lhs.id != rhs.id {return false}
if lhs.messageVersion != rhs.messageVersion {return false}
if lhs.senderAddress != rhs.senderAddress {return false}
if lhs._recipientAddress != rhs._recipientAddress {return false}
if lhs.sentNs != rhs.sentNs {return false}
if lhs.contentTopic != rhs.contentTopic {return false}
if lhs._conversation != rhs._conversation {return false}
if lhs.contentBytes != rhs.contentBytes {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,787 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_contents/private_key.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Private Key Storage
///
/// Following definitions are not used in the protocol, instead
/// they provide a way for encoding private keys for storage.
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// PrivateKey generalized to support different key types
public struct Xmtp_MessageContents_SignedPrivateKey {
// 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.
/// time the key was created
public var createdNs: UInt64 = 0
/// private key
public var union: Xmtp_MessageContents_SignedPrivateKey.OneOf_Union? = nil
public var secp256K1: Xmtp_MessageContents_SignedPrivateKey.Secp256k1 {
get {
if case .secp256K1(let v)? = union {return v}
return Xmtp_MessageContents_SignedPrivateKey.Secp256k1()
}
set {union = .secp256K1(newValue)}
}
/// public key for this private key
public var publicKey: Xmtp_MessageContents_SignedPublicKey {
get {return _publicKey ?? Xmtp_MessageContents_SignedPublicKey()}
set {_publicKey = newValue}
}
/// Returns true if `publicKey` has been explicitly set.
public var hasPublicKey: Bool {return self._publicKey != nil}
/// Clears the value of `publicKey`. Subsequent reads from it will return its default value.
public mutating func clearPublicKey() {self._publicKey = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
/// private key
public enum OneOf_Union: Equatable {
case secp256K1(Xmtp_MessageContents_SignedPrivateKey.Secp256k1)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_SignedPrivateKey.OneOf_Union, rhs: Xmtp_MessageContents_SignedPrivateKey.OneOf_Union) -> Bool {
// 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 (lhs, rhs) {
case (.secp256K1, .secp256K1): return {
guard case .secp256K1(let l) = lhs, case .secp256K1(let r) = rhs else { preconditionFailure() }
return l == r
}()
}
}
#endif
}
/// EC: SECP256k1
public struct Secp256k1 {
// 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.
/// D big-endian, 32 bytes
public var bytes: Data = Data()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public init() {}
fileprivate var _publicKey: Xmtp_MessageContents_SignedPublicKey? = nil
}
/// PrivateKeyBundle wraps the identityKey and the preKeys,
/// enforces usage of signed keys.
public struct Xmtp_MessageContents_PrivateKeyBundleV2 {
// 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 identityKey: Xmtp_MessageContents_SignedPrivateKey {
get {return _identityKey ?? Xmtp_MessageContents_SignedPrivateKey()}
set {_identityKey = newValue}
}
/// Returns true if `identityKey` has been explicitly set.
public var hasIdentityKey: Bool {return self._identityKey != nil}
/// Clears the value of `identityKey`. Subsequent reads from it will return its default value.
public mutating func clearIdentityKey() {self._identityKey = nil}
/// all the known pre-keys, newer keys first,
public var preKeys: [Xmtp_MessageContents_SignedPrivateKey] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _identityKey: Xmtp_MessageContents_SignedPrivateKey? = nil
}
/// LEGACY: PrivateKey generalized to support different key types
public struct Xmtp_MessageContents_PrivateKey {
// 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.
/// time the key was created
public var timestamp: UInt64 = 0
/// private key
public var union: Xmtp_MessageContents_PrivateKey.OneOf_Union? = nil
public var secp256K1: Xmtp_MessageContents_PrivateKey.Secp256k1 {
get {
if case .secp256K1(let v)? = union {return v}
return Xmtp_MessageContents_PrivateKey.Secp256k1()
}
set {union = .secp256K1(newValue)}
}
/// public key for this private key
public var publicKey: Xmtp_MessageContents_PublicKey {
get {return _publicKey ?? Xmtp_MessageContents_PublicKey()}
set {_publicKey = newValue}
}
/// Returns true if `publicKey` has been explicitly set.
public var hasPublicKey: Bool {return self._publicKey != nil}
/// Clears the value of `publicKey`. Subsequent reads from it will return its default value.
public mutating func clearPublicKey() {self._publicKey = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
/// private key
public enum OneOf_Union: Equatable {
case secp256K1(Xmtp_MessageContents_PrivateKey.Secp256k1)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_PrivateKey.OneOf_Union, rhs: Xmtp_MessageContents_PrivateKey.OneOf_Union) -> Bool {
// 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 (lhs, rhs) {
case (.secp256K1, .secp256K1): return {
guard case .secp256K1(let l) = lhs, case .secp256K1(let r) = rhs else { preconditionFailure() }
return l == r
}()
}
}
#endif
}
/// EC: SECP256k1
public struct Secp256k1 {
// 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.
/// D big-endian, 32 bytes
public var bytes: Data = Data()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public init() {}
fileprivate var _publicKey: Xmtp_MessageContents_PublicKey? = nil
}
/// LEGACY: PrivateKeyBundleV1 wraps the identityKey and the preKeys
public struct Xmtp_MessageContents_PrivateKeyBundleV1 {
// 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 identityKey: Xmtp_MessageContents_PrivateKey {
get {return _identityKey ?? Xmtp_MessageContents_PrivateKey()}
set {_identityKey = newValue}
}
/// Returns true if `identityKey` has been explicitly set.
public var hasIdentityKey: Bool {return self._identityKey != nil}
/// Clears the value of `identityKey`. Subsequent reads from it will return its default value.
public mutating func clearIdentityKey() {self._identityKey = nil}
/// all the known pre-keys, newer keys first,
public var preKeys: [Xmtp_MessageContents_PrivateKey] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _identityKey: Xmtp_MessageContents_PrivateKey? = nil
}
/// Versioned PrivateKeyBundle
public struct Xmtp_MessageContents_PrivateKeyBundle {
// 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 version: Xmtp_MessageContents_PrivateKeyBundle.OneOf_Version? = nil
public var v1: Xmtp_MessageContents_PrivateKeyBundleV1 {
get {
if case .v1(let v)? = version {return v}
return Xmtp_MessageContents_PrivateKeyBundleV1()
}
set {version = .v1(newValue)}
}
public var v2: Xmtp_MessageContents_PrivateKeyBundleV2 {
get {
if case .v2(let v)? = version {return v}
return Xmtp_MessageContents_PrivateKeyBundleV2()
}
set {version = .v2(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public enum OneOf_Version: Equatable {
case v1(Xmtp_MessageContents_PrivateKeyBundleV1)
case v2(Xmtp_MessageContents_PrivateKeyBundleV2)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_PrivateKeyBundle.OneOf_Version, rhs: Xmtp_MessageContents_PrivateKeyBundle.OneOf_Version) -> Bool {
// 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 (lhs, rhs) {
case (.v1, .v1): return {
guard case .v1(let l) = lhs, case .v1(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.v2, .v2): return {
guard case .v2(let l) = lhs, case .v2(let r) = rhs else { preconditionFailure() }
return l == r
}()
default: return false
}
}
#endif
}
public init() {}
}
/// PrivateKeyBundle encrypted with key material generated by
/// signing a randomly generated "pre-key" with the user's wallet,
/// i.e. EIP-191 signature of a "storage signature" message with
/// the pre-key embedded in it.
/// (see xmtp-js::PrivateKeyBundle.toEncryptedBytes for details)
public struct Xmtp_MessageContents_EncryptedPrivateKeyBundleV1 {
// 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.
/// randomly generated pre-key
public var walletPreKey: Data = Data()
/// MUST contain encrypted PrivateKeyBundle
public var ciphertext: Xmtp_MessageContents_Ciphertext {
get {return _ciphertext ?? Xmtp_MessageContents_Ciphertext()}
set {_ciphertext = newValue}
}
/// Returns true if `ciphertext` has been explicitly set.
public var hasCiphertext: Bool {return self._ciphertext != nil}
/// Clears the value of `ciphertext`. Subsequent reads from it will return its default value.
public mutating func clearCiphertext() {self._ciphertext = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _ciphertext: Xmtp_MessageContents_Ciphertext? = nil
}
/// Versioned encrypted PrivateKeyBundle
public struct Xmtp_MessageContents_EncryptedPrivateKeyBundle {
// 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 version: Xmtp_MessageContents_EncryptedPrivateKeyBundle.OneOf_Version? = nil
public var v1: Xmtp_MessageContents_EncryptedPrivateKeyBundleV1 {
get {
if case .v1(let v)? = version {return v}
return Xmtp_MessageContents_EncryptedPrivateKeyBundleV1()
}
set {version = .v1(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public enum OneOf_Version: Equatable {
case v1(Xmtp_MessageContents_EncryptedPrivateKeyBundleV1)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_EncryptedPrivateKeyBundle.OneOf_Version, rhs: Xmtp_MessageContents_EncryptedPrivateKeyBundle.OneOf_Version) -> Bool {
// 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 (lhs, rhs) {
case (.v1, .v1): return {
guard case .v1(let l) = lhs, case .v1(let r) = rhs else { preconditionFailure() }
return l == r
}()
}
}
#endif
}
public init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageContents_SignedPrivateKey: @unchecked Sendable {}
extension Xmtp_MessageContents_SignedPrivateKey.OneOf_Union: @unchecked Sendable {}
extension Xmtp_MessageContents_SignedPrivateKey.Secp256k1: @unchecked Sendable {}
extension Xmtp_MessageContents_PrivateKeyBundleV2: @unchecked Sendable {}
extension Xmtp_MessageContents_PrivateKey: @unchecked Sendable {}
extension Xmtp_MessageContents_PrivateKey.OneOf_Union: @unchecked Sendable {}
extension Xmtp_MessageContents_PrivateKey.Secp256k1: @unchecked Sendable {}
extension Xmtp_MessageContents_PrivateKeyBundleV1: @unchecked Sendable {}
extension Xmtp_MessageContents_PrivateKeyBundle: @unchecked Sendable {}
extension Xmtp_MessageContents_PrivateKeyBundle.OneOf_Version: @unchecked Sendable {}
extension Xmtp_MessageContents_EncryptedPrivateKeyBundleV1: @unchecked Sendable {}
extension Xmtp_MessageContents_EncryptedPrivateKeyBundle: @unchecked Sendable {}
extension Xmtp_MessageContents_EncryptedPrivateKeyBundle.OneOf_Version: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_contents"
extension Xmtp_MessageContents_SignedPrivateKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SignedPrivateKey"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "created_ns"),
2: .same(proto: "secp256k1"),
3: .standard(proto: "public_key"),
]
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.decodeSingularUInt64Field(value: &self.createdNs) }()
case 2: try {
var v: Xmtp_MessageContents_SignedPrivateKey.Secp256k1?
var hadOneofValue = false
if let current = self.union {
hadOneofValue = true
if case .secp256K1(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.union = .secp256K1(v)
}
}()
case 3: try { try decoder.decodeSingularMessageField(value: &self._publicKey) }()
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
if self.createdNs != 0 {
try visitor.visitSingularUInt64Field(value: self.createdNs, fieldNumber: 1)
}
try { if case .secp256K1(let v)? = self.union {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try { if let v = self._publicKey {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_SignedPrivateKey, rhs: Xmtp_MessageContents_SignedPrivateKey) -> Bool {
if lhs.createdNs != rhs.createdNs {return false}
if lhs.union != rhs.union {return false}
if lhs._publicKey != rhs._publicKey {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_SignedPrivateKey.Secp256k1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_SignedPrivateKey.protoMessageName + ".Secp256k1"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "bytes"),
]
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.decodeSingularBytesField(value: &self.bytes) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.bytes.isEmpty {
try visitor.visitSingularBytesField(value: self.bytes, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_SignedPrivateKey.Secp256k1, rhs: Xmtp_MessageContents_SignedPrivateKey.Secp256k1) -> Bool {
if lhs.bytes != rhs.bytes {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_PrivateKeyBundleV2: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".PrivateKeyBundleV2"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "identity_key"),
2: .standard(proto: "pre_keys"),
]
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._identityKey) }()
case 2: try { try decoder.decodeRepeatedMessageField(value: &self.preKeys) }()
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._identityKey {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
if !self.preKeys.isEmpty {
try visitor.visitRepeatedMessageField(value: self.preKeys, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_PrivateKeyBundleV2, rhs: Xmtp_MessageContents_PrivateKeyBundleV2) -> Bool {
if lhs._identityKey != rhs._identityKey {return false}
if lhs.preKeys != rhs.preKeys {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_PrivateKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".PrivateKey"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "timestamp"),
2: .same(proto: "secp256k1"),
3: .standard(proto: "public_key"),
]
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.decodeSingularUInt64Field(value: &self.timestamp) }()
case 2: try {
var v: Xmtp_MessageContents_PrivateKey.Secp256k1?
var hadOneofValue = false
if let current = self.union {
hadOneofValue = true
if case .secp256K1(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.union = .secp256K1(v)
}
}()
case 3: try { try decoder.decodeSingularMessageField(value: &self._publicKey) }()
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
if self.timestamp != 0 {
try visitor.visitSingularUInt64Field(value: self.timestamp, fieldNumber: 1)
}
try { if case .secp256K1(let v)? = self.union {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try { if let v = self._publicKey {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_PrivateKey, rhs: Xmtp_MessageContents_PrivateKey) -> Bool {
if lhs.timestamp != rhs.timestamp {return false}
if lhs.union != rhs.union {return false}
if lhs._publicKey != rhs._publicKey {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_PrivateKey.Secp256k1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_PrivateKey.protoMessageName + ".Secp256k1"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "bytes"),
]
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.decodeSingularBytesField(value: &self.bytes) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.bytes.isEmpty {
try visitor.visitSingularBytesField(value: self.bytes, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_PrivateKey.Secp256k1, rhs: Xmtp_MessageContents_PrivateKey.Secp256k1) -> Bool {
if lhs.bytes != rhs.bytes {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_PrivateKeyBundleV1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".PrivateKeyBundleV1"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "identity_key"),
2: .standard(proto: "pre_keys"),
]
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._identityKey) }()
case 2: try { try decoder.decodeRepeatedMessageField(value: &self.preKeys) }()
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._identityKey {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
if !self.preKeys.isEmpty {
try visitor.visitRepeatedMessageField(value: self.preKeys, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_PrivateKeyBundleV1, rhs: Xmtp_MessageContents_PrivateKeyBundleV1) -> Bool {
if lhs._identityKey != rhs._identityKey {return false}
if lhs.preKeys != rhs.preKeys {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_PrivateKeyBundle: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".PrivateKeyBundle"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "v1"),
2: .same(proto: "v2"),
]
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 {
var v: Xmtp_MessageContents_PrivateKeyBundleV1?
var hadOneofValue = false
if let current = self.version {
hadOneofValue = true
if case .v1(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.version = .v1(v)
}
}()
case 2: try {
var v: Xmtp_MessageContents_PrivateKeyBundleV2?
var hadOneofValue = false
if let current = self.version {
hadOneofValue = true
if case .v2(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.version = .v2(v)
}
}()
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
switch self.version {
case .v1?: try {
guard case .v1(let v)? = self.version else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
}()
case .v2?: try {
guard case .v2(let v)? = self.version else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
}()
case nil: break
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_PrivateKeyBundle, rhs: Xmtp_MessageContents_PrivateKeyBundle) -> Bool {
if lhs.version != rhs.version {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_EncryptedPrivateKeyBundleV1: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".EncryptedPrivateKeyBundleV1"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "wallet_pre_key"),
2: .same(proto: "ciphertext"),
]
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.decodeSingularBytesField(value: &self.walletPreKey) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._ciphertext) }()
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
if !self.walletPreKey.isEmpty {
try visitor.visitSingularBytesField(value: self.walletPreKey, fieldNumber: 1)
}
try { if let v = self._ciphertext {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_EncryptedPrivateKeyBundleV1, rhs: Xmtp_MessageContents_EncryptedPrivateKeyBundleV1) -> Bool {
if lhs.walletPreKey != rhs.walletPreKey {return false}
if lhs._ciphertext != rhs._ciphertext {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_EncryptedPrivateKeyBundle: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".EncryptedPrivateKeyBundle"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "v1"),
]
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 {
var v: Xmtp_MessageContents_EncryptedPrivateKeyBundleV1?
var hadOneofValue = false
if let current = self.version {
hadOneofValue = true
if case .v1(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.version = .v1(v)
}
}()
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 case .v1(let v)? = self.version {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_EncryptedPrivateKeyBundle, rhs: Xmtp_MessageContents_EncryptedPrivateKeyBundle) -> Bool {
if lhs.version != rhs.version {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,562 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_contents/public_key.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Structure for representing public keys of different types,
/// including signatures used to authenticate the keys.
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// UnsignedPublicKey represents a generalized public key,
/// defined as a union to support cryptographic algorithm agility.
public struct Xmtp_MessageContents_UnsignedPublicKey {
// 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 createdNs: UInt64 = 0
public var union: Xmtp_MessageContents_UnsignedPublicKey.OneOf_Union? = nil
public var secp256K1Uncompressed: Xmtp_MessageContents_UnsignedPublicKey.Secp256k1Uncompressed {
get {
if case .secp256K1Uncompressed(let v)? = union {return v}
return Xmtp_MessageContents_UnsignedPublicKey.Secp256k1Uncompressed()
}
set {union = .secp256K1Uncompressed(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public enum OneOf_Union: Equatable {
case secp256K1Uncompressed(Xmtp_MessageContents_UnsignedPublicKey.Secp256k1Uncompressed)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_UnsignedPublicKey.OneOf_Union, rhs: Xmtp_MessageContents_UnsignedPublicKey.OneOf_Union) -> Bool {
// 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 (lhs, rhs) {
case (.secp256K1Uncompressed, .secp256K1Uncompressed): return {
guard case .secp256K1Uncompressed(let l) = lhs, case .secp256K1Uncompressed(let r) = rhs else { preconditionFailure() }
return l == r
}()
}
}
#endif
}
/// EC: SECP256k1
public struct Secp256k1Uncompressed {
// 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.
/// uncompressed point with prefix (0x04) [ P || X || Y ], 65 bytes
public var bytes: Data = Data()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public init() {}
}
/// SignedPublicKey
public struct Xmtp_MessageContents_SignedPublicKey {
// 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.
/// embeds an UnsignedPublicKey
public var keyBytes: Data = Data()
/// signs key_bytes
public var signature: Xmtp_MessageContents_Signature {
get {return _signature ?? Xmtp_MessageContents_Signature()}
set {_signature = newValue}
}
/// Returns true if `signature` has been explicitly set.
public var hasSignature: Bool {return self._signature != nil}
/// Clears the value of `signature`. Subsequent reads from it will return its default value.
public mutating func clearSignature() {self._signature = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _signature: Xmtp_MessageContents_Signature? = nil
}
/// PublicKeyBundle packages the cryptographic keys associated with a wallet.
public struct Xmtp_MessageContents_SignedPublicKeyBundle {
// 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.
/// Identity key MUST be signed by the wallet.
public var identityKey: Xmtp_MessageContents_SignedPublicKey {
get {return _identityKey ?? Xmtp_MessageContents_SignedPublicKey()}
set {_identityKey = newValue}
}
/// Returns true if `identityKey` has been explicitly set.
public var hasIdentityKey: Bool {return self._identityKey != nil}
/// Clears the value of `identityKey`. Subsequent reads from it will return its default value.
public mutating func clearIdentityKey() {self._identityKey = nil}
/// Pre-key MUST be signed by the identity key.
public var preKey: Xmtp_MessageContents_SignedPublicKey {
get {return _preKey ?? Xmtp_MessageContents_SignedPublicKey()}
set {_preKey = newValue}
}
/// Returns true if `preKey` has been explicitly set.
public var hasPreKey: Bool {return self._preKey != nil}
/// Clears the value of `preKey`. Subsequent reads from it will return its default value.
public mutating func clearPreKey() {self._preKey = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _identityKey: Xmtp_MessageContents_SignedPublicKey? = nil
fileprivate var _preKey: Xmtp_MessageContents_SignedPublicKey? = nil
}
/// PublicKey represents a generalized public key,
/// defined as a union to support cryptographic algorithm agility.
public struct Xmtp_MessageContents_PublicKey {
// 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 timestamp: UInt64 = 0
public var signature: Xmtp_MessageContents_Signature {
get {return _signature ?? Xmtp_MessageContents_Signature()}
set {_signature = newValue}
}
/// Returns true if `signature` has been explicitly set.
public var hasSignature: Bool {return self._signature != nil}
/// Clears the value of `signature`. Subsequent reads from it will return its default value.
public mutating func clearSignature() {self._signature = nil}
public var union: Xmtp_MessageContents_PublicKey.OneOf_Union? = nil
public var secp256K1Uncompressed: Xmtp_MessageContents_PublicKey.Secp256k1Uncompressed {
get {
if case .secp256K1Uncompressed(let v)? = union {return v}
return Xmtp_MessageContents_PublicKey.Secp256k1Uncompressed()
}
set {union = .secp256K1Uncompressed(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public enum OneOf_Union: Equatable {
case secp256K1Uncompressed(Xmtp_MessageContents_PublicKey.Secp256k1Uncompressed)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_PublicKey.OneOf_Union, rhs: Xmtp_MessageContents_PublicKey.OneOf_Union) -> Bool {
// 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 (lhs, rhs) {
case (.secp256K1Uncompressed, .secp256K1Uncompressed): return {
guard case .secp256K1Uncompressed(let l) = lhs, case .secp256K1Uncompressed(let r) = rhs else { preconditionFailure() }
return l == r
}()
}
}
#endif
}
/// The key bytes
public struct Secp256k1Uncompressed {
// 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.
/// uncompressed point with prefix (0x04) [ P || X || Y ], 65 bytes
public var bytes: Data = Data()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public init() {}
fileprivate var _signature: Xmtp_MessageContents_Signature? = nil
}
/// PublicKeyBundle packages the cryptographic keys associated with a wallet,
/// both senders and recipients are identified by their key bundles.
public struct Xmtp_MessageContents_PublicKeyBundle {
// 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.
/// Identity key MUST be signed by the wallet.
public var identityKey: Xmtp_MessageContents_PublicKey {
get {return _identityKey ?? Xmtp_MessageContents_PublicKey()}
set {_identityKey = newValue}
}
/// Returns true if `identityKey` has been explicitly set.
public var hasIdentityKey: Bool {return self._identityKey != nil}
/// Clears the value of `identityKey`. Subsequent reads from it will return its default value.
public mutating func clearIdentityKey() {self._identityKey = nil}
/// Pre-key MUST be signed by the identity key.
public var preKey: Xmtp_MessageContents_PublicKey {
get {return _preKey ?? Xmtp_MessageContents_PublicKey()}
set {_preKey = newValue}
}
/// Returns true if `preKey` has been explicitly set.
public var hasPreKey: Bool {return self._preKey != nil}
/// Clears the value of `preKey`. Subsequent reads from it will return its default value.
public mutating func clearPreKey() {self._preKey = nil}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _identityKey: Xmtp_MessageContents_PublicKey? = nil
fileprivate var _preKey: Xmtp_MessageContents_PublicKey? = nil
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageContents_UnsignedPublicKey: @unchecked Sendable {}
extension Xmtp_MessageContents_UnsignedPublicKey.OneOf_Union: @unchecked Sendable {}
extension Xmtp_MessageContents_UnsignedPublicKey.Secp256k1Uncompressed: @unchecked Sendable {}
extension Xmtp_MessageContents_SignedPublicKey: @unchecked Sendable {}
extension Xmtp_MessageContents_SignedPublicKeyBundle: @unchecked Sendable {}
extension Xmtp_MessageContents_PublicKey: @unchecked Sendable {}
extension Xmtp_MessageContents_PublicKey.OneOf_Union: @unchecked Sendable {}
extension Xmtp_MessageContents_PublicKey.Secp256k1Uncompressed: @unchecked Sendable {}
extension Xmtp_MessageContents_PublicKeyBundle: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_contents"
extension Xmtp_MessageContents_UnsignedPublicKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".UnsignedPublicKey"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "created_ns"),
3: .standard(proto: "secp256k1_uncompressed"),
]
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.decodeSingularUInt64Field(value: &self.createdNs) }()
case 3: try {
var v: Xmtp_MessageContents_UnsignedPublicKey.Secp256k1Uncompressed?
var hadOneofValue = false
if let current = self.union {
hadOneofValue = true
if case .secp256K1Uncompressed(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.union = .secp256K1Uncompressed(v)
}
}()
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
if self.createdNs != 0 {
try visitor.visitSingularUInt64Field(value: self.createdNs, fieldNumber: 1)
}
try { if case .secp256K1Uncompressed(let v)? = self.union {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_UnsignedPublicKey, rhs: Xmtp_MessageContents_UnsignedPublicKey) -> Bool {
if lhs.createdNs != rhs.createdNs {return false}
if lhs.union != rhs.union {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_UnsignedPublicKey.Secp256k1Uncompressed: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_UnsignedPublicKey.protoMessageName + ".Secp256k1Uncompressed"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "bytes"),
]
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.decodeSingularBytesField(value: &self.bytes) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.bytes.isEmpty {
try visitor.visitSingularBytesField(value: self.bytes, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_UnsignedPublicKey.Secp256k1Uncompressed, rhs: Xmtp_MessageContents_UnsignedPublicKey.Secp256k1Uncompressed) -> Bool {
if lhs.bytes != rhs.bytes {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_SignedPublicKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SignedPublicKey"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "key_bytes"),
2: .same(proto: "signature"),
]
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.decodeSingularBytesField(value: &self.keyBytes) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._signature) }()
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
if !self.keyBytes.isEmpty {
try visitor.visitSingularBytesField(value: self.keyBytes, fieldNumber: 1)
}
try { if let v = self._signature {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_SignedPublicKey, rhs: Xmtp_MessageContents_SignedPublicKey) -> Bool {
if lhs.keyBytes != rhs.keyBytes {return false}
if lhs._signature != rhs._signature {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_SignedPublicKeyBundle: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SignedPublicKeyBundle"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "identity_key"),
2: .standard(proto: "pre_key"),
]
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._identityKey) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._preKey) }()
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._identityKey {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try { if let v = self._preKey {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_SignedPublicKeyBundle, rhs: Xmtp_MessageContents_SignedPublicKeyBundle) -> Bool {
if lhs._identityKey != rhs._identityKey {return false}
if lhs._preKey != rhs._preKey {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_PublicKey: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".PublicKey"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "timestamp"),
2: .same(proto: "signature"),
3: .standard(proto: "secp256k1_uncompressed"),
]
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.decodeSingularUInt64Field(value: &self.timestamp) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._signature) }()
case 3: try {
var v: Xmtp_MessageContents_PublicKey.Secp256k1Uncompressed?
var hadOneofValue = false
if let current = self.union {
hadOneofValue = true
if case .secp256K1Uncompressed(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.union = .secp256K1Uncompressed(v)
}
}()
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
if self.timestamp != 0 {
try visitor.visitSingularUInt64Field(value: self.timestamp, fieldNumber: 1)
}
try { if let v = self._signature {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try { if case .secp256K1Uncompressed(let v)? = self.union {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_PublicKey, rhs: Xmtp_MessageContents_PublicKey) -> Bool {
if lhs.timestamp != rhs.timestamp {return false}
if lhs._signature != rhs._signature {return false}
if lhs.union != rhs.union {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_PublicKey.Secp256k1Uncompressed: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_PublicKey.protoMessageName + ".Secp256k1Uncompressed"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "bytes"),
]
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.decodeSingularBytesField(value: &self.bytes) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.bytes.isEmpty {
try visitor.visitSingularBytesField(value: self.bytes, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_PublicKey.Secp256k1Uncompressed, rhs: Xmtp_MessageContents_PublicKey.Secp256k1Uncompressed) -> Bool {
if lhs.bytes != rhs.bytes {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_PublicKeyBundle: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".PublicKeyBundle"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "identity_key"),
2: .standard(proto: "pre_key"),
]
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._identityKey) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._preKey) }()
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._identityKey {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
} }()
try { if let v = self._preKey {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
} }()
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_PublicKeyBundle, rhs: Xmtp_MessageContents_PublicKeyBundle) -> Bool {
if lhs._identityKey != rhs._identityKey {return false}
if lhs._preKey != rhs._preKey {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,271 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: message_contents/signature.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
/// Signature is a generic structure for public key signatures.
import Foundation
import SwiftProtobuf
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// Signature represents a generalized public key signature,
/// defined as a union to support cryptographic algorithm agility.
public struct Xmtp_MessageContents_Signature {
// 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 union: Xmtp_MessageContents_Signature.OneOf_Union? = nil
public var ecdsaCompact: Xmtp_MessageContents_Signature.ECDSACompact {
get {
if case .ecdsaCompact(let v)? = union {return v}
return Xmtp_MessageContents_Signature.ECDSACompact()
}
set {union = .ecdsaCompact(newValue)}
}
public var walletEcdsaCompact: Xmtp_MessageContents_Signature.WalletECDSACompact {
get {
if case .walletEcdsaCompact(let v)? = union {return v}
return Xmtp_MessageContents_Signature.WalletECDSACompact()
}
set {union = .walletEcdsaCompact(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public enum OneOf_Union: Equatable {
case ecdsaCompact(Xmtp_MessageContents_Signature.ECDSACompact)
case walletEcdsaCompact(Xmtp_MessageContents_Signature.WalletECDSACompact)
#if !swift(>=4.1)
public static func ==(lhs: Xmtp_MessageContents_Signature.OneOf_Union, rhs: Xmtp_MessageContents_Signature.OneOf_Union) -> Bool {
// 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 (lhs, rhs) {
case (.ecdsaCompact, .ecdsaCompact): return {
guard case .ecdsaCompact(let l) = lhs, case .ecdsaCompact(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.walletEcdsaCompact, .walletEcdsaCompact): return {
guard case .walletEcdsaCompact(let l) = lhs, case .walletEcdsaCompact(let r) = rhs else { preconditionFailure() }
return l == r
}()
default: return false
}
}
#endif
}
/// ECDSA signature bytes and the recovery bit
public struct ECDSACompact {
// 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.
/// compact representation [ R || S ], 64 bytes
public var bytes: Data = Data()
/// recovery bit
public var recovery: UInt32 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// ECDSA signature bytes and the recovery bit
/// produced by xmtp-js::PublicKey.signWithWallet function, i.e.
/// EIP-191 signature of a "Create Identity" message with the key embedded.
/// Used to sign identity keys.
public struct WalletECDSACompact {
// 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.
/// compact representation [ R || S ], 64 bytes
public var bytes: Data = Data()
/// recovery bit
public var recovery: UInt32 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
public init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension Xmtp_MessageContents_Signature: @unchecked Sendable {}
extension Xmtp_MessageContents_Signature.OneOf_Union: @unchecked Sendable {}
extension Xmtp_MessageContents_Signature.ECDSACompact: @unchecked Sendable {}
extension Xmtp_MessageContents_Signature.WalletECDSACompact: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "xmtp.message_contents"
extension Xmtp_MessageContents_Signature: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Signature"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "ecdsa_compact"),
2: .standard(proto: "wallet_ecdsa_compact"),
]
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 {
var v: Xmtp_MessageContents_Signature.ECDSACompact?
var hadOneofValue = false
if let current = self.union {
hadOneofValue = true
if case .ecdsaCompact(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.union = .ecdsaCompact(v)
}
}()
case 2: try {
var v: Xmtp_MessageContents_Signature.WalletECDSACompact?
var hadOneofValue = false
if let current = self.union {
hadOneofValue = true
if case .walletEcdsaCompact(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
if hadOneofValue {try decoder.handleConflictingOneOf()}
self.union = .walletEcdsaCompact(v)
}
}()
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
switch self.union {
case .ecdsaCompact?: try {
guard case .ecdsaCompact(let v)? = self.union else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
}()
case .walletEcdsaCompact?: try {
guard case .walletEcdsaCompact(let v)? = self.union else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
}()
case nil: break
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_Signature, rhs: Xmtp_MessageContents_Signature) -> Bool {
if lhs.union != rhs.union {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_Signature.ECDSACompact: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_Signature.protoMessageName + ".ECDSACompact"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "bytes"),
2: .same(proto: "recovery"),
]
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.decodeSingularBytesField(value: &self.bytes) }()
case 2: try { try decoder.decodeSingularUInt32Field(value: &self.recovery) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.bytes.isEmpty {
try visitor.visitSingularBytesField(value: self.bytes, fieldNumber: 1)
}
if self.recovery != 0 {
try visitor.visitSingularUInt32Field(value: self.recovery, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_Signature.ECDSACompact, rhs: Xmtp_MessageContents_Signature.ECDSACompact) -> Bool {
if lhs.bytes != rhs.bytes {return false}
if lhs.recovery != rhs.recovery {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Xmtp_MessageContents_Signature.WalletECDSACompact: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = Xmtp_MessageContents_Signature.protoMessageName + ".WalletECDSACompact"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "bytes"),
2: .same(proto: "recovery"),
]
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.decodeSingularBytesField(value: &self.bytes) }()
case 2: try { try decoder.decodeSingularUInt32Field(value: &self.recovery) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.bytes.isEmpty {
try visitor.visitSingularBytesField(value: self.bytes, fieldNumber: 1)
}
if self.recovery != 0 {
try visitor.visitSingularUInt32Field(value: self.recovery, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Xmtp_MessageContents_Signature.WalletECDSACompact, rhs: Xmtp_MessageContents_Signature.WalletECDSACompact) -> Bool {
if lhs.bytes != rhs.bytes {return false}
if lhs.recovery != rhs.recovery {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -4,89 +4,117 @@
//
// Created by Pat Nakajima on 1/20/23.
//
#if canImport(UIKit)
import Connect
import UIKit
import UserNotifications
import Connect
import UIKit
import UserNotifications
enum XMTPPushError: Error {
case noPushServer
}
public struct XMTPPush {
public static var shared = XMTPPush()
var installationID: String
var installationIDKey: String = "installationID"
var pushServer: String = ""
private init() {
if let id = UserDefaults.standard.string(forKey: installationIDKey) {
installationID = id
} else {
installationID = UUID().uuidString
UserDefaults.standard.set(installationID, forKey: installationIDKey)
}
enum XMTPPushError: Error {
case noPushServer
}
public mutating func setPushServer(_ server: String) {
pushServer = server
}
public struct XMTPPush {
public static var shared = XMTPPush()
public func request() async throws -> Bool {
if pushServer == "" {
throw XMTPPushError.noPushServer
}
var installationID: String
var installationIDKey: String = "installationID"
if try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge]) {
await UIApplication.shared.registerForRemoteNotifications()
var pushServer: String = ""
return true
}
return false
}
public func register(token: String) async throws {
if pushServer == "" {
throw XMTPPushError.noPushServer
}
let request = Notifications_V1_RegisterInstallationRequest.with { request in
request.installationID = installationID
request.deliveryMechanism = Notifications_V1_DeliveryMechanism.with { delivery in
delivery.apnsDeviceToken = token
delivery.deliveryMechanismType = .apnsDeviceToken(token)
private init() {
if let id = UserDefaults.standard.string(forKey: installationIDKey) {
installationID = id
} else {
installationID = UUID().uuidString
UserDefaults.standard.set(installationID, forKey: installationIDKey)
}
}
_ = await client.registerInstallation(request: request)
}
public func subscribe(topics: [String]) async throws {
if pushServer == "" {
throw XMTPPushError.noPushServer
public mutating func setPushServer(_ server: String) {
pushServer = server
}
let request = Notifications_V1_SubscribeRequest.with { request in
request.installationID = installationID
request.topics = topics
public func request() async throws -> Bool {
if pushServer == "" {
throw XMTPPushError.noPushServer
}
if try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge]) {
// await UIApplication.shared.registerForRemoteNotifications()
return true
}
return false
}
_ = await client.subscribe(request: request)
}
public func register(token: String) async throws {
if pushServer == "" {
throw XMTPPushError.noPushServer
}
var client: Notifications_V1_NotificationsClient {
let protocolClient = ProtocolClient(
httpClient: URLSessionHTTPClient(),
config: ProtocolClientConfig(
host: pushServer,
networkProtocol: .connect,
codec: ProtoCodec()
let request = Notifications_V1_RegisterInstallationRequest.with { request in
request.installationID = installationID
request.deliveryMechanism = Notifications_V1_DeliveryMechanism.with { delivery in
delivery.apnsDeviceToken = token
delivery.deliveryMechanismType = .apnsDeviceToken(token)
}
}
_ = await client.registerInstallation(request: request)
}
public func subscribe(topics: [String]) async throws {
if pushServer == "" {
throw XMTPPushError.noPushServer
}
let request = Notifications_V1_SubscribeRequest.with { request in
request.installationID = installationID
request.topics = topics
}
_ = await client.subscribe(request: request)
}
var client: Notifications_V1_NotificationsClient {
let protocolClient = ProtocolClient(
httpClient: URLSessionHTTPClient(),
config: ProtocolClientConfig(
host: pushServer,
networkProtocol: .connect,
codec: ProtoCodec()
)
)
)
return Notifications_V1_NotificationsClient(client: protocolClient)
return Notifications_V1_NotificationsClient(client: protocolClient)
}
}
}
#else
public struct XMTPPush {
public static var shared = XMTPPush()
private init() {
fatalError("XMTPPush not available")
}
public mutating func setPushServer(_: String) {
fatalError("XMTPPush not available")
}
public func request() async throws -> Bool {
fatalError("XMTPPush not available")
}
public func register(token _: String) async throws {
fatalError("XMTPPush not available")
}
public func subscribe(topics _: [String]) async throws {
fatalError("XMTPPush not available")
}
var client: Notifications_V1_NotificationsClient {
fatalError("XMTPPush not available")
}
}
#endif

View File

@ -6,7 +6,8 @@
//
import Foundation
import secp256k1
import web3
import XMTPRust
/// Defines a type that is used by a ``Client`` to sign keys and messages.
///
@ -36,9 +37,9 @@ extension SigningKey {
let signatureText = Signature.createIdentityText(key: try slimKey.serializedData())
let signature = try await sign(message: signatureText)
let digest = try Signature.ethHash(signatureText)
let recoveredKey = try KeyUtil.recoverPublicKey(message: digest, signature: signature.rawData)
let address = KeyUtil.generateAddress(from: recoveredKey).toChecksumAddress()
let message = try Signature.ethPersonalMessage(signatureText)
let recoveredKey = try KeyUtilx.recoverPublicKeyKeccak256(from: signature.rawData, message: message)
let address = KeyUtilx.generateAddress(from: recoveredKey).toChecksumAddress()
var authorized = PublicKey()
authorized.secp256K1Uncompressed = slimKey.secp256K1Uncompressed

View File

@ -13,3 +13,11 @@ enum Util {
return data.web3.keccak256
}
}
extension Array {
func chunks(_ chunkSize: Int) -> [[Element]] {
return stride(from: 0, to: self.count, by: chunkSize).map {
Array(self[$0..<Swift.min($0 + chunkSize, self.count)])
}
}
}

View File

@ -5,10 +5,11 @@
// Created by Pat Nakajima on 12/6/22.
//
#if canImport(XCTest)
import Combine
import XCTest
@testable import XMTP
import XMTPProto
import XMTPRust
public struct FakeWallet: SigningKey {
public static func generate() throws -> FakeWallet {
@ -42,24 +43,24 @@ enum FakeApiClientError: String, Error {
}
class FakeStreamHolder: ObservableObject {
@Published var envelope: Envelope?
@Published var envelope: XMTP.Envelope?
func send(envelope: Envelope) {
func send(envelope: XMTP.Envelope) {
self.envelope = envelope
}
}
@available(iOS 15, *)
public class FakeApiClient: ApiClient {
public func envelopes(topics: [String], pagination: XMTP.Pagination?) async throws -> [XMTP.Envelope] {
try await query(topics: topics, pagination: pagination).envelopes
public func envelopes(topic: String, pagination: XMTP.Pagination?) async throws -> [XMTP.Envelope] {
try await query(topic: topic, pagination: pagination).envelopes
}
public var environment: XMTPEnvironment
public var authToken: String = ""
private var responses: [String: [Envelope]] = [:]
private var responses: [String: [XMTP.Envelope]] = [:]
private var stream = FakeStreamHolder()
public var published: [Envelope] = []
public var published: [XMTP.Envelope] = []
var cancellable: AnyCancellable?
var forbiddingQueries = false
@ -81,7 +82,7 @@ public class FakeApiClient: ApiClient {
forbiddingQueries = false
}
public func register(message: [Envelope], for topic: Topic) {
public func register(message: [XMTP.Envelope], for topic: Topic) {
var responsesForTopic = responses[topic.description] ?? []
responsesForTopic.append(contentsOf: message)
responses[topic.description] = responsesForTopic
@ -91,15 +92,15 @@ public class FakeApiClient: ApiClient {
environment = .local
}
public func send(envelope: Envelope) {
public func send(envelope: XMTP.Envelope) {
stream.send(envelope: envelope)
}
public func findPublishedEnvelope(_ topic: Topic) -> Envelope? {
public func findPublishedEnvelope(_ topic: Topic) -> XMTP.Envelope? {
return findPublishedEnvelope(topic.description)
}
public func findPublishedEnvelope(_ topic: String) -> Envelope? {
public func findPublishedEnvelope(_ topic: String) -> XMTP.Envelope? {
for envelope in published.reversed() {
if envelope.contentTopic == topic.description {
return envelope
@ -111,11 +112,11 @@ public class FakeApiClient: ApiClient {
// MARK: ApiClient conformance
public required init(environment: XMTP.XMTPEnvironment, secure _: Bool) throws {
public required init(environment: XMTP.XMTPEnvironment, secure _: Bool, rustClient _: XMTPRust.RustClient) throws {
self.environment = environment
}
public func subscribe(topics: [String]) -> AsyncThrowingStream<Envelope, Error> {
public func subscribe(topics: [String]) -> AsyncThrowingStream<XMTP.Envelope, Error> {
AsyncThrowingStream { continuation in
self.cancellable = stream.$envelope.sink(receiveValue: { env in
if let env, topics.contains(env.contentTopic) {
@ -129,22 +130,20 @@ public class FakeApiClient: ApiClient {
authToken = token
}
public func query(topics: [String], pagination: Pagination? = nil, cursor _: Xmtp_MessageApi_V1_Cursor? = nil) async throws -> XMTP.QueryResponse {
public func query(topic: String, pagination: Pagination? = nil, cursor _: Xmtp_MessageApi_V1_Cursor? = nil) async throws -> XMTP.QueryResponse {
if forbiddingQueries {
XCTFail("Attempted to query \(topics)")
XCTFail("Attempted to query \(topic)")
throw FakeApiClientError.queryAssertionFailure
}
var result: [Envelope] = []
var result: [XMTP.Envelope] = []
for topic in topics {
if let response = responses.removeValue(forKey: topic) {
result.append(contentsOf: response)
}
result.append(contentsOf: published.filter { $0.contentTopic == topic }.reversed())
if let response = responses.removeValue(forKey: topic) {
result.append(contentsOf: response)
}
result.append(contentsOf: published.filter { $0.contentTopic == topic }.reversed())
if let startAt = pagination?.startTime {
result = result
.filter { $0.timestampNs < UInt64(startAt.millisecondsSinceEpoch * 1_000_000) }
@ -181,8 +180,8 @@ public class FakeApiClient: ApiClient {
return queryResponse
}
public func query(topics: [XMTP.Topic], pagination: Pagination? = nil) async throws -> XMTP.QueryResponse {
return try await query(topics: topics.map(\.description), pagination: pagination, cursor: nil)
public func query(topic: XMTP.Topic, pagination: Pagination? = nil) async throws -> XMTP.QueryResponse {
return try await query(topic: topic.description, pagination: pagination, cursor: nil)
}
public func publish(envelopes: [XMTP.Envelope]) async throws -> XMTP.PublishResponse {
@ -194,6 +193,19 @@ public class FakeApiClient: ApiClient {
return PublishResponse()
}
public func batchQuery(request: XMTP.BatchQueryRequest) async throws -> XMTP.BatchQueryResponse {
abort() // Not supported on Fake
}
public func query(request: XMTP.QueryRequest) async throws -> XMTP.QueryResponse {
abort() // Not supported on Fake
}
public func publish(request: XMTP.PublishRequest) async throws -> XMTP.PublishResponse {
abort() // Not supported on Fake
}
}
@available(iOS 15, *)
@ -236,3 +248,4 @@ public extension XCTestCase {
return try! await Fixtures()
}
}
#endif

View File

@ -7,7 +7,6 @@
import Foundation
import secp256k1
import XCTest
@testable import XMTP

View File

@ -9,16 +9,29 @@ import Foundation
import XCTest
@testable import XMTP
import XMTPRust
import XMTPTestHelpers
@available(iOS 15, *)
class ClientTests: XCTestCase {
func testTakesAWallet() async throws {
let fakeWallet = try PrivateKey.generate()
_ = try await Client.create(account: fakeWallet)
}
func testCanMessage() async throws {
let fixtures = await fixtures()
let notOnNetwork = try PrivateKey.generate()
let canMessage = try await fixtures.aliceClient.canMessage(fixtures.bobClient.address)
let cannotMessage = try await fixtures.aliceClient.canMessage(notOnNetwork.address)
XCTAssertTrue(canMessage)
XCTAssertFalse(cannotMessage)
}
func testHasPrivateKeyBundleV1() async throws {
let fakeWallet = try PrivateKey.generate()
let client = try await Client.create(account: fakeWallet)
let client = try await Client.create(account: fakeWallet, apiClient: FakeApiClient())
XCTAssertEqual(1, client.privateKeyBundleV1.preKeys.count)
@ -32,7 +45,7 @@ class ClientTests: XCTestCase {
let client = try await Client.create(account: fakeWallet)
let bundle = client.privateKeyBundle
let clientFromV1Bundle = try Client.from(bundle: bundle)
let clientFromV1Bundle = try await Client.from(bundle: bundle)
XCTAssertEqual(client.address, clientFromV1Bundle.address)
XCTAssertEqual(client.privateKeyBundleV1.identityKey, clientFromV1Bundle.privateKeyBundleV1.identityKey)
@ -44,7 +57,7 @@ class ClientTests: XCTestCase {
let client = try await Client.create(account: fakeWallet)
let bundleV1 = client.v1keys
let clientFromV1Bundle = try Client.from(v1Bundle: bundleV1)
let clientFromV1Bundle = try await Client.from(v1Bundle: bundleV1)
XCTAssertEqual(client.address, clientFromV1Bundle.address)
XCTAssertEqual(client.privateKeyBundleV1.identityKey, clientFromV1Bundle.privateKeyBundleV1.identityKey)

View File

@ -20,14 +20,52 @@ class ConversationTests: XCTestCase {
var bob: PrivateKey!
var bobClient: Client!
var fixtures: Fixtures!
override func setUp() async throws {
alice = try PrivateKey.generate()
bob = try PrivateKey.generate()
fixtures = await fixtures()
fakeApiClient = FakeApiClient()
alice = fixtures.alice
bob = fixtures.bob
aliceClient = try await Client.create(account: alice, apiClient: fakeApiClient)
bobClient = try await Client.create(account: bob, apiClient: fakeApiClient)
fakeApiClient = fixtures.fakeApiClient
aliceClient = fixtures.aliceClient
bobClient = fixtures.bobClient
}
func testCanPrepareV1Message() async throws {
// Publish legacy contacts so we can get v1 conversations
try await fixtures.publishLegacyContact(client: bobClient)
try await fixtures.publishLegacyContact(client: aliceClient)
let conversation = try await aliceClient.conversations.newConversation(with: bob.address)
XCTAssertEqual(conversation.version, .v1)
let preparedMessage = try await conversation.prepareMessage(content: "hi")
let messageID = preparedMessage.messageID
try await preparedMessage.send()
let messages = try await conversation.messages()
let message = messages[0]
XCTAssertEqual("hi", message.body)
XCTAssertEqual(message.id, messageID)
}
func testCanPrepareV2Message() async throws {
let conversation = try await aliceClient.conversations.newConversation(with: bob.address)
let preparedMessage = try await conversation.prepareMessage(content: "hi")
let messageID = preparedMessage.messageID
try await preparedMessage.send()
let messages = try await conversation.messages()
let message = messages[0]
XCTAssertEqual("hi", message.body)
XCTAssertEqual(message.id, messageID)
}
func testV2RejectsSpoofedContactBundles() async throws {
@ -317,8 +355,10 @@ class ConversationTests: XCTestCase {
let expectation = expectation(description: "got a message")
Task(priority: .userInitiated) {
for try await _ in conversation.streamMessages() {
expectation.fulfill()
for try await message in conversation.streamMessages() {
if message.body == "hi alice" {
expectation.fulfill()
}
}
}

View File

@ -9,7 +9,9 @@ import Foundation
import secp256k1
import web3
import XCTest
import XMTPRust
@testable import XMTP
import XMTPRust
import XMTPTestHelpers
@available(iOS 16, *)
@ -24,7 +26,8 @@ final class IntegrationTests: XCTestCase {
let authToken = try await authorized.createAuthToken()
let api = try GRPCApiClient(environment: .local, secure: false)
let rustClient = try await XMTPRust.create_client(XMTP.GRPCApiClient.envToUrl(env: .local), false)
let api = try GRPCApiClient(environment: .local, secure: false, rustClient: rustClient)
api.setAuthToken(authToken)
let encryptedBundle = try await authorized.toBundle.encrypted(with: alice)
@ -38,7 +41,7 @@ final class IntegrationTests: XCTestCase {
try await Task.sleep(nanoseconds: 2_000_000_000)
let result = try await api.query(topics: [.userPrivateStoreKeyBundle(authorized.address)])
let result = try await api.query(topic: .userPrivateStoreKeyBundle(authorized.address))
XCTAssert(result.envelopes.count == 1)
}
@ -72,7 +75,8 @@ final class IntegrationTests: XCTestCase {
let identity = try PrivateKey.generate()
let authorized = try await aliceWallet.createIdentity(identity)
let authToken = try await authorized.createAuthToken()
var api = try GRPCApiClient(environment: .local, secure: false)
let rustClient = try await XMTPRust.create_client(XMTP.GRPCApiClient.envToUrl(env: .local), false)
let api = try GRPCApiClient(environment: .local, secure: false, rustClient: rustClient)
api.setAuthToken(authToken)
let encryptedBundle = try await PrivateKeyBundle(v1: alice).encrypted(with: aliceWallet)
var envelope = Envelope()
@ -360,16 +364,16 @@ final class IntegrationTests: XCTestCase {
throw XCTSkip("integration only (requires dev network)")
// Generated from JS script
let keyBytes: [UInt8] = [
let keyBytes = Data([
31, 116, 198, 193, 189, 122, 19, 254,
191, 189, 211, 215, 255, 131, 171, 239,
243, 33, 4, 62, 143, 86, 18, 195,
251, 61, 128, 90, 34, 126, 219, 236,
]
])
var key = PrivateKey()
key.secp256K1.bytes = Data(keyBytes)
key.publicKey.secp256K1Uncompressed.bytes = try KeyUtil.generatePublicKey(from: Data(keyBytes))
key.publicKey.secp256K1Uncompressed.bytes = Data(try XMTPRust.public_key_from_private_key_k256(RustVec(keyBytes)))
let client = try await XMTP.Client.create(account: key)
XCTAssertEqual(client.apiClient.environment, .dev)
@ -430,16 +434,16 @@ final class IntegrationTests: XCTestCase {
func testCanReadGzipCompressedMessages() async throws {
throw XCTSkip("integration only (requires dev network)")
let keyBytes: [UInt8] = [
let keyBytes = Data([
225, 2, 36, 98, 37, 243, 68, 234,
42, 126, 248, 246, 126, 83, 186, 197,
204, 186, 19, 173, 51, 0, 64, 0,
155, 8, 249, 247, 163, 185, 124, 159,
]
])
var key = PrivateKey()
key.secp256K1.bytes = Data(keyBytes)
key.publicKey.secp256K1Uncompressed.bytes = try KeyUtil.generatePublicKey(from: Data(keyBytes))
key.publicKey.secp256K1Uncompressed.bytes = Data(try XMTPRust.public_key_from_private_key_k256(RustVec<UInt8>(keyBytes)))
let client = try await XMTP.Client.create(account: key)
XCTAssertEqual(client.apiClient.environment, .dev)
@ -453,16 +457,16 @@ final class IntegrationTests: XCTestCase {
func testCanReadZipCompressedMessages() async throws {
throw XCTSkip("integration only (requires dev network)")
let keyBytes: [UInt8] = [
let keyBytes = Data([
60, 45, 240, 192, 223, 2, 14, 166,
122, 65, 231, 31, 122, 178, 158, 137,
192, 97, 139, 83, 133, 245, 149, 250,
25, 125, 25, 11, 203, 97, 12, 200,
]
])
var key = PrivateKey()
key.secp256K1.bytes = Data(keyBytes)
key.publicKey.secp256K1Uncompressed.bytes = try KeyUtil.generatePublicKey(from: Data(keyBytes))
key.publicKey.secp256K1Uncompressed.bytes = Data(try XMTPRust.public_key_from_private_key_k256(RustVec<UInt8>(keyBytes)))
let client = try await XMTP.Client.create(account: key)
XCTAssertEqual(client.apiClient.environment, .dev)
@ -482,16 +486,17 @@ final class IntegrationTests: XCTestCase {
func testCanLoadAllConversations() async throws {
throw XCTSkip("integration only (requires dev network)")
let keyBytes: [UInt8] = [
let keyBytes = Data([
105, 207, 193, 11, 240, 115, 115, 204,
117, 134, 201, 10, 56, 59, 52, 90,
229, 103, 15, 66, 20, 113, 118, 137,
44, 62, 130, 90, 30, 158, 182, 178,
]
])
var key = PrivateKey()
key.secp256K1.bytes = Data(keyBytes)
key.publicKey.secp256K1Uncompressed.bytes = try KeyUtil.generatePublicKey(from: Data(keyBytes))
key.publicKey.secp256K1Uncompressed.bytes = Data(try XMTPRust.public_key_from_private_key_k256(RustVec<UInt8>(keyBytes)))
let client = try await XMTP.Client.create(account: key)

View File

@ -7,6 +7,7 @@
import CryptoKit
import XCTest
import XMTPRust
@testable import XMTP
import XMTPTestHelpers
@ -114,7 +115,7 @@ class MessageTests: XCTestCase {
140, 247, 221, 172, 14, 188, 52, 88,
])
key.publicKey.secp256K1Uncompressed.bytes = try KeyUtil.generatePublicKey(from: key.secp256K1.bytes)
key.publicKey.secp256K1Uncompressed.bytes = try KeyUtilx.generatePublicKey(from: key.secp256K1.bytes)
}
let keyBundleData = Data(

View File

@ -0,0 +1,133 @@
//
// PaginationTests.swift
//
//
// Created by Michael Xu on 05/16/23.
//
import Foundation
import XCTest
@testable import XMTP
import XMTPRust
@available(iOS 15, *)
class PaginationTests: XCTestCase {
func newClientHelper(account: PrivateKey) async throws -> Client {
let client = try await Client.create(account: account, options: ClientOptions(api: .init(env: .local, isSecure: false)))
return client
}
func testLongConvo() async throws {
throw XCTSkip("integration only (requires local node)")
let alice = try PrivateKey.generate()
let bob = try PrivateKey.generate()
let aliceClient = try await newClientHelper(account: alice)
let bobClient = try await newClientHelper(account: bob)
let canAliceMessageBob = try await aliceClient.canMessage(bobClient.address)
XCTAssert(canAliceMessageBob)
// Start a conversation with alice
guard case let .v2(bobConversation) = try await bobClient.conversations.newConversation(with: alice.address, context: InvitationV1.Context(conversationID: "hi")) else {
XCTFail("did not get a v2 conversation for alice")
return
}
guard case let .v2(aliceConversation) = try await aliceClient.conversations.newConversation(with: bob.address, context: InvitationV1.Context(conversationID: "hi")) else {
XCTFail("did not get a v2 conversation for alice")
return
}
try await bobConversation.send(content: "hey alice 1", sentAt: Date().addingTimeInterval(-1000))
try await bobConversation.send(content: "hey alice 2", sentAt: Date().addingTimeInterval(-500))
try await bobConversation.send(content: "hey alice 3", sentAt: Date())
let messages = try await aliceConversation.messages(limit: 1)
XCTAssertEqual(1, messages.count)
XCTAssertEqual("hey alice 3", messages[0].body)
let messages2 = try await aliceConversation.messages(limit: 1, before: messages[0].sent)
XCTAssertEqual(1, messages2.count)
XCTAssertEqual("hey alice 2", messages2[0].body)
// Send many many more messages, such that it forces cursor saving and pagination
for i in 4..<101 {
try await bobConversation.send(content: "hey alice \(i)", sentAt: Date())
}
// Grab the messages 50 at a time
let messages3 = try await aliceConversation.messages(limit: 50)
XCTAssertEqual(50, messages3.count)
XCTAssertEqual("hey alice 100", messages3[0].body)
XCTAssertEqual("hey alice 51", messages3[49].body)
let messages4 = try await aliceConversation.messages(limit: 100, before: messages3[49].sent)
XCTAssertEqual(50, messages4.count)
XCTAssertEqual("hey alice 50", messages4[0].body)
XCTAssertEqual("hey alice 1", messages4[49].body)
}
func testCanStreamConversationsV2() async throws {
throw XCTSkip("integration only (requires local node)")
let alice = try PrivateKey.generate()
let bob = try PrivateKey.generate()
// Need to upload Alice's contact bundle
let _ = try await newClientHelper(account: alice)
let bobClient = try await newClientHelper(account: bob)
let expectation1 = expectation(description: "got a conversation")
expectation1.expectedFulfillmentCount = 2
Task(priority: .userInitiated) {
for try await _ in bobClient.conversations.stream() {
print("Got one conversation")
expectation1.fulfill()
}
}
guard case let .v2(conversation) = try await bobClient.conversations.newConversation(with: alice.walletAddress) else {
XCTFail("Did not create a v2 convo")
return
}
try await conversation.send(content: "hi")
let newWallet = try PrivateKey.generate()
// Need to upload contact bundle
let _ = try await newClientHelper(account: newWallet)
guard case let .v2(conversation2) = try await bobClient.conversations.newConversation(with: newWallet.walletAddress) else {
XCTFail("Did not create a v2 convo")
return
}
try await conversation2.send(content: "hi from new wallet")
await waitForExpectations(timeout: 5)
// Test that we can stream a few more messages
let expectation2 = expectation(description: "got follow-up messages")
expectation2.expectedFulfillmentCount = 5
Task(priority: .userInitiated) {
for try await message in conversation.streamMessages() {
print("Got message: \(message)")
expectation2.fulfill()
}
}
// Slowly send out messages
Task(priority: .userInitiated) {
try! await conversation.send(content: "hi")
try! await conversation.send(content: "hi again")
try! await conversation.send(content: "hi again again")
try! await conversation.send(content: "hi again again again")
try! await conversation.send(content: "hi again again again again")
}
await waitForExpectations(timeout: 5)
}
}

View File

@ -14,7 +14,6 @@ class SignatureTests: XCTestCase {
let digest = SHA256.hash(data: Data("Hello world".utf8))
let signingKey = try PrivateKey.generate()
let signature = try await signingKey.sign(Data(digest))
XCTAssert(try signature.verify(signedBy: signingKey.publicKey, digest: Data("Hello world".utf8)))
}
}

50
XMTP.podspec Normal file
View File

@ -0,0 +1,50 @@
#
# Be sure to run `pod spec lint XMTP.podspec' to ensure this is a
# valid spec and to remove all comments including this before submitting the spec.
#
# To learn more about Podspec attributes see https://guides.cocoapods.org/syntax/podspec.html
# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
#
Pod::Spec.new do |spec|
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
#
# These will help people to find your library, and whilst it
# can feel like a chore to fill in it's definitely to your advantage. The
# summary should be tweet-length, and the description more in depth.
#
spec.name = "XMTP"
spec.version = "0.3.1-alpha0"
spec.summary = "XMTP SDK Cocoapod"
# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!
spec.description = <<-DESC
The XMTP cocoapod implements the XMTP protocol for iOS. It handles cryptographic operations and network communication with the XMTP network.
DESC
spec.homepage = "https://github.com/xmtp/xmtp-ios"
spec.license = "MIT"
spec.author = { "Pat Nakajima" => "pat@xmtp.com" }
spec.platform = :ios, '14.0', :macos, '11.0'
spec.swift_version = '5.3'
spec.source = { :git => "https://github.com/xmtp/xmtp-ios.git", :tag => "#{spec.version}" }
spec.source_files = "Sources/**/*.swift"
spec.frameworks = "CryptoKit", "UIKit"
spec.dependency "web3.swift"
spec.dependency "GzipSwift"
spec.dependency "Connect-Swift"
spec.dependency 'XMTPRust', '= 0.3.0-beta0'
spec.xcconfig = {'VALID_ARCHS' => 'arm64' }
end

View File

@ -36,22 +36,23 @@ class NotificationService: UNNotificationServiceExtension {
return
}
let client = try Client.from(bundle: keys)
let conversation = conversationContainer.decode(with: client)
Task {
let client = try await Client.from(bundle: keys)
let conversation = conversationContainer.decode(with: client)
let envelope = XMTP.Envelope.with { envelope in
envelope.message = encryptedMessageData
envelope.contentTopic = topic
let envelope = XMTP.Envelope.with { envelope in
envelope.message = encryptedMessageData
envelope.contentTopic = topic
}
if let bestAttemptContent = bestAttemptContent {
let decodedMessage = try conversation.decode(envelope)
bestAttemptContent.body = (try? decodedMessage.content()) ?? "no content"
contentHandler(bestAttemptContent)
}
}
if let bestAttemptContent = bestAttemptContent {
let decodedMessage = try conversation.decode(envelope)
bestAttemptContent.body = (try? decodedMessage.content()) ?? "no content"
contentHandler(bestAttemptContent)
}
// swiftlint:enable no_optional_try
} catch {
print("Error receiving notification: \(error)")

32
XMTPiOSExample/Podfile Normal file
View File

@ -0,0 +1,32 @@
# Uncomment the next line to define a global platform for your project
platform :ios, '16.0'
target 'NotificationService' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for NotificationService
# pod "web3.swift"
# pod 'KeychainAccess'
end
target 'XMTPiOSExample' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for XMTPiOSExample
# pod 'WalletConnectSwift'
# pod "web3.swift"
# pod 'KeychainAccess'
# pod "XMTP", path: '../'
end
post_install do |installer|
installer.generated_projects.each do |project|
project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0'
end
end
end
end

View File

@ -0,0 +1,3 @@
PODFILE CHECKSUM: e82385142d41677b470dd3362d25b239b9c3621c
COCOAPODS: 1.12.0

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
6AEE396E29F330CD0027B657 /* secp256k1 in Frameworks */ = {isa = PBXBuildFile; productRef = 6AEE396D29F330CD0027B657 /* secp256k1 */; };
A60FC8BF293AD054001697E3 /* MessageComposerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A60FC8BE293AD054001697E3 /* MessageComposerView.swift */; };
A60FC8C1293AD171001697E3 /* ConversationDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A60FC8C0293AD171001697E3 /* ConversationDetailView.swift */; };
A60FC8C3293AD18A001697E3 /* PreviewClientProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A60FC8C2293AD18A001697E3 /* PreviewClientProvider.swift */; };
@ -92,6 +93,7 @@
buildActionMask = 2147483647;
files = (
A65F0707297B5E7600C3C76E /* WalletConnectSwift in Frameworks */,
6AEE396E29F330CD0027B657 /* secp256k1 in Frameworks */,
A69F33C6292DC992005A5556 /* XMTP in Frameworks */,
A65F070A297B5E8600C3C76E /* KeychainAccess in Frameworks */,
);
@ -217,6 +219,7 @@
A69F33C5292DC992005A5556 /* XMTP */,
A65F0706297B5E7600C3C76E /* WalletConnectSwift */,
A65F0709297B5E8600C3C76E /* KeychainAccess */,
6AEE396D29F330CD0027B657 /* secp256k1 */,
);
productName = XMTPiOSExample;
productReference = A628198F292DC825004B9117 /* XMTPiOSExample.app */;
@ -273,6 +276,7 @@
packageReferences = (
A65F0705297B5E7500C3C76E /* XCRemoteSwiftPackageReference "WalletConnectSwift" */,
A65F0708297B5E8600C3C76E /* XCRemoteSwiftPackageReference "KeychainAccess" */,
6AEE396C29F330CD0027B657 /* XCRemoteSwiftPackageReference "secp256k1.swift" */,
);
productRefGroup = A6281990292DC825004B9117 /* Products */;
projectDirPath = "";
@ -491,6 +495,7 @@
SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@ -530,6 +535,7 @@
SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_STRICT_CONCURRENCY = complete;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@ -625,6 +631,14 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
6AEE396C29F330CD0027B657 /* XCRemoteSwiftPackageReference "secp256k1.swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/GigaBitcoin/secp256k1.swift.git";
requirement = {
kind = exactVersion;
version = 0.10.0;
};
};
A65F0705297B5E7500C3C76E /* XCRemoteSwiftPackageReference "WalletConnectSwift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/WalletConnect/WalletConnectSwift";
@ -644,6 +658,11 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
6AEE396D29F330CD0027B657 /* secp256k1 */ = {
isa = XCSwiftPackageProductDependency;
package = 6AEE396C29F330CD0027B657 /* XCRemoteSwiftPackageReference "secp256k1.swift" */;
productName = secp256k1;
};
A65F0706297B5E7600C3C76E /* WalletConnectSwift */ = {
isa = XCSwiftPackageProductDependency;
package = A65F0705297B5E7500C3C76E /* XCRemoteSwiftPackageReference "WalletConnectSwift" */;

View File

@ -21,7 +21,7 @@
{
"identity" : "cryptoswift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/krzyzanowskim/CryptoSwift",
"location" : "https://github.com/krzyzanowskim/CryptoSwift.git",
"state" : {
"revision" : "039f56c5d7960f277087a0be51f5eb04ed0ec073",
"version" : "1.5.1"
@ -36,15 +36,6 @@
"version" : "2.0.2"
}
},
{
"identity" : "grpc-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/grpc/grpc-swift",
"state" : {
"revision" : "3e17f2b847da39b50329b7a11c5ad23453190e8b",
"version" : "1.13.0"
}
},
{
"identity" : "gzipswift",
"kind" : "remoteSourceControl",
@ -60,16 +51,7 @@
"location" : "https://github.com/kishikawakatsumi/KeychainAccess",
"state" : {
"branch" : "master",
"revision" : "6299daec1d74be12164fec090faf9ed14d0da9d6"
}
},
{
"identity" : "proto",
"kind" : "remoteSourceControl",
"location" : "https://github.com/xmtp/proto",
"state" : {
"branch" : "main",
"revision" : "6a8905a8b260406698433d210c25c4397a93cef1"
"revision" : "ecb18d8ce4d88277cc4fb103973352d91e18c535"
}
},
{
@ -77,8 +59,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/GigaBitcoin/secp256k1.swift.git",
"state" : {
"branch" : "main",
"revision" : "9bfd1a648d0867d5491f56f237c58bc0bd105fc3"
"revision" : "48fb20fce4ca3aad89180448a127d5bc16f0e44c",
"version" : "0.10.0"
}
},
{
@ -99,6 +81,24 @@
"version" : "1.0.3"
}
},
{
"identity" : "swift-docc-plugin",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-docc-plugin.git",
"state" : {
"revision" : "9b1258905c21fc1b97bf03d1b4ca12c4ec4e5fda",
"version" : "1.2.0"
}
},
{
"identity" : "swift-docc-symbolkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-docc-symbolkit",
"state" : {
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
"version" : "1.0.0"
}
},
{
"identity" : "swift-log",
"kind" : "remoteSourceControl",
@ -117,24 +117,6 @@
"version" : "2.45.0"
}
},
{
"identity" : "swift-nio-extras",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-extras.git",
"state" : {
"revision" : "91dd2d61fb772e1311bb5f13b59266b579d77e42",
"version" : "1.15.0"
}
},
{
"identity" : "swift-nio-http2",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-nio-http2.git",
"state" : {
"revision" : "d6656967f33ed8b368b38e4b198631fc7c484a40",
"version" : "1.23.1"
}
},
{
"identity" : "swift-nio-ssl",
"kind" : "remoteSourceControl",
@ -188,6 +170,15 @@
"revision" : "2d9d2188a08eef4a869d368daab21b3c08510991",
"version" : "2.6.1"
}
},
{
"identity" : "xmtp-rust-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/xmtp/xmtp-rust-swift",
"state" : {
"revision" : "41a1161cf06a86bab0aa886e450584a1191429b1",
"version" : "0.3.0-beta0"
}
}
],
"version" : 2

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A6AE517F297B61AE006FDD0F"
BuildableName = "NotificationService.appex"
BlueprintName = "NotificationService"
ReferencedContainer = "container:XMTPiOSExample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A628198E292DC825004B9117"
BuildableName = "XMTPiOSExample.app"
BlueprintName = "XMTPiOSExample"
ReferencedContainer = "container:XMTPiOSExample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A628198E292DC825004B9117"
BuildableName = "XMTPiOSExample.app"
BlueprintName = "XMTPiOSExample"
ReferencedContainer = "container:XMTPiOSExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
askForAppToLaunch = "Yes"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A628198E292DC825004B9117"
BuildableName = "XMTPiOSExample.app"
BlueprintName = "XMTPiOSExample"
ReferencedContainer = "container:XMTPiOSExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A628198E292DC825004B9117"
BuildableName = "XMTPiOSExample.app"
BlueprintName = "XMTPiOSExample"
ReferencedContainer = "container:XMTPiOSExample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A628198E292DC825004B9117"
BuildableName = "XMTPiOSExample.app"
BlueprintName = "XMTPiOSExample"
ReferencedContainer = "container:XMTPiOSExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A628198E292DC825004B9117"
BuildableName = "XMTPiOSExample.app"
BlueprintName = "XMTPiOSExample"
ReferencedContainer = "container:XMTPiOSExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -5,7 +5,6 @@
// Created by Pat Nakajima on 11/22/22.
//
import Foundation
import UIKit
import XMTP
/// Wrapper around a WalletConnect V1 wallet connection. Account conforms to ``SigningKey`` so

View File

@ -10,6 +10,7 @@ import UIKit
import WalletConnectSwift
import web3
import XMTP
import UIKit
extension WCURL {
var asURL: URL {
@ -61,7 +62,7 @@ class WCWalletConnection: WalletConnection, WalletConnectSwift.ClientDelegate {
walletConnectClient = WalletConnectSwift.Client(delegate: self, dAppInfo: dAppInfo)
}
func preferredConnectionMethod() throws -> WalletConnectionMethodType {
@MainActor func preferredConnectionMethod() throws -> WalletConnectionMethodType {
guard let url = walletConnectURL?.asURL else {
throw WalletConnectionError.walletConnectURL
}

View File

@ -105,7 +105,7 @@ struct ContentView: View {
Task {
do {
let wallet = try PrivateKey.generate()
let client = try await Client.create(account: wallet)
let client = try await Client.create(account: wallet, options: .init(api: .init(env: .dev, isSecure: true)))
let keysData = try client.privateKeyBundle.serializedData()
Persistence().saveKeys(keysData)

8
buf.gen.yaml Normal file
View File

@ -0,0 +1,8 @@
version: v1
managed:
enabled: true
plugins:
- plugin: buf.build/apple/swift
out: Sources/XMTP/Proto
opt:
- Visibility=Public

View File

@ -2,12 +2,14 @@ version: "3.8"
services:
wakunode:
image: xmtp/node-go
platform: linux/arm64
environment:
- GOWAKU-NODEKEY=8a30dcb604b0b53627a5adc054dbf434b446628d4bd1eccc681d223f0550ce67
command:
- --ws
- --store
- --message-db-connection-string=postgres://postgres:xmtp@db:5432/postgres?sslmode=disable
- --message-db-reader-connection-string=postgres://postgres:xmtp@db:5432/postgres?sslmode=disable
- --lightpush
- --filter
- --ws-port=9001
@ -20,7 +22,7 @@ services:
depends_on:
- db
healthcheck:
test: ["CMD", "lsof", "-i", ":5556"]
test: [ "CMD", "lsof", "-i", ":5556" ]
interval: 3s
timeout: 10s
retries: 5

3
script/gen-proto Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env sh
buf generate buf.build/xmtp/proto

View File

@ -1,3 +1,3 @@
#!/usr/bin/env sh
swiftlint Sources/ XMTPiOSExample/
swiftlint Sources/ XMTPiOSExample/XMTPiOSExample

View File

@ -1,3 +1,3 @@
#!/usr/bin/env sh
docker-compose -p xmtp-ios-swift -f dev/local/docker-compose.yml up
docker-compose -p xmtp-ios-swiftxx -f dev/local/docker-compose.yml up