Skip to content

Commit

Permalink
Bug fixes for TonConnect
Browse files Browse the repository at this point in the history
  • Loading branch information
ealymbaev committed Feb 13, 2025
1 parent 03f188a commit 9bac07c
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2700,6 +2700,8 @@
D30C4D582D55FE980082B487 /* BottomSheetModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30C4D562D55FE910082B487 /* BottomSheetModifier.swift */; };
D30C4D5A2D560D3A0082B487 /* BottomSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30C4D592D560D360082B487 /* BottomSheetView.swift */; };
D30C4D5B2D560D3A0082B487 /* BottomSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30C4D592D560D360082B487 /* BottomSheetView.swift */; };
D30C4D612D5CAFCB0082B487 /* TonConnectErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30C4D5F2D5CAFCB0082B487 /* TonConnectErrorView.swift */; };
D30C4D632D5CAFCB0082B487 /* TonConnectErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30C4D5F2D5CAFCB0082B487 /* TonConnectErrorView.swift */; };
D30D7E5F2CAAC89700B8CAA7 /* TonConnectEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30D7E5E2CAAC89700B8CAA7 /* TonConnectEventHandler.swift */; };
D30D7E602CAAC89700B8CAA7 /* TonConnectEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30D7E5E2CAAC89700B8CAA7 /* TonConnectEventHandler.swift */; };
D30D7E622CAACCF300B8CAA7 /* TonConnectSendView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D30D7E612CAACCF300B8CAA7 /* TonConnectSendView.swift */; };
Expand Down Expand Up @@ -4604,6 +4606,7 @@
D30C4D532D537E990082B487 /* RecentAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentAddress.swift; sourceTree = "<group>"; };
D30C4D562D55FE910082B487 /* BottomSheetModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomSheetModifier.swift; sourceTree = "<group>"; };
D30C4D592D560D360082B487 /* BottomSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BottomSheetView.swift; sourceTree = "<group>"; };
D30C4D5F2D5CAFCB0082B487 /* TonConnectErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TonConnectErrorView.swift; sourceTree = "<group>"; };
D30D7E5E2CAAC89700B8CAA7 /* TonConnectEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TonConnectEventHandler.swift; sourceTree = "<group>"; };
D30D7E612CAACCF300B8CAA7 /* TonConnectSendView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TonConnectSendView.swift; sourceTree = "<group>"; };
D30D7E642CAACCFB00B8CAA7 /* TonConnectSendViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TonConnectSendViewModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -8763,6 +8766,7 @@
D362879D2CA2B32900ADAF3B /* TonConnect */ = {
isa = PBXGroup;
children = (
D30C4D5F2D5CAFCB0082B487 /* TonConnectErrorView.swift */,
D362879E2CA2B34E00ADAF3B /* TonConnectListView.swift */,
D36287A12CA2B35A00ADAF3B /* TonConnectListViewModel.swift */,
D36287A52CA2B89200ADAF3B /* TonConnectParameters.swift */,
Expand Down Expand Up @@ -10050,6 +10054,7 @@
11B351B95F191EEA750D9955 /* BalancePrimaryValue.swift in Sources */,
D362879F2CA2B34E00ADAF3B /* TonConnectListView.swift in Sources */,
11B35C2D75133B8F13101A24 /* BalancePrimaryValueManager.swift in Sources */,
D30C4D632D5CAFCB0082B487 /* TonConnectErrorView.swift in Sources */,
11B350F9E67A095998D9462C /* BalanceConversionManager.swift in Sources */,
11B35D11D00301F7B67B0340 /* AppIconManager.swift in Sources */,
11B35B0E1435737240D26C92 /* AppIcon.swift in Sources */,
Expand Down Expand Up @@ -11538,6 +11543,7 @@
ABC9A9562DD283B6FCACBCF9 /* MarketCardTitleView.swift in Sources */,
D36287A02CA2B34E00ADAF3B /* TonConnectListView.swift in Sources */,
ABC9AC1BD5C95957726F8AE8 /* MarketCardValueView.swift in Sources */,
D30C4D612D5CAFCB0082B487 /* TonConnectErrorView.swift in Sources */,
ABC9ADE7C30F3F992FD9E1CC /* Array.swift in Sources */,
ABC9AE223619E13A296BED51 /* MarketCardCell.swift in Sources */,
11B353E7A2462E19D946E723 /* CellComponent.swift in Sources */,
Expand Down Expand Up @@ -13116,7 +13122,7 @@
repositoryURL = "https://github.com/horizontalsystems/TonKit.Swift";
requirement = {
kind = exactVersion;
version = 1.0.14;
version = 1.0.15;
};
};
6BF66DD82BA1A73300963242 /* XCRemoteSwiftPackageReference "ObjectMapper" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ enum MainModule {
let tonConnectHandler = TonConnectEventHandler(parentViewController: viewController)

eventHandler.append(handler: deepLinkHandler)
// eventHandler.append(handler: tonConnectHandler)
eventHandler.append(handler: tonConnectHandler)
eventHandler.append(handler: widgetCoinHandler)
eventHandler.append(handler: sendAddressHandler)
eventHandler.append(handler: telegramUserHandler)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,15 +289,15 @@ class MainSettingsViewController: ThemeViewController {
self?.viewModel.onTapWalletConnect()
}
),
// StaticRow(
// cell: tonConnectCell,
// id: "ton-connect",
// height: .heightCell48,
// autoDeselect: true,
// action: { [weak self] in
// self?.onTapTonConnect()
// }
// ),
StaticRow(
cell: tonConnectCell,
id: "ton-connect",
height: .heightCell48,
autoDeselect: true,
action: { [weak self] in
self?.onTapTonConnect()
}
),
tableView.universalRow48(
id: "backup-manager",
image: .local(UIImage(named: "icloud_24")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,26 +272,40 @@ private extension Int {

public struct SendTransactionParam: Decodable {
let messages: [Message]
let validUntil: TimeInterval
let validUntil: TimeInterval?
let from: TonSwift.Address?
let network: TonConnect.Network

enum CodingKeys: String, CodingKey {
case messages
case validUntil = "valid_until"
case from
case source
case network
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
messages = try container.decode([Message].self, forKey: .messages)
validUntil = try container.decode(TimeInterval.self, forKey: .validUntil)
if container.contains(.validUntil) {
validUntil = try container.decode(TimeInterval.self, forKey: .validUntil)
} else {
validUntil = nil
}

if let fromValue = try? container.decode(String.self, forKey: .from) {
from = try TonSwift.Address.parse(fromValue)
} else {
from = try TonSwift.Address.parse(container.decode(String.self, forKey: .source))
}

let rawNetwork = try container.decode(String.self, forKey: .network)

guard let intNetwork = Int16(rawNetwork), let network = TonConnect.Network(rawValue: intNetwork) else {
throw AppError.unknownError
}

self.network = network
}

public struct Message: Decodable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ struct TonConnectConnectView: View {
.disabled(viewModel.account == nil)

Button(action: {
viewModel.rejectConnection()
presentationMode.wrappedValue.dismiss()
}) {
Text("ton_connect.connect.reject".localized)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,10 @@ extension TonConnectConnectViewModel {
}
}
}

func rejectConnection() {
Task {
try await tonConnectManager.rejectConnection(parameters: parameters)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import ComponentKit
import MarketKit
import SwiftUI

struct TonConnectErrorView: View {
let requestError: TonConnectSendTransactionRequestError

@Environment(\.presentationMode) private var presentationMode

var body: some View {
ThemeNavigationView {
ThemeView {
BottomGradientWrapper {
VStack {
HighlightedTextView(text: "ton_connect.invalid_transaction".localized, style: .alert)
Spacer()
}
.padding(.top, .margin12)
.padding(.horizontal, .margin16)
} bottomContent: {
Button(action: {
presentationMode.wrappedValue.dismiss()
}) {
Text("button.close".localized)
}
.buttonStyle(PrimaryButtonStyle(style: .gray))
}
}
.navigationTitle(requestError.app.manifest.name)
.navigationBarTitleDisplayMode(.inline)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,22 @@ class TonConnectEventHandler {
.receive(on: DispatchQueue.main)
.sink { [weak self] in self?.handle(sendTransactionRequest: $0) }
.store(in: &cancellables)

tonConnectManager.sendTransactionRequestErrorPublisher
.receive(on: DispatchQueue.main)
.sink { [weak self] in self?.handle(sendTransactionRequestError: $0) }
.store(in: &cancellables)
}

private func handle(sendTransactionRequest: TonConnectSendTransactionRequest) {
let view = TonConnectSendView(request: sendTransactionRequest)
parentViewController?.visibleController.present(view.toViewController(), animated: true)
}

private func handle(sendTransactionRequestError: TonConnectSendTransactionRequestError) {
let view = TonConnectErrorView(requestError: sendTransactionRequestError)
parentViewController?.visibleController.present(view.toViewController(), animated: true)
}
}

extension TonConnectEventHandler: IEventHandler {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class TonConnectManager {
private let jsonDecoder = JSONDecoder()

private let sendTransactionRequestSubject = PassthroughSubject<TonConnectSendTransactionRequest, Never>()
private let sendTransactionRequestErrorSubject = PassthroughSubject<TonConnectSendTransactionRequestError, Never>()

init(storage: TonConnectStorage, accountManager: AccountManager) {
let configuration = URLSessionConfiguration.default
Expand All @@ -35,11 +36,11 @@ class TonConnectManager {
self.storage = storage
self.accountManager = accountManager

// accountManager.accountDeletedPublisher
// .sink { [weak self] in self?.handleDeleted(account: $0) }
// .store(in: &cancellables)
//
// syncTonConnectApps()
accountManager.accountDeletedPublisher
.sink { [weak self] in self?.handleDeleted(account: $0) }
.store(in: &cancellables)

syncTonConnectApps()
}

private func handleDeleted(account: Account) {
Expand All @@ -63,7 +64,7 @@ class TonConnectManager {
tonConnectApps = []
}

// start()
start()
}

public func start() {
Expand All @@ -75,7 +76,7 @@ class TonConnectManager {
return
}

// print("Apps: \(tonConnectApps.map { $0.manifest.name })")
// print("Apps: \(tonConnectApps.map(\.manifest.name))")

let task = Task { [storage, tonConnectApps] in
let ids = tonConnectApps.map(\.keyPair.publicKey.hexString).joined(separator: ",")
Expand Down Expand Up @@ -149,8 +150,12 @@ class TonConnectManager {

switch request.method {
case .sendTransaction:
if let param = request.params.first {
if let param = request.params.first, param.network == .mainnet, !param.messages.isEmpty {
sendTransactionRequestSubject.send(.init(id: request.id, param: param, app: app))
} else {
let requestError = TonConnectSendTransactionRequestError(id: request.id, app: app)
sendTransactionRequestErrorSubject.send(requestError)
handle(requestError: requestError)
}
case .disconnect:
try delete(tonConnectApp: app)
Expand Down Expand Up @@ -193,6 +198,8 @@ class TonConnectManager {
body: .plainText(.init(stringLiteral: encrypted.base64EncodedString()))
)

// print("SEND: \(String(data: encoded, encoding: .utf8) ?? "nil")")

// _ = try resp.ok.body.json
}

Expand All @@ -204,7 +211,15 @@ class TonConnectManager {
private func delete(tonConnectApp: TonConnectApp) throws {
try storage.delete(tonConnectApp: tonConnectApp)

// syncTonConnectApps()
syncTonConnectApps()
}

func handle(requestError: TonConnectSendTransactionRequestError) {
Task {
let message = TonConnect.SendTransactionResponse.error(.init(id: requestError.id, error: .init(code: .badRequest, message: "“Bad request")))
let sessionCrypto = try TonConnectSessionCrypto(privateKey: requestError.app.keyPair.privateKey)
try await send(message: message, clientId: requestError.app.clientId, sessionCrypto: sessionCrypto)
}
}
}

Expand All @@ -213,6 +228,10 @@ extension TonConnectManager {
sendTransactionRequestSubject.eraseToAnyPublisher()
}

var sendTransactionRequestErrorPublisher: AnyPublisher<TonConnectSendTransactionRequestError, Never> {
sendTransactionRequestErrorSubject.eraseToAnyPublisher()
}

func loadTonConnectConfiguration(parameters: TonConnectParameters) async throws -> TonConnectConfig {
do {
let manifest = try await loadManifest(url: parameters.requestPayload.manifestUrl)
Expand Down Expand Up @@ -243,7 +262,14 @@ extension TonConnectManager {
try await send(message: message, clientId: parameters.clientId, sessionCrypto: sessionCrypto)
try storeConnectedApp(account: account, sessionCrypto: sessionCrypto, parameters: parameters, manifest: manifest)

// syncTonConnectApps()
syncTonConnectApps()
}

func rejectConnection(parameters: TonConnectParameters) async throws {
let message = TonConnect.ConnectEventError(payload: .init(code: .userDeclinedTheConnection, message: "User declined the connection"))
let sessionCrypto = try TonConnectSessionCrypto()

try await send(message: message, clientId: parameters.clientId, sessionCrypto: sessionCrypto)
}

func disconnect(tonConnectApp: TonConnectApp) async throws {
Expand All @@ -261,7 +287,7 @@ extension TonConnectManager {
}

func reject(request: TonConnectSendTransactionRequest) async throws {
let message = TonConnect.SendTransactionResponse.error(.init(id: request.id, error: .init(code: .userDeclinedTransaction, message: "")))
let message = TonConnect.SendTransactionResponse.error(.init(id: request.id, error: .init(code: .userDeclinedTransaction, message: "“User declined the transaction")))
let sessionCrypto = try TonConnectSessionCrypto(privateKey: request.app.keyPair.privateKey)

try await send(message: message, clientId: request.app.clientId, sessionCrypto: sessionCrypto)
Expand Down Expand Up @@ -318,3 +344,8 @@ struct TonConnectSendTransactionRequest {
let param: SendTransactionParam
let app: TonConnectApp
}

struct TonConnectSendTransactionRequestError {
let id: String
let app: TonConnectApp
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,27 @@ extension TonConnectSendHandler: ISendHandler {
var fee: Decimal?
var transactionError: Error?
var record: TonTransactionRecord?
let account = try await TonKit.Kit.account(address: transferData.sender)

do {
var totalValue: BigUInt = 0

for message in transferData.internalMessages {
switch message.info {
case let .internalInfo(info):
totalValue += info.value.coins.rawValue
default: ()
}
}

let result = try await TonKit.Kit.emulate(transferData: transferData, contract: contract, network: TonKitManager.network)

record = converter.transactionRecord(event: result.event)
fee = TonAdapter.amount(kitAmount: result.totalFee)

guard account.balance >= totalValue + result.totalFee else {
throw TransactionError.insufficientTonBalance(balance: TonAdapter.amount(kitAmount: account.balance))
}
} catch {
transactionError = error
}
Expand Down Expand Up @@ -305,7 +320,7 @@ extension TonConnectSendHandler {
)
}

let transferData = try TonKit.Kit.transferData(sender: address, payloads: payloads)
let transferData = try TonKit.Kit.transferData(sender: address, validUntil: request.param.validUntil, payloads: payloads)

guard let baseToken = try? App.shared.coinManager.token(query: .init(blockchainType: .ton, tokenType: .native)) else {
throw FactoryError.noBaseToken
Expand Down
Loading

0 comments on commit 9bac07c

Please sign in to comment.