Skip to content

Commit

Permalink
Ton connect initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ealymbaev committed Oct 2, 2024
1 parent 27e768d commit 4bf0d8e
Show file tree
Hide file tree
Showing 44 changed files with 2,629 additions and 12 deletions.
9 changes: 9 additions & 0 deletions UnstoppableWallet/TonConnectAPI/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
15 changes: 15 additions & 0 deletions UnstoppableWallet/TonConnectAPI/Generation/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// swift-tools-version: 5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "TonAPI",
platforms: [
.macOS(.v12), .iOS(.v13)
],
dependencies: [
.package(url: "https://github.com/apple/swift-openapi-generator", .upToNextMinor(from: "0.3.0")),
.package(url: "https://github.com/apple/swift-openapi-runtime", .upToNextMinor(from: "0.3.0")),
]
)
5 changes: 5 additions & 0 deletions UnstoppableWallet/TonConnectAPI/Generation/generate_api.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash
swift run swift-openapi-generator generate \
--mode types --mode client \
--output-directory ../Sources/TonConnectAPI\
./openapi.yml
93 changes: 93 additions & 0 deletions UnstoppableWallet/TonConnectAPI/Generation/openapi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
openapi: 3.0.2
info:
title: TonConnect
version: 1.0.0
servers:
- url: "https://bridge.tonapi.io/bridge"
paths:
/events:
get:
operationId: events
parameters:
- $ref: '#/components/parameters/clientIdParameter'
- name: last_event_id
in: query
required: false
schema:
type: string
responses:
"200":
description: OK
content:
text/event-stream:
schema:
type: string
format: binary
/message:
post:
operationId: message
parameters:
- name: client_id
in: query
required: true
schema:
type: string
- name: to
in: query
required: true
schema:
type: string
- name: ttl
in: query
required: true
schema:
type: integer
format: int64
requestBody:
required: true
content:
text/plain:
schema:
type: string
contentEncoding: base64
responses:
'200':
$ref: '#/components/responses/Response'
'default':
$ref: '#/components/responses/Response'
components:
parameters:
clientIdParameter:
in: query
name: client_id
required: true
explode: false
schema:
type: array
items:
type: string
toParameter:
in: query
name: to
required: true
explode: false
schema:
type: array
items:
type: string
responses:
Response:
description: OK
content:
application/json:
schema:
type: object
required:
- message
- statusCode
properties:
message:
type: string
statusCode:
type: integer
format: int64
29 changes: 29 additions & 0 deletions UnstoppableWallet/TonConnectAPI/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// swift-tools-version: 5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "TonConnectAPI",
platforms: [
.macOS(.v12), .iOS(.v13)
],
products: [
.library(name: "TonConnectAPI", targets: ["TonConnectAPI"])
],
dependencies: [
.package(url: "https://github.com/apple/swift-openapi-runtime", .upToNextMinor(from: "0.3.0")),
],
targets: [
.target(name: "TonConnectAPI",
dependencies: [
.product(
name: "OpenAPIRuntime",
package: "swift-openapi-runtime"
)
],
path: "Sources",
sources: ["TonConnectAPI"]
)
]
)
166 changes: 166 additions & 0 deletions UnstoppableWallet/TonConnectAPI/Sources/TonConnectAPI/Client.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// Generated by swift-openapi-generator, do not modify.
@_spi(Generated) import OpenAPIRuntime
#if os(Linux)
@preconcurrency import struct Foundation.URL
@preconcurrency import struct Foundation.Data
@preconcurrency import struct Foundation.Date
#else
import struct Foundation.URL
import struct Foundation.Data
import struct Foundation.Date
#endif
import HTTPTypes
public struct Client: APIProtocol {
/// The underlying HTTP client.
private let client: UniversalClient
/// Creates a new client.
/// - Parameters:
/// - serverURL: The server URL that the client connects to. Any server
/// URLs defined in the OpenAPI document are available as static methods
/// on the ``Servers`` type.
/// - configuration: A set of configuration values for the client.
/// - transport: A transport that performs HTTP operations.
/// - middlewares: A list of middlewares to call before the transport.
public init(
serverURL: Foundation.URL,
configuration: Configuration = .init(),
transport: any ClientTransport,
middlewares: [any ClientMiddleware] = []
) {
self.client = .init(
serverURL: serverURL,
configuration: configuration,
transport: transport,
middlewares: middlewares
)
}
private var converter: Converter { client.converter }
/// - Remark: HTTP `GET /events`.
/// - Remark: Generated from `#/paths//events/get(events)`.
public func events(_ input: Operations.events.Input) async throws -> Operations.events.Output {
try await client.send(
input: input,
forOperation: Operations.events.id,
serializer: { input in
let path = try converter.renderedPath(template: "/events", parameters: [])
var request: HTTPTypes.HTTPRequest = .init(soar_path: path, method: .get)
suppressMutabilityWarning(&request)
try converter.setQueryItemAsURI(
in: &request,
style: .form,
explode: true,
name: "client_id",
value: input.query.client_id
)
try converter.setQueryItemAsURI(
in: &request,
style: .form,
explode: true,
name: "last_event_id",
value: input.query.last_event_id
)
converter.setAcceptHeader(in: &request.headerFields, contentTypes: input.headers.accept)
return (request, nil)
},
deserializer: { response, responseBody in
switch response.status.code {
case 200:
let contentType = converter.extractContentTypeIfPresent(in: response.headerFields)
let body: Operations.events.Output.Ok.Body
if try contentType == nil
|| converter.isMatchingContentType(received: contentType, expectedRaw: "text/event-stream")
{
body = try converter.getResponseBodyAsBinary(
OpenAPIRuntime.HTTPBody.self,
from: responseBody,
transforming: { value in .text_event_hyphen_stream(value) }
)
} else {
throw converter.makeUnexpectedContentTypeError(contentType: contentType)
}
return .ok(.init(body: body))
default: return .undocumented(statusCode: response.status.code, .init())
}
}
)
}
/// - Remark: HTTP `POST /message`.
/// - Remark: Generated from `#/paths//message/post(message)`.
public func message(_ input: Operations.message.Input) async throws -> Operations.message.Output {
try await client.send(
input: input,
forOperation: Operations.message.id,
serializer: { input in
let path = try converter.renderedPath(template: "/message", parameters: [])
var request: HTTPTypes.HTTPRequest = .init(soar_path: path, method: .post)
suppressMutabilityWarning(&request)
try converter.setQueryItemAsURI(
in: &request,
style: .form,
explode: true,
name: "client_id",
value: input.query.client_id
)
try converter.setQueryItemAsURI(
in: &request,
style: .form,
explode: true,
name: "to",
value: input.query.to
)
try converter.setQueryItemAsURI(
in: &request,
style: .form,
explode: true,
name: "ttl",
value: input.query.ttl
)
converter.setAcceptHeader(in: &request.headerFields, contentTypes: input.headers.accept)
let body: OpenAPIRuntime.HTTPBody?
switch input.body {
case let .plainText(value):
body = try converter.setRequiredRequestBodyAsBinary(
value,
headerFields: &request.headerFields,
contentType: "text/plain"
)
}
return (request, body)
},
deserializer: { response, responseBody in
switch response.status.code {
case 200:
let contentType = converter.extractContentTypeIfPresent(in: response.headerFields)
let body: Components.Responses.Response.Body
if try contentType == nil
|| converter.isMatchingContentType(received: contentType, expectedRaw: "application/json")
{
body = try await converter.getResponseBodyAsJSON(
Components.Responses.Response.Body.jsonPayload.self,
from: responseBody,
transforming: { value in .json(value) }
)
} else {
throw converter.makeUnexpectedContentTypeError(contentType: contentType)
}
return .ok(.init(body: body))
default:
let contentType = converter.extractContentTypeIfPresent(in: response.headerFields)
let body: Components.Responses.Response.Body
if try contentType == nil
|| converter.isMatchingContentType(received: contentType, expectedRaw: "application/json")
{
body = try await converter.getResponseBodyAsJSON(
Components.Responses.Response.Body.jsonPayload.self,
from: responseBody,
transforming: { value in .json(value) }
)
} else {
throw converter.makeUnexpectedContentTypeError(contentType: contentType)
}
return .`default`(statusCode: response.status.code, .init(body: body))
}
}
)
}
}
Loading

0 comments on commit 4bf0d8e

Please sign in to comment.