-
Notifications
You must be signed in to change notification settings - Fork 250
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
33 changed files
with
730 additions
and
524 deletions.
There are no files selected for viewing
138 changes: 26 additions & 112 deletions
138
UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj
Large diffs are not rendered by default.
Oops, something went wrong.
22 changes: 22 additions & 0 deletions
22
...nstoppableWallet/Assets.xcassets/Images/the-open-network_jetton_32.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"idiom" : "universal", | ||
"scale" : "1x" | ||
}, | ||
{ | ||
"filename" : "[email protected]", | ||
"idiom" : "universal", | ||
"scale" : "2x" | ||
}, | ||
{ | ||
"filename" : "[email protected]", | ||
"idiom" : "universal", | ||
"scale" : "3x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
Binary file added
BIN
+1.85 KB
...ets.xcassets/Images/the-open-network_jetton_32.imageset/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+2.74 KB
...ets.xcassets/Images/the-open-network_jetton_32.imageset/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
172 changes: 172 additions & 0 deletions
172
UnstoppableWallet/UnstoppableWallet/Core/Adapters/JettonAdapter.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
import BigInt | ||
import Combine | ||
import Foundation | ||
import RxSwift | ||
import TonKit | ||
import TonSwift | ||
|
||
class JettonAdapter { | ||
private let tonKit: TonKit.Kit | ||
private let address: TonSwift.Address | ||
private var cancellables = Set<AnyCancellable>() | ||
|
||
private let balanceStateSubject = PublishSubject<AdapterState>() | ||
private(set) var balanceState: AdapterState { | ||
didSet { | ||
balanceStateSubject.onNext(balanceState) | ||
} | ||
} | ||
|
||
private let jettonBalanceSubject = PublishSubject<JettonBalance?>() | ||
private(set) var jettonBalance: JettonBalance? { | ||
didSet { | ||
jettonBalanceSubject.onNext(jettonBalance) | ||
} | ||
} | ||
|
||
private let transactionRecordsSubject = PublishSubject<[TonTransactionRecord]>() | ||
|
||
init(tonKit: TonKit.Kit, address: String) throws { | ||
self.tonKit = tonKit | ||
self.address = try TonSwift.Address.parse(address) | ||
|
||
balanceState = Self.adapterState(kitSyncState: tonKit.jettonSyncState) | ||
jettonBalance = tonKit.jettonBalanceMap[self.address] | ||
|
||
tonKit.jettonSyncStatePublisher | ||
.sink { [weak self] in self?.balanceState = Self.adapterState(kitSyncState: $0) } | ||
.store(in: &cancellables) | ||
|
||
tonKit.jettonBalanceMapPublisher | ||
.sink { [weak self] in self?.handle(jettonBalanceMap: $0) } | ||
.store(in: &cancellables) | ||
} | ||
|
||
private func handle(jettonBalanceMap: [TonSwift.Address: JettonBalance]) { | ||
jettonBalance = jettonBalanceMap[address] | ||
} | ||
|
||
private static func adapterState(kitSyncState: TonKit.SyncState) -> AdapterState { | ||
switch kitSyncState { | ||
case .syncing: return .syncing(progress: nil, lastBlockDate: nil) | ||
case .synced: return .synced | ||
case let .notSynced(error): return .notSynced(error: error) | ||
} | ||
} | ||
|
||
private static func amount(jettonBalance: JettonBalance?) -> Decimal { | ||
guard let jettonBalance, let significand = Decimal(string: jettonBalance.balance.description) else { | ||
return 0 | ||
} | ||
|
||
return Decimal(sign: .plus, exponent: -jettonBalance.jetton.decimals, significand: significand) | ||
} | ||
|
||
private static func amount(kitAmount: BigUInt, decimals: Int) -> Decimal { | ||
guard let significand = Decimal(string: kitAmount.description) else { | ||
return 0 | ||
} | ||
|
||
return Decimal(sign: .plus, exponent: -decimals, significand: significand) | ||
} | ||
} | ||
|
||
extension JettonAdapter: IBaseAdapter { | ||
var isMainNet: Bool { | ||
true | ||
} | ||
} | ||
|
||
extension JettonAdapter: IAdapter { | ||
func start() { | ||
// started via TonKitManager | ||
} | ||
|
||
func stop() { | ||
// stopped via TonKitManager | ||
} | ||
|
||
func refresh() { | ||
// refreshed via TonKitManager | ||
} | ||
|
||
var statusInfo: [(String, Any)] { | ||
[] | ||
} | ||
|
||
var debugInfo: String { | ||
"" | ||
} | ||
} | ||
|
||
extension JettonAdapter: IBalanceAdapter { | ||
var balanceStateUpdatedObservable: Observable<AdapterState> { | ||
balanceStateSubject.asObservable() | ||
} | ||
|
||
var balanceData: BalanceData { | ||
BalanceData(available: Self.amount(jettonBalance: jettonBalance)) | ||
} | ||
|
||
var balanceDataUpdatedObservable: Observable<BalanceData> { | ||
jettonBalanceSubject.map { BalanceData(available: Self.amount(jettonBalance: $0)) } | ||
} | ||
} | ||
|
||
extension JettonAdapter: IDepositAdapter { | ||
var receiveAddress: DepositAddress { | ||
DepositAddress(tonKit.receiveAddress.toString(bounceable: false)) | ||
} | ||
} | ||
|
||
extension JettonAdapter: ISendTonAdapter { | ||
var availableBalance: Decimal { | ||
balanceData.available | ||
} | ||
|
||
func validate(address: String) throws { | ||
_ = try FriendlyAddress(string: address) | ||
} | ||
|
||
func estimateFee(recipient: String, amount: Decimal, comment: String?) async throws -> Decimal { | ||
guard let jettonBalance else { | ||
throw EstimateError.noWalletAddress | ||
} | ||
|
||
let recipient = try FriendlyAddress(string: recipient) | ||
let amount = Decimal(sign: .plus, exponent: jettonBalance.jetton.decimals, significand: amount).rounded(decimal: 0) | ||
|
||
guard let kitAmount = BigUInt(amount.description) else { | ||
throw AmountError.invalidAmount | ||
} | ||
|
||
let kitFee = try await tonKit.estimateFee(jettonWallet: jettonBalance.walletAddress, recipient: recipient, amount: kitAmount, comment: comment) | ||
|
||
return Self.amount(kitAmount: kitFee, decimals: jettonBalance.jetton.decimals) | ||
} | ||
|
||
func send(recipient: String, amount: Decimal, comment: String?) async throws { | ||
guard let jettonBalance else { | ||
throw EstimateError.noWalletAddress | ||
} | ||
|
||
let recipient = try FriendlyAddress(string: recipient) | ||
let amount = Decimal(sign: .plus, exponent: jettonBalance.jetton.decimals, significand: amount).rounded(decimal: 0) | ||
|
||
guard let kitAmount = BigUInt(amount.description) else { | ||
throw AmountError.invalidAmount | ||
} | ||
|
||
try await tonKit.send(jettonWallet: jettonBalance.walletAddress, recipient: recipient, amount: kitAmount, comment: comment) | ||
} | ||
} | ||
|
||
extension JettonAdapter { | ||
enum EstimateError: Error { | ||
case noWalletAddress | ||
} | ||
|
||
enum AmountError: Error { | ||
case invalidAmount | ||
} | ||
} |
Oops, something went wrong.